はじめに
I2C(Inter-Integrated Circuit)は、マイクロコントローラがセンサー、ディスプレイ、その他の周辺機器とわずか2本の配線(SDA(データ)とSCL(クロック))で通信できる、人気のある通信プロトコルです。しかし、プロトタイピング中は、新しいI2Cデバイスの正確なアドレスがわからないことがよくあります。そんなときに便利なのがI2Cスキャナーです。バス上のすべての可能なアドレスをプローブし、応答があったものを報告します。
このチュートリアルでは、Velxio のブラウザ内シミュレーターを使用して、Raspberry Pi Pico 用のI2Cスキャナーを構築します。2つのインジケーターLEDを使った簡単な回路の配線方法、Arduino C++でのスキャンコードの書き方、結果の解釈方法を学びます。ハードウェアは不要で、ブラウザだけでOKです!

回路の解説
私たちの回路は最小限ですが、教育的です。スキャン中に視覚的なフィードバックを与えるために、2つのLEDを使用します。
- 青色LED (led-scan):電流制限抵抗(LEDコンポーネント内蔵)を介して GP12(PicoのD12)に接続します。アノード(A)はGP12に、カソード(C)はグランドに接続します。このLEDは、スキャナーがI2Cバスにスタートコンディションを送信するたびに点滅します。
- 緑色LED (led-found):GP10(D10)に接続します。アノードはGP10に、カソードはグランドに接続します。このLEDは、スキャン中にデバイスが見つかるたびに点灯します。
両方のLEDは、PicoのGND.1ピンへの共通グランド接続を共有します。I2Cバス自体はデフォルトのピン SDA = GP4 と SCL = GP5 を使用します。WireライブラリによってPicoの内部プルアップが有効になるため、外部プルアップ抵抗は必要ありません。
Velxioでこの回路を構築するには:
- キャンバスツールバーから コンポーネントピッカー を開きます。

- Raspberry Pi Pico ボードを追加します。
- 出力カテゴリから2つのLED(青と緑)を追加します。
- 説明の通りに配線します:GP12 → 青色LEDアノード、GP10 → 緑色LEDアノード、両方のカソード → GND。
- キャンバスツールバー を使用して、コンポーネントをズームおよび整列させます。

コードの解説
それではコードを見ていきましょう。Velxioでコードエディターを開き、次のスケッチを貼り付けます:
// Raspberry Pi Pico — I2C Scanner
// Scans I2C bus (Wire / I2C0: SDA=GP4, SCL=GP5) for devices
#include <Wire.h>
void setup() {
Serial.begin(115200);
delay(500);
Wire.begin(); // SDA=GP4, SCL=GP5 by default on Pico
Serial.println("=== Pico I2C Scanner ===");
Serial.println("Default I2C0: SDA=GP4, SCL=GP5");
Serial.println();
}
void loop() {
Serial.println("Scanning I2C bus...");
int found = 0;
for (byte addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
byte error = Wire.endTransmission();
if (error == 0) {
found++;
Serial.print(" Device found at 0x");
if (addr < 16) Serial.print("0");
Serial.print(addr, HEX);
// Identify known addresses
switch (addr) {
case 0x48: Serial.print(" (Temperature sensor)"); break;
case 0x50: Serial.print(" (EEPROM)"); break;
case 0x68: Serial.print(" (DS1307 RTC)"); break;
case 0x27: Serial.print(" (LCD backpack)"); break;
case 0x3C: Serial.print(" (SSD1306 OLED)"); break;
default: break;
}
Serial.println();
}
}
Serial.print("Scan complete. Found ");
Serial.print(found);
Serial.println(" device(s).");
Serial.println();
delay(5000);
}
仕組み
Wire.begin()は、デフォルトのピン(GP4/GP5)でI2Cペリフェラルを初期化します。Picoでは、これによりI2C0がセットアップされます。forループ は、1から127までのすべての可能な7ビットアドレスを反復処理します。アドレス0は一般呼び出し用に予約されているため、スキップします。- 各アドレスに対して、
Wire.beginTransmission(addr)を呼び出し、次にWire.endTransmission()を呼び出します。endTransmission()の戻り値は、デバイスが応答した場合は0、それ以外の場合は0以外のエラーコードです。 - デバイスが応答した場合、そのアドレスを16進数形式で出力します。コードには、いくつかの一般的なアドレス(例:SSD1306 OLEDディスプレイ用の0x3C)にラベルを付ける switch 文 も含まれています。
- GP12の青色LED は、スキャンサイクルが開始されるたびにトグルします(視覚的なフィードバックのために、スキャンループの前後に
digitalWrite(12, HIGH)とdigitalWrite(12, LOW)を追加できます)。GP10の緑色LED は、デバイスが見つかったときに点灯します。
コンパイルして実行するには、エディターツールバーの コンパイル ボタンをクリックします。

主要な概念
- I2C プロトコル:マルチマスター、マルチスレーブ、パケット交換、シングルエンド、シリアル通信バス。各デバイスは固有のアドレスを持ちます。
- Wire ライブラリ:I2C通信用のArduino組み込みライブラリ。Picoでは、デフォルトでI2C0を使用します。
- プルアップ抵抗:I2CラインにはVCCへのプルアップ抵抗が必要です。Picoには有効にできる内部プルアップがありますが、多くのデバイスで信頼性の高い動作を行うには、外部の4.7kΩ抵抗が推奨されます。
- アドレッシング:7ビットアドレスは0x01から0x7F(127)の範囲です。一部のアドレスは予約されています(例:一般呼び出し用の0x00)。
よくある落とし穴とデバッグのヒント
- デバイスが見つからない? I2Cデバイスに電源が供給され、正しく接続されていることを確認してください。シミュレーションでは、回路に仮想I2Cペリフェラル(OLEDや温度センサーなど)を追加したことを確認してください。
- ピンが間違っている? PicoのデフォルトのI2C0ピンはGP4(SDA)とGP5(SCL)です。異なるピンを使用する場合は、
Wire.begin()の前にWire.setSDA(pin)とWire.setSCL(pin)を呼び出してください。 - シリアルモニターに出力が表示されない? ボーレートが一致していることを確認してください(コードでは115200)。Velxioでは、ツールバーからシリアルモニターを開きます。
- LEDが点滅しない? 配線を確認してください:アノードをGPIOに、カソードをGNDに接続します。また、
setup()でpinMode(12, OUTPUT)とpinMode(10, OUTPUT)を使用してピンを出力として設定していることを確認してください。
推奨される拡張機能
- 実際のI2Cデバイスを追加する:キャンバスにSSD1306 OLEDやBMP280センサーを配置し、スキャナーがそれを検出するのを確認します。
- 複数のバスをスキャンする:Picoには2つのI2Cペリフェラル(I2C0とI2C1)があります。両方をスキャンするようにコードを変更します。
- 結果をLCDに表示する:シリアルではなく、見つかったアドレスを16x2 LCDに表示します。
- 自動検出と設定:デバイスのアドレスがわかったら、そのライブラリを自動的に初期化します。
自分で試してみよう!
I2Cバスをスキャンする準備はできましたか?Velxioでライブサンプルを開いて、実験を始めましょう:
ダウンロードもはんだ付けも不要、純粋なシミュレーションだけです。コードを変更し、新しいコンポーネントを追加して、結果を即座に確認できます。ハッピースキャニング!