OLEDディスプレイ(SSD1306)の使い方:Arduinoで文字、図形、グラフィックを描く
0.96インチのI2C OLEDディスプレイ(SSD1306)の使い方は?配線とI2Cアドレス(0x3C)、Adafruit SSD1306とGFXライブラリ、文字・図形・センサー値・ビットマップの描画、ESP32とPicoのMicroPythonのコードを解説します。
指先ほどの大きさしかありませんが、0.96インチのOLEDディスプレイは128×64ピクセルのくっきりした画像を表示でき、Arduinoのプロジェクトでとくに人気のディスプレイです。文字表示のLCDと違い、文字だけでなく線、円、アイコン、グラフ、さらには小さなゲームまで描けます。スマートウォッチ、気象観測所、リモコン、携帯型の測定器にぴったりです。これらのディスプレイのほとんどはSSD1306というドライバチップを使い、2本のデータ線(I2C)だけでつながります。

OLEDとは?LCDとの違い
OLED(Organic Light Emitting Diode:有機EL)ディスプレイでは、各ピクセルが自ら光を出し、バックライトはありません。そのため黒い部分は本当に黒く、コントラストがとても高く、どの角度から見てもくっきりしていて、画像の大部分が暗いときは消費電力もごくわずかです。128×64のピクセルで、文字ベースのLCDでは表示できないグラフィック、アイコン、絵を描けます。
| 項目 | 0.96インチOLED | 0.91インチOLED | 16x2 LCD |
|---|---|---|---|
| 解像度 | 128×64ピクセル | 128×32ピクセル | 16×2文字 |
| グラフィックとアイコン | 可能 | 可能 | 不可(文字のみ) |
| バックライト | 不要 | 不要 | 必要 |
| 接続 | I2C(SPI版もあり) | I2C | I2Cモジュールで4本の線 |
| 日光の下では | 読みにくい | 読みにくい | 比較的読みやすい |
仕様
| 項目 | 値 |
|---|---|
| ドライバチップ | SSD1306 |
| 画面 | 0.96インチ 128×64(0.91インチ版は128×32) |
| 色 | モノクロ:白、青、または上部が黄色で下部が青 |
| 電源 | 3.3〜5 V(基板にレギュレーターあり) |
| 電流 | 約10〜25 mA(点灯しているピクセル数による) |
| I2Cアドレス | 0x3C(一部のモデルは0x3D) |
| ピン | GND、VCC、SCL、SDA |
OLEDディスプレイの配線
| OLEDのピン | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| GND | GND | GND | GND |
| VCC | 5Vまたは3.3V | 3V3 | 3V3 |
| SCL | A5 | GPIO 22 | GP5 |
| SDA | A4 | GPIO 21 | GP4 |
2色のモデルでは、画面の上の16行が黄色、残りが青に光ります。この色はソフトウェアでは変えられないので、上の部分をタイトルバーのようにデザインするときれいに見えます。ディスプレイのアドレスがわからない場合は、I2C LCDディスプレイの使い方にあるI2Cスキャナースケッチを使ってください。
ライブラリのインストール
- Arduino IDEでライブラリマネージャを開き、Adafruit SSD1306を検索します。
- インストール中に依存関係について聞かれたら「全てをインストール」を選び、Adafruit GFXとAdafruit BusIOも一緒にインストールします。
- 必要なら「ファイル」>「スケッチ例」>「Adafruit SSD1306」>「ssd1306_128x64_i2c」を開き、ディスプレイのアドレスを0x3Cにして試してみてください。
最初のプログラム:画面に文字を書く
1#include <Wire.h>
2#include <Adafruit_GFX.h>
3#include <Adafruit_SSD1306.h>
4
5Adafruit_SSD1306 display(128, 64, &Wire, -1); // genişlik, yükseklik, I2C, reset pini yok / width, height, I2C, no reset pin
6
7void setup() {
8 if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // I2C adresi / I2C address
9 for (;;); // ekran bulunamadı / display not found
10 }
11 display.clearDisplay();
12 display.setTextColor(SSD1306_WHITE);
13 display.setTextSize(2); // 2 kat büyük / double size
14 display.setCursor(0, 0);
15 display.println(F("BlueGrays"));
16 display.setTextSize(1);
17 display.setCursor(0, 24);
18 display.println(F("OLED 128x64 hazir!"));
19 display.display(); // tamponu ekrana gönder / push the buffer to the screen
20}
21
22void loop() {
23}図形を描く:Adafruit GFXの関数
| 関数 | 描くもの |
|---|---|
| drawPixel(x, y, 色) | 1つのピクセル |
| drawLine(x0, y0, x1, y1, 色) | 線 |
| drawRect / fillRect(x, y, 幅, 高さ, 色) | 四角形、または塗りつぶした四角形 |
| drawCircle / fillCircle(x, y, 半径, 色) | 円、または塗りつぶした円 |
| drawRoundRect(x, y, 幅, 高さ, 角の半径, 色) | 角の丸い四角形 |
| drawTriangle(x0, y0, x1, y1, x2, y2, 色) | 三角形 |
| drawBitmap(x, y, 配列, 幅, 高さ, 色) | 用意した画像(ビットマップ) |
画面の左上の角が(0, 0)、右下の角が(127, 63)です。色にはSSD1306_WHITE(点灯)、SSD1306_BLACK(消灯)、SSD1306_INVERSE(反転)を使います。
センサーの値を表示する:リアルタイム温度計
OLEDの強みは、測定値を大きな数字やグラフィックで表示できることです。下のコードは、DHT11で読み取った温度を大きなフォントで書き、その下に湿度を棒グラフで表示します。センサーの配線はDHT11温湿度センサーを参照してください。
1#include <Wire.h>
2#include <Adafruit_GFX.h>
3#include <Adafruit_SSD1306.h>
4#include <DHT.h>
5
6Adafruit_SSD1306 display(128, 64, &Wire, -1);
7DHT dht(2, DHT11);
8
9void setup() {
10 display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
11 display.setTextColor(SSD1306_WHITE);
12 dht.begin();
13}
14
15void loop() {
16 float t = dht.readTemperature();
17 float h = dht.readHumidity();
18 display.clearDisplay();
19 display.setTextSize(1);
20 display.setCursor(0, 0);
21 display.print(F("Sicaklik / Temp"));
22 display.setTextSize(3);
23 display.setCursor(0, 16);
24 display.print(t, 1);
25 display.print(F("C"));
26 display.drawRect(0, 52, 128, 10, SSD1306_WHITE); // nem çubuğu çerçevesi / humidity bar frame
27 display.fillRect(2, 54, (int)(h / 100.0 * 124), 6, SSD1306_WHITE); // nem oranı kadar dolu / filled by humidity
28 display.display();
29 delay(2000);
30}オリジナルのアイコンを描く:ビットマップ
ロゴやアイコンを表示するには、画像をバイトの配列に変換します。各ビットが1つのピクセルです。image2cppのような変換ツールを使えば、白黒の画像をそのままArduinoの配列にできます。小さなアイコンなら手で書くこともできます。下の8×8の配列はハートを描きます。
1const unsigned char PROGMEM heart[] = {
2 0b01100110,
3 0b11111111,
4 0b11111111,
5 0b11111111,
6 0b01111110,
7 0b00111100,
8 0b00011000,
9 0b00000000
10};
11
12// setup() ya da loop() içinde / inside setup() or loop()
13display.drawBitmap(60, 28, heart, 8, 8, SSD1306_WHITE);
14display.display();ESP32とRaspberry Pi PicoでOLEDを使う
ESP32では、同じArduinoのコードとライブラリがそのまま動きます。I2CピンはGPIO 21(SDA)と22(SCL)です。ESP32はメモリが豊富なので、アニメーションや頻繁に更新するグラフィックもずっとなめらかになります。MicroPythonを使うPicoでは、ssd1306.pyドライバファイル(micropython-lib)をPicoにコピーするだけです。
1from machine import Pin, I2C
2import ssd1306 # ssd1306.py Pico'da olmalı / must be on the Pico
3
4i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=400000)
5oled = ssd1306.SSD1306_I2C(128, 64, i2c) # adres varsayılan 0x3C / default address 0x3C
6
7oled.fill(0) # ekranı temizle / clear the screen
8oled.text("BlueGrays", 0, 0)
9oled.text("Pico + OLED", 0, 16)
10oled.rect(0, 40, 128, 20, 1) # çerçeve / frame
11oled.fill_rect(2, 42, 80, 16, 1) # dolu çubuk / filled bar
12oled.show() # ekrana gönder / push to the screenディスプレイの寿命と焼き付き
OLEDのピクセルは、使うにつれて明るさが落ちていきます。同じ画像を何か月も変えずに表示し続けると、よく点灯するピクセルにうっすらと残像ができることがあります。これを防ぐには、使っていないときにディスプレイをオフにする(display.ssd1306_command(SSD1306_DISPLAYOFF))、明るさを下げる(display.dim(true))、動かない表示をときどき数ピクセルずらす、またはPIRセンサーを使って人が近くにいるときだけディスプレイをオンにする、といった方法があります。
OLEDディスプレイのプロジェクトアイデア
- ミニ気象観測所:温度、湿度、気圧をアイコン付きで表示します。
- ポケットゲーム:ボタンやジョイスティックで、PongやT-Rexランナーのようなゲームを遊びます。
- 天気表示:ESP32でインターネットから取得した天気を、アイコン付きで表示します。
- 駐車センサーの表示:HC-SR04で測った距離を数字とバーで表示します。
- 信号プロッター:analogReadの値を、画面上でスクロールするグラフとして描きます。
- 卓上時計:インターネットの時刻、日付、その日の天気を1つの画面にまとめます。
よくあるミスと直し方
- 画面が真っ暗のまま:display.display()を呼んでいない、アドレスが違う(0x3Cではなく0x3D)、またはSDAとSCLが逆になっています。
- 「SSD1306 allocation failed」:UnoのRAMが足りていません。128×64のディスプレイのバッファは1 KBを使います。文字列はF()で書く、大きな配列はPROGMEMに移す、またはRAMにやさしいU8g2ライブラリを使ってください。
- 画像が乱れる、または半分しか表示されない:128×32のディスプレイを128×64として宣言しています(またはその逆)。コードで正しいサイズを使ってください。
- 画像が上下逆になる:display.setRotation(2)で180度回転させてください。
- VCCとGNDを逆につないでいる:ディスプレイが永久に壊れます。つなぐ前にピンの表示を読んでください。
- ランダムに固まる:I2Cの配線が長くたるんでいます。配線は短くし、必要ならI2Cの速度を下げてください。
OLEDディスプレイは、プロジェクトを本格的な見た目にするいちばん安い方法です。数字だけを表示できればよいなら7セグメントディスプレイが、日光の下でも読める文字が必要ならI2C LCDがよい選択です。BlueGraysアプリには、OLEDのPongやT-Rexのゲーム、ESP32の天気表示、駐車センサー、温度ロガーのプロジェクトが回路図とコード付きで載っています。
よくある質問
OLEDディスプレイのアドレスは0x3Cと0x3Dのどちらですか?
128×64のOLEDモジュールのほとんどは0x3Cを使います。一部は基板裏の抵抗の設定で0x3Dになります。裏に「0x78」と書かれていれば、それは8ビット表記で、コードでは0x3Cにあたります。確実に知るには、I2Cスキャナースケッチを実行してください。
OLEDディスプレイは5 Vで動きますか?
SSD1306モジュールのほとんどは基板にレギュレーターがあるので、3.3 Vでも5 Vでも給電でき、Arduino Unoに直接つなげます。ESP32やPicoでは、モジュールを3V3ピンから給電すれば、I2Cのラインも3.3 Vに保たれます。
「SSD1306 allocation failed」エラーが出るのはなぜですか?
ライブラリは128×64のディスプレイ用に1 KBのフレームバッファを確保しようとします。Arduino Unoの2 KBのRAMがほかの変数で埋まっていると、その場所がありません。固定の文字列はF()マクロで書く、大きな配列はPROGMEMに移す、またはページ単位で描くU8g2ライブラリを使ってください。
OLEDディスプレイでアクセント付きの文字や特殊文字を表示できますか?
Adafruit GFXの標準フォントには、ş、ğ、éのような文字は含まれていません。U8g2ライブラリなら、UTF-8対応と大きな文字セットのフォントでそれらを表示できます。Adafruit GFXでは、カスタムフォントを作るか、文字をビットマップとして描く必要があります。
カラーのOLEDディスプレイはありますか?
SSD1306のディスプレイはモノクロで、2色のモデルでも色は固定です。カラーの画像には、SSD1331やSSD1351ドライバのカラーOLEDか、ST7789やILI9341のようなカラーTFTディスプレイを使ってください。
1台のArduinoにOLEDディスプレイを2台つなげますか?
はい。裏の抵抗を付け替えて1台のアドレスを0x3Dにすれば、2台が同じI2Cバスを共有できます。アドレスを変えられない場合は、ESP32やPicoの2つ目のI2Cバスを使うか、TCA9548AのようなI2Cマルチプレクサを追加してください。
この記事を読んだ後に作れるプロジェクト
全プロジェクトを見る
パドルボールゲーム(SSD1306)
ボール1個とパドル2本で遊ぶ、ビデオゲームの原点の1つである卓球ゲームを、小さなOLEDディスプレイで楽しめます。2つのボタンで右のパドルを上下に動かします。左のパドルはコンピューターがボールを追いながら操作し、ボールを打つたびにブザーが短く鳴ります。先に9点を取ると勝ちです。その後、新しいゲームが自動で始まります。

