Introduction
Have you ever wanted to store data that survives a power cycle? In embedded systems, EEPROM (Electrically Erasable Programmable Read-Only Memory) is the go‑to for non‑volatile storage. Today, we’ll simulate an I2C EEPROM read/write operation using the Raspberry Pi Pico—all inside your browser with Velxio. No hardware required!
We’ll write a few bytes to the EEPROM, read them back, and verify they match. Along the way, you’ll learn about the I2C protocol, the Wire library, and how to debug serial output. Let’s dive in!
Circuit Walkthrough
Open the example in Velxio and you’ll see the circuit on the canvas. The main components are:
- Raspberry Pi Pico (the microcontroller)
- Red LED (labeled
led-write) – lights up during a write operation - Green LED (labeled
led-read) – lights up during a read operation

Wiring Details
| From (Pico pin) | To (Component) | Wire Color |
|---|---|---|
| D12 (GPIO12) | Red LED anode | Red (#ff4444) |
| D10 (GPIO10) | Green LED anode | Green (#00cc00) |
| Red LED cathode | GND.1 | Black (#000000) |
| Green LED cathode | GND.1 | Black (#000000) |
Note: In this simulation, the I2C EEPROM is virtual—it’s built into the Velxio environment. The LEDs are used as visual indicators: the red LED blinks during a write, the green LED during a read. In a real circuit, you’d connect the EEPROM’s SDA and SCL lines to the Pico’s I2C pins (GPIO4 and GPIO5 by default, but here we use D12 and D10 for the LEDs).
Code Walkthrough
Let’s break down the Arduino sketch. The code uses the Wire library to communicate over I2C.
Includes and Definitions
#include <Wire.h>
#define EEPROM_ADDR 0x50
We include the Wire library and define the EEPROM’s I2C address as 0x50. This is a common address for 24LC series EEPROMs.
Helper Functions
void eepromWrite(byte memAddr, byte data) {
Wire.beginTransmission(EEPROM_ADDR);
Wire.write(memAddr);
Wire.write(data);
Wire.endTransmission();
delay(5); // EEPROM write cycle
}
byte eepromRead(byte memAddr) {
Wire.beginTransmission(EEPROM_ADDR);
Wire.write(memAddr);
Wire.endTransmission();
Wire.requestFrom(EEPROM_ADDR, 1);
return Wire.available() ? Wire.read() : 0xFF;
}
eepromWrite: Sends the memory address followed by the data byte. Thedelay(5)simulates the EEPROM’s internal write cycle (typically 5 ms).eepromRead: First sends the memory address (a “dummy write”), then requests one byte from the EEPROM. Returns the byte or0xFFif nothing available.
Setup
void setup() {
Serial.begin(115200);
delay(500);
Wire.begin();
Serial.println("=== Pico I2C EEPROM Test ===");
Serial.println();
// Write 8 bytes
Serial.println("Writing 8 bytes...");
byte testData[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE};
for (int i = 0; i < 8; i++) {
eepromWrite(i, testData[i]);
Serial.print(" ["); Serial.print(i);
Serial.print("] = 0x");
if (testData[i] < 16) Serial.print('0');
Serial.println(testData[i], HEX);
}
Serial.println();
// Read back
Serial.println("Reading back...");
int pass = 0;
for (int i = 0; i < 8; i++) {
byte val = eepromRead(i);
Serial.print(" ["); Serial.print(i);
Serial.print("] = 0x");
if (val < 16) Serial.print('0');
Serial.print(val, HEX);
if (val == testData[i]) {
Serial.println(" OK");
pass++;
} else {
Serial.print(" FAIL (expected 0x");
Serial.print(testData[i], HEX);
Serial.println(")");
}
}
Serial.println();
Serial.print("Result: ");
Serial.print(pass);
Serial.println("/8 passed");
}
- Initializes serial at 115200 baud and the I2C bus with
Wire.begin(). - Writes 8 bytes (
0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE) to addresses 0–7. - Reads back each address and compares with the original data. Prints “OK” or “FAIL”.
- Finally prints the number of passed tests.
Loop
void loop() {
delay(10000);
}
Nothing to do repeatedly—the test runs once in setup(). The loop just delays to keep the serial output visible.
Key Concepts
- I2C Protocol: A two‑wire serial bus (SDA, SCL) for communication between microcontrollers and peripherals. Each device has a unique address.
- Wire Library: Arduino’s built‑in library for I2C.
beginTransmission(),write(),endTransmission(),requestFrom(), andread()are the core functions. - EEPROM Addressing: EEPROMs are organized in memory banks. We write a memory address byte before the data.
- Write Cycle Delay: EEPROMs need a few milliseconds to store data. The
delay(5)ensures the write completes before the next operation.
Common Pitfalls & Debugging Tips
- Wrong I2C Address: Double‑check the EEPROM address. Common addresses are
0x50to0x57(depending on A0/A1/A2 pins). - Missing Pull‑up Resistors: In real hardware, SDA and SCL need pull‑up resistors (4.7kΩ). Velxio’s virtual EEPROM handles this internally.
- Serial Monitor Baud Rate: Ensure the serial monitor is set to 115200 baud. Mismatch causes gibberish.
- Write Cycle Timing: If you skip the
delay(5), the EEPROM may not store the data correctly. Increase the delay if needed. - LEDs Not Blinking: Check the wiring. The red LED is connected to D12, green to D10. Both cathodes go to GND.
Suggested Extensions
- Store and retrieve sensor data: Read a temperature sensor and save the last value to EEPROM.
- Add a button: Use a push button to trigger a read or write.
- Expand to 256 bytes: Modify the code to write a larger block of data.
- Use the EEPROM for configuration: Store calibration values or user settings.
Try It Yourself!
Ready to experiment? Open the live example in Velxio:
Click the Run button in the editor toolbar to compile and simulate. Watch the serial output in the console—you should see all 8 bytes read back successfully.

Use the canvas toolbar to zoom, pan, and inspect the circuit.

Need to add more components? Open the component picker to browse parts.

Happy simulating!