はじめに
電源を切ってもデータを保持したいと思ったことはありませんか?組み込みシステムでは、EEPROM(電気的消去・書き換え可能な読み出し専用メモリ)が不揮発性ストレージの定番です。今回は、Raspberry Pi Pico を使い、ブラウザ上の Velxio で I2C EEPROM の読み書きをシミュレーションします。ハードウェアは不要です!
EEPROM に数バイト書き込み、それを読み戻して一致するか確認します。その過程で、I2C プロトコル、Wire ライブラリ、シリアル出力のデバッグ方法について学びましょう。さっそく始めます!
回路の解説
Velxio でサンプルを開くと、キャンバス上に回路が表示されます。主な部品は以下の通りです:
- Raspberry Pi Pico(マイクロコントローラ)
- 赤色 LED(
led-writeと表示) – 書き込み操作中に点灯 - 緑色 LED(
led-readと表示) – 読み出し操作中に点灯

配線の詳細
| 接続元(Pico ピン) | 接続先(部品) | 配線色 |
|---|---|---|
| D12(GPIO12) | 赤色 LED アノード | 赤(#ff4444) |
| D10(GPIO10) | 緑色 LED アノード | 緑(#00cc00) |
| 赤色 LED カソード | GND.1 | 黒(#000000) |
| 緑色 LED カソード | GND.1 | 黒(#000000) |
注意: このシミュレーションでは、I2C EEPROM は仮想的なもので、Velxio 環境に組み込まれています。LED は視覚的なインジケータとして使用され、書き込み中は赤色 LED が点滅し、読み出し中は緑色 LED が点滅します。実際の回路では、EEPROM の SDA と SCL ラインを Pico の I2C ピン(デフォルトでは GPIO4 と GPIO5、ここでは LED 用に D12 と D10 を使用)に接続します。
コードの解説
Arduino スケッチを詳しく見ていきましょう。このコードは Wire ライブラリを使って I2C 通信を行います。
インクルードと定義
#include <Wire.h>
#define EEPROM_ADDR 0x50
Wire ライブラリをインクルードし、EEPROM の I2C アドレスを 0x50 と定義します。これは 24LC シリーズ EEPROM で一般的なアドレスです。
ヘルパー関数
void eepromWrite(byte memAddr, byte data) {
Wire.beginTransmission(EEPROM_ADDR);
Wire.write(memAddr);
Wire.write(data);
Wire.endTransmission();
delay(5); // EEPROM 書き込みサイクル
}
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:メモリアドレスに続いてデータバイトを送信します。delay(5)は EEPROM の内部書き込みサイクル(通常 5 ms)をシミュレートしています。eepromRead:最初にメモリアドレスを送信(「ダミー書き込み」)、その後 EEPROM から 1 バイトを要求します。データがあればそのバイトを、なければ0xFFを返します。
セットアップ
void setup() {
Serial.begin(115200);
delay(500);
Wire.begin();
Serial.println("=== Pico I2C EEPROM Test ===");
Serial.println();
// 8 バイト書き込み
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();
// 読み戻し
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");
}
- シリアル通信を 115200 ボーで初期化し、
Wire.begin()で I2C バスを開始します。 - アドレス 0~7 に 8 バイト(
0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE)を書き込みます。 - 各アドレスを読み戻し、元のデータと比較します。「OK」または「FAIL」を表示します。
- 最後に合格したテストの数を表示します。
ループ
void loop() {
delay(10000);
}
繰り返し処理は不要です。テストは setup() 内で一度だけ実行されます。ループはシリアル出力を表示し続けるための遅延です。
重要な概念
- I2C プロトコル:マイクロコントローラと周辺機器間の通信用 2 線式シリアルバス(SDA、SCL)。各デバイスは固有のアドレスを持ちます。
- Wire ライブラリ:Arduino に組み込まれた I2C 用ライブラリ。
beginTransmission()、write()、endTransmission()、requestFrom()、read()が主要な関数です。 - EEPROM アドレッシング:EEPROM はメモリバンクで構成されています。データの前にメモリアドレスバイトを書き込みます。
- 書き込みサイクルの遅延:EEPROM はデータを保存するのに数ミリ秒必要です。
delay(5)により、次の操作の前に書き込みが完了します。
よくある落とし穴とデバッグのコツ
- I2C アドレスの間違い:EEPROM のアドレスを再確認してください。一般的なアドレスは
0x50から0x57です(A0/A1/A2 ピンに依存)。 - プルアップ抵抗の欠落:実際のハードウェアでは、SDA と SCL にプルアップ抵抗(4.7kΩ)が必要です。Velxio の仮想 EEPROM は内部でこれを処理します。
- シリアルモニタのボーレート:シリアルモニタを 115200 ボーに設定してください。不一致だと文字化けが発生します。
- 書き込みサイクルのタイミング:
delay(5)を省略すると、EEPROM が正しくデータを保存できない可能性があります。必要に応じて遅延を増やしてください。 - LED が点滅しない:配線を確認してください。赤色 LED は D12、緑色 LED は D10 に接続されています。両方のカソードは GND に接続します。
発展の提案
- センサーデータの保存と取得:温度センサーを読み取り、最後の値を EEPROM に保存します。
- ボタンの追加:プッシュボタンを使って読み取りや書き込みをトリガーします。
- 256 バイトへの拡張:より大きなデータブロックを書き込むようにコードを変更します。
- 設定用 EEPROM:キャリブレーション値やユーザー設定を保存します。
実際に試してみよう!
実験の準備はできましたか?Velxio でライブサンプルを開いてください:
エディタツールバーの Run ボタンをクリックしてコンパイルとシミュレーションを実行します。コンソールのシリアル出力を確認してください。8 バイトすべてが正常に読み戻されるはずです。

キャンバスツールバーを使って、ズーム、パン、回路の検査を行ってください。

さらに部品を追加する必要がありますか?部品ピッカーを開いてパーツを参照してください。

それでは、楽しいシミュレーションを!