I2C で OLED に表示する2 本の線で小さな画面をつなぎ、センサーの値を出す
センサーの値を PC のシリアルモニタではなく、その場で見たい。0.96 インチの OLED(SSD1306)は 4 本の線(電源 2 本 + I2C の 2 本)でつながり、数百円で買えます。I2C は温湿度センサーや ADC モジュールもつなぐ規格なので、ここで覚えると一気に世界が広がります。
- ESP32-S3
- Raspberry Pi 5 8GB
- M5Stack CoreS3
CONTENTSこの記事の目次+
01 — I2C
I2C とは
SDA(データ)とSCL(クロック)の2本を全員で共有し、7bitアドレス(OLEDは0x3Cなど)で呼び分けます。デバイスが増えても線の数は増えません。
- 2 本の線:SDA(データ)と SCL(クロック)。それに VCC と GND
- 1 組の線に複数のデバイスをぶら下げられる。それぞれ 7bit のアドレスを持つ(OLED は 0x3C が多い)
- マイコンが「マスター」、センサーや表示器が「ターゲット」。マスターがアドレスを呼んで読み書きする
- 速度は 100kHz(標準)か 400kHz。配線は数十 cm まで
- SDA / SCL にはプルアップ抵抗が必要。モジュールにはたいてい載っている(4.7kΩ〜10kΩ)
02 — WIRING
配線
| OLED のピン | ESP32-S3 | Raspberry Pi 5 | CoreS3(Port A) |
|---|---|---|---|
| VCC | 3V3 | 物理 1(3.3V) | Grove 赤(5V。モジュールが 5V 対応か確認) |
| GND | GND | 物理 6 | Grove 黒 |
| SCL | GPIO9 | GPIO3(物理 5) | G1(Grove 黄) |
| SDA | GPIO8 | GPIO2(物理 3) | G2(Grove 白) |
I2C は「SDA 同士、SCL 同士」をつなぎます。UART のように交差させません。ESP32-S3 の GPIO8 / 9 は Arduino の Wire.begin() が既定で使うピンです。
03 — SCAN
まずアドレスを確認する
#include <Wire.h>
void setup() {
Serial.begin(115200);
Wire.begin(); // ESP32-S3: SDA=GPIO8, SCL=GPIO9
for (uint8_t addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) {
Serial.printf("found: 0x%02X\n", addr);
}
}
}
void loop() {}Raspberry Pi 5 では sudo raspi-config → Interface Options → I2C を有効にしてから、i2cdetect -y 1 で表が出ます。3c が見えれば OK です。
何も見つからないときは、SDA と SCL が逆、VCC が来ていない、プルアップがない、のどれかです。
04 — DISPLAY
文字を出す(Adafruit SSD1306)
ライブラリマネージャで「Adafruit SSD1306」を入れます(Adafruit GFX も一緒に入ります)。
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 display(128, 64, &Wire);
void setup() {
Wire.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // スキャンで見えたアドレス
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Hello");
display.display(); // ここで初めて画面に反映
}
void loop() {}display.display()を呼ぶまで画面は変わらない(描画はメモリ上で行われる)- 数値を出すなら
display.print(value)。更新するときはclearDisplay()→ 描画 →display() - 128×32 のモジュールなら高さを 32 にする
- Raspberry Pi 5 では Python の
luma.oledライブラリ。準備が多いので、まずは ESP32 で試すのがおすすめ
05 — SENSOR → DISPLAY
センサーの値を表示する
void loop() {
int light = analogRead(2); // CdS(→ ADC でセンサーを読む)
display.clearDisplay();
display.setCursor(0, 0);
display.print("Light");
display.setCursor(0, 32);
display.print(light);
display.display();
delay(200);
}これで PC なしで動く「測定器」になります。CoreS3 なら OLED は不要で、M5.Display に同じように出せます。
06 — WATCH OUT
注意点
同じアドレスのデバイスは 1 本の I2C 線に 2 つつなげません(OLED 2 枚など)。アドレス変更ジャンパか、もう 1 組の I2C(Wire1)を使います。
5V 専用の I2C モジュールを 3.3V の SDA / SCL に直結しないようにします。大抵は 3.3V 対応ですが、確認します。
数十 cm を超えると通信エラーが増えます。速度を 100kHz に落とすか、配線を短くします。
07 — CHECK YOURSELF
理解チェック
Q1I2C の 2 本の線の名前と役割は?答えを見る
SDA(データ)と SCL(クロック)。
Q2OLED に print したのに何も出ない。よくある原因は?答えを見る
display.display() を呼んでいない。またはアドレスが 0x3C ではない(スキャンで確認)。