OLED T-Rexラン:Arduino恐竜ゲーム
インターネットが切れると現れる恐竜ゲームを、机の上で楽しめます。小さなOLEDディスプレイを恐竜が走り、迫るサボテンを1つのボタンでジャンプして避けます。横の4桁ディスプレイには得点がリアルタイムで表示され、100点ごとにブザーがお祝いの音を鳴らします。サボテンにぶつかるとゲーム終了です。ボタンを押すと、もう一度始められます。

ESP32 HTTPClient+天気API(SSD1306 OLED付き)
このプロジェクトでは、ESP32でHTTPClient.hを使い、インターネット経由で天気API(wttr.in)をREST APIとして呼び出します。前のI2C LCD版とは異なり、SSD1306 OLED(128×64)ディスプレイを使うため、大きな文字やベクターアイコンで、1つの画面に豊かな表現ができます。天気を表す7種類のベクターアイコン(晴れ、晴れ時々曇り、曇り、雨、雪、嵐、霧)を実行時に描画するので、ビットマップファイルは不要です。気温は中央に3倍の大きさの文字で表示します。

ESP32のディープスリープで節電(OLED + RTC RAMカウンター)
ESP32のディープスリープモードは、CPUとほとんどの周辺機器を停止し、消費電流を約10 µAまで抑えます。電池で動くIoT機器に欠かせない機能です。このプロジェクトでは、タイマー(15秒)、外部ピン(EXT0、ボタンはGPIO 33)、タッチ(T0/GPIO 4)の3種類の復帰方法を使います。RTC_DATA_ATTRを付けた変数はディープスリープ中も保持され、起動回数、タイマーによる復帰回数、ボタンによる復帰回数を継続して記録できます。復帰するたびにSSD1306 OLEDディスプレイに復帰理由と回数を表示します。

