The first byte
Four wires and a sketch that counts how many times your board has started. It reads one byte at address 0, adds one, writes it back, and prints it. Unplug the board, plug it in again, and the count carries on: the byte survived the power going off.
Four wires
GND to GND. VCC to your board's logic supply: 5V on an Uno, 3V3 on the others. SDA and SCL to your board's I2C pins: A4 and A5 on an Uno, GPIO 21 and 22 on an ESP32, GPIO 8 and 9 on an ESP32-S3, GP4 and GP5 on a Pico.
Those are each board's default I2C pins, so Wire.begin() needs nothing in
its brackets. They are the same pins the SHT31 book uses, so two I2C blocks
share the same four wires.
The sketch
readByte sends 0x50, the two address bytes and a repeated start, then asks
for one byte. writeByte sends 0x50, the two address bytes and the value,
then waits 5 ms. Those are the two transactions from two wires and an
address, in about
ten lines each.
setup() reads byte 0, adds one and writes it back. A chip that has never
been written usually reads 255, so the sketch treats 255 as zero.
What you should see
At 115200 the serial monitor prints:
Started 1 times. Unplug it, plug it back in.Unplug the board, plug it back in, and it says 2, then 3. The number was on
the TK31 while the power was off. If it says no answer at 0x50, the chip did
not acknowledge: check the four wires, counting from the square pad.
The code
No library to install: Wire comes with every board. readByte and writeByte are the two transactions from the last chapter, written out. Change nothing but the wiring.
/*
EEPROM Memory - boot counter TK31 / /p/tk31
Wiring. Count from the square pad on the TinkerBlock board, parts
up, header at the bottom:
GND -> GND
VCC -> your board's logic supply: 5V on an Uno, 3V3 on an
ESP32 or ESP32-S3, 3V3(OUT) on a Pico. Never 5V beside
a 3.3 V board: the pull-ups would put 5 V on its pins.
SDA -> A4 on an Uno, GPIO 21 on an ESP32, GPIO 8 on an
ESP32-S3, GP4 on a Raspberry Pi Pico
SCL -> A5 on an Uno, GPIO 22 on an ESP32, GPIO 9 on an
ESP32-S3, GP5 on a Raspberry Pi Pico
Arduino IDE
Tools > Board your board, e.g. Arduino Uno
Tools > Port the one that appears when you plug in
Tools > USB CDC On Boot Enabled (ESP32-S3 only)
No library to install: Wire comes with every board.
*/
#include <Wire.h>
const int EEPROM_ADDR = 0x50; // fixed: A0 to A2 are tied to GND
const uint16_t COUNT_AT = 0; // the byte that holds the count
// Returns true if the chip acknowledged every byte.
bool writeByte(uint16_t at, uint8_t value) {
Wire.beginTransmission(EEPROM_ADDR);
Wire.write((uint8_t)(at >> 8)); // memory address, high byte
Wire.write((uint8_t)(at & 0xFF)); // then the low byte
Wire.write(value);
bool ok = Wire.endTransmission() == 0; // the stop starts the write
delay(5); // up to 5 ms, answering nobody
return ok;
}
int readByte(uint16_t at) {
Wire.beginTransmission(EEPROM_ADDR);
Wire.write((uint8_t)(at >> 8));
Wire.write((uint8_t)(at & 0xFF));
if (Wire.endTransmission(false) != 0) return -1; // no answer
Wire.requestFrom(EEPROM_ADDR, 1); // repeated start, then read
return Wire.available() ? Wire.read() : -1;
}
void setup() {
Serial.begin(115200);
delay(1000); // time for the monitor to open
Wire.begin(); // the board's default I2C pins
int count = readByte(COUNT_AT);
if (count < 0) {
Serial.println("no answer at 0x50: check the four wires");
return;
}
if (count == 255) count = 0; // a byte never written
count++;
writeByte(COUNT_AT, count);
Serial.print("Started ");
Serial.print(count);
Serial.println(" times. Unplug it, plug it back in.");
}
void loop() {
}writeByte waits 5 ms after every write, because the chip answers nobody while it writes. This is not the Arduino EEPROM library: EEPROM.h would read the memory inside your microcontroller, not this chip.
The same counter in MicroPython, for an ESP32, an ESP32-S3 or a Pico. readfrom_mem and writeto_mem do the transactions, and addrsize=16 makes them send the two address bytes this chip needs.
"""
EEPROM Memory - boot counter, MicroPython TK31 / /p/tk31
Wiring. Count from the square pad on the TinkerBlock board, parts
up, header at the bottom:
GND -> GND
VCC -> 3V3 on an ESP32 or ESP32-S3, 3V3(OUT) on a Pico.
Never 5V: the pull-ups would put 5 V on your pins.
SDA -> GPIO 21 on an ESP32, GPIO 8 on an ESP32-S3,
GP4 on a Raspberry Pi Pico
SCL -> GPIO 22 on an ESP32, GPIO 9 on an ESP32-S3,
GP5 on a Raspberry Pi Pico
Thonny
Run > Configure interpreter MicroPython (ESP32) or
MicroPython (Raspberry Pi Pico)
Save it to the board as main.py to count real power-ups.
Nothing to install: machine and time are built in.
"""
import time
from machine import I2C, Pin
# SDA, SCL. ESP32: 21, 22. ESP32-S3: 8, 9. Pico: 4, 5.
i2c = I2C(0, sda=Pin(21), scl=Pin(22), freq=100_000)
EEPROM = 0x50 # fixed: A0 to A2 are tied to GND
COUNT_AT = 0 # the byte that holds the count
count = i2c.readfrom_mem(EEPROM, COUNT_AT, 1, addrsize=16)[0]
if count == 255: # a byte never written
count = 0
count += 1
i2c.writeto_mem(EEPROM, COUNT_AT, bytes([count]), addrsize=16)
time.sleep_ms(5) # up to 5 ms, answering nobody
print("Started", count, "times. Unplug it, plug it back in.")There is no Uno here: an Uno cannot run MicroPython. Without addrsize=16 MicroPython sends one address byte, which is right for a small chip and wrong for this one: the reads come from somewhere else and the writes land somewhere else.
When it does not work
That is right. An unwritten chip usually reads 255 at every address, and the sketch treats 255 as never started, so the first start counts as 1. After 255 starts the one byte is full and the count goes back to 1.
Opening the serial monitor resets an Uno, and a reset is a start. The count is doing its job. Unplug the USB cable and plug it back in to see the power-off case.
The chip did not acknowledge. Count from the square pad: GND, VCC, SDA, SCL, and check SDA and SCL are not swapped. Then check VCC is on your board's logic supply and actually connected.
Set Tools > USB CDC On Boot to Enabled and upload again. Without it the S3's USB port does not bring up a serial port at boot, so the sketch runs with nowhere to print.
Edit this page — content/books/eeprom-memory/the-first-byte.mdx
Questions about this product
See what other owners have asked, and read their solutions.
EEPROM Memory
Loading discussions…
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.