はじめに
Pico マルチプロトコルデモへようこそ!このチュートリアルでは、Raspberry Pi Pico (RP2040) を使用して、シリアル、I2C、SPI、ADC の複数のプロトコルを同時に通信する方法を学びます。これは、組み込み開発に必要な複数の主要スキルを統合した高度な例です。Velxio シミュレータで回路を構築し、コードを書き、各部分をステップバイステップで解説します。

回路の解説
コンポーネントと配線を見てみましょう。この回路は、Raspberry Pi Pico (Nano RP2040 Connect) といくつかの周辺機器を使用しています。
- 青色 LED (led-i2c): 電流制限抵抗を介してピン D12 (GP12) に接続。アノード (A) は D12 に、カソード (C) は GND に接続。
- 黄色 LED (led-spi): 同様にピン D7 (GP7) に接続。
- ポテンショメータ (pot-adc): 信号ピン (SIG) は A0 (GP26) に接続。VCC は 3.3V に、GND は GND に接続。
- 緑色 LED (led-gpio): ピン D2 (GP2) に接続。
すべての LED は共通のグランドを共有しています。ポテンショメータは 3.3V レールから電源を供給されます。配線は簡単ですが、Pico の内蔵 I2C および SPI ペリフェラルを使用していることに注意してください(回路図には明示的に示されていませんが、コードはデフォルトのピンで利用可能であると想定しています)。
コードの解説
コードは Arduino C++ で書かれており、Wire ライブラリと SPI ライブラリを使用しています。セクションごとに詳しく見ていきましょう。
セットアップ
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
delay(500);
Serial.println("==============================");
Serial.println(" Pico Multi-Protocol Demo");
Serial.println("==============================");
Serial.println();
まず、内蔵 LED とシリアルを 115200 ボー で初期化します。delay により、シリアルモニタが接続する時間を確保します。
1. I2C スキャナ
Wire.begin();
Serial.println("[I2C] Scanning bus...");
int found = 0;
for (byte addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) {
found++;
Serial.print(" Found device at 0x");
if (addr < 16) Serial.print('0');
Serial.println(addr, HEX);
}
}
Serial.print(" Total devices: "); Serial.println(found);
Serial.println();
これは、すべての可能な I2C アドレス (1-126) をスキャンし、応答があったものを報告します。シミュレータでは、0x50 (EEPROM) や 0x68 (RTC) などのアドレスに仮想デバイスが表示される場合があります。
2. I2C EEPROM 読み書き
Serial.println("[I2C] EEPROM test at 0x50...");
Wire.beginTransmission(0x50);
Wire.write(0x00); // register 0
Wire.write(0x42); // data
Wire.endTransmission();
delay(5);
Wire.beginTransmission(0x50);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom(0x50, 1);
if (Wire.available()) {
byte val = Wire.read();
Serial.print(" Wrote 0x42, Read 0x");
Serial.print(val, HEX);
Serial.println(val == 0x42 ? " — OK" : " — FAIL");
}
Serial.println();
アドレス 0x50 の EEPROM のレジスタ 0 に値 0x42 を書き込み、それを読み戻して検証します。これにより、基本的な I2C 読み書きをテストします。
3. I2C RTC
Serial.println("[I2C] Reading DS1307 RTC at 0x68...");
Wire.beginTransmission(0x68);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom(0x68, 3);
if (Wire.available() >= 3) {
byte sec = ((Wire.read() & 0x7F) >> 4) * 10 + (Wire.read() & 0x0F);
byte min2 = Wire.read();
(void)sec; (void)min2;
Serial.println(" RTC responded OK");
}
Serial.println();
ここでは、アドレス 0x68 の DS1307 RTC から時刻レジスタを読み取ろうとします。コードは 3 バイト(秒、分、時)を読み取りますが、デバイスが応答したかどうかのみを確認します。
4. SPI ループバック
Serial.println("[SPI] Loopback test...");
SPI.begin();
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
byte tx = 0xAB;
byte rx = SPI.transfer(tx);
Serial.print(" TX: 0x"); Serial.print(tx, HEX);
Serial.print(" RX: 0x"); Serial.println(rx, HEX);
SPI.endTransaction();
Serial.println();
これは単純な SPI ループバックを実行します。0xAB を送信し、受信した値を読み戻します。シミュレータでは、MISO と MOSI が外部で接続されていないため、受信値は 0xFF または他の値になる可能性があります。これにより、SPI ハードウェアをテストします。
5. ADC
Serial.println("[ADC] Reading analog channels...");
analogReadResolution(12);
int a0 = analogRead(A0);
Serial.print(" A0 (GP26): "); Serial.println(a0);
Serial.println();
ADC の解像度を 12 ビット に設定し、A0 (GP26) から値を読み取ります。ポテンショメータのワイパー電圧が読み取られ、0 から 4095 の間の値が得られます。
6. GPIO 点滅
Serial.println("[GPIO] Blinking LED...");
for (int i = 0; i < 3; i++) {
digitalWrite(LED_BUILTIN, HIGH);
delay(200);
digitalWrite(LED_BUILTIN, LOW);
delay(200);
}
Serial.println(" 3 blinks done");
Serial.println();
Serial.println("=== All protocol tests complete ===");
}
最後に、内蔵 LED を 3 回点滅させて、セットアップが完了したことを示します。
ループ
void loop() {
// Heartbeat
static unsigned long last = 0;
if (millis() - last >= 3000) {
last = millis();
Serial.print("[Heartbeat] ");
Serial.print(millis() / 1000);
Serial.println("s");
}
}
ループは 3 秒 ごとにハートビートメッセージを出力し、プログラムが実行中であることを示します。
主要な概念
- マルチプロトコル統合: シリアル、I2C、SPI、ADC を 1 つのスケッチに組み合わせることで、競合なく複数のペリフェラルを管理する方法を学べます。
- I2C アドレッシング: 特定のアドレスでデバイスをスキャンし通信する方法の理解。
- SPI 設定: クロック速度、ビット順序、モードの設定。
- ADC 解像度:
analogReadResolution()を使用してより高い精度を得る方法。 - シリアルデバッグ: シリアルモニタを使用してリアルタイムデータを出力する方法。
よくある落とし穴とデバッグのヒント
- I2C プルアップ抵抗: Pico には内部プルアップがありますが、長い配線には外部プルアップが必要な場合があります。シミュレータでは自動的に処理されます。
- SPI ループバック: 物理的なループバックがない場合、受信データはゴミになる可能性があります。実際のループバックテストには、MOSI と MISO の間にジャンパ線を使用してください。
- ADC ノイズ: ポテンショメータはノイズが発生する可能性があります。ワイパーとグランドの間にコンデンサを追加すると効果的です。
- シリアルボーレートの不一致: シリアルモニタが 115200 ボー に設定されていることを確認してください。
推奨拡張機能
- 外部 I2C センサー(例:温度/湿度)を追加し、その読み取り値を表示する。
- SPI を使用して OLED ディスプレイを制御する。
- ADC を読み取り、値を EEPROM に保存するシンプルなデータロガーを実装する。
- ボタンを追加して、異なるテストモードをトリガーする。
自分で試してみよう!
実験する準備はできましたか?Velxio でライブサンプルを開き、シミュレーションを実行してください。コードを変更したり、コンポーネントを追加したり、結果を即座に確認できます。



ハッピーハッキング!