ESP32の礼拝ラカア数カウンター(HC-SR04 + SSD1306 OLED + ボタン2個)
礼拝中に何ラカア行ったか忘れてしまうことはありませんか?このプロジェクトでは、礼拝マットの横に置き、手を近づけると平伏の回数を数えるラカア数カウンターを作ります。HC-SR04超音波距離センサーで手の接近を検知し、SSD1306 OLEDディスプレイにラカア数を表示します。2個のボタンで2・3・4ラカアの選択とリセットができます。状態遷移による制御に2.5秒のデバウンス処理と手が離れたことを確認するアルゴリズムを組み合わせ、誤検知を防ぎます。同じ平伏を2回数えることはありません。

ESP32の調色ライト(可変抵抗3個 + RGB LED + OLED)
ESP32と3個の可変抵抗で、好みの色を作れるスマート調色ライトです。赤・緑・青の可変抵抗を回すと、カソードコモンのRGB LEDの色がリアルタイムに変わります。SSD1306 OLEDディスプレイには、各色の0~255の値、色の強さを示すバー、#FF8040などのWeb用HEXカラーコードをリアルタイムで表示します。小さなプロ仕様のカラースタジオとして、RGBの色の仕組み、ADCによるアナログ値の読み取り、PWMによる明るさの制御、I2Cディスプレイの表示設計を1つのプロジェクトで学べます。

ESP32スマート照明(PIR + LDR + リレー + OLED)
ESP32で廊下やトイレ、食品庫の照明をスマート化します!PIRモーションセンサー、LDR光センサー、リレーモジュールを使い、「暗い場所で動きを検知すると点灯する」定番の仕組みを作ります。周囲が明るければ動きを検知しても点灯しないため、日中の無駄な電力消費を抑えられます。照明は30秒間点灯し、動きが続くとタイマーがリセットされて点灯時間が延びます。SSD1306 OLEDには大きな文字で状態(ON / DAYTIME / WAITING)とカウントダウンを表示します。

ESP32温度データロガー(DHT22 + DS1307 RTC + microSD + OLED)
ESP32で日時付きの温度・湿度記録システムを作ります!DHT22で1分ごとに温度と湿度を読み取り、DS1307 RTCから取得した日時とともにmicroSDカードへCSV形式で記録します。OLEDには最新の温度を大きな文字で表示し、湿度のパーセント値、日時、総記録数も表示します。SDカードの/temp_log.csvファイルはExcel、Google Sheets、Pythonのpandasで開いて分析できます。温室の監視、家や部屋の温度管理、実験室のデータ収集、食品の保管環境や養蜂箱の監視に適しています。
ほかの記事
BlueGraysアプリ
この回路をスマホでステップごとに作る
回路図、コード、部品リストを1つの画面で確認できます。Arduino、ESP32、Picoのプロジェクトを200件以上用意しています。

