ゆるく楽しむプログラミング

OLED SSD01306 (I2C接続)

 OLED SSD1306はレギュレータ付きで動作範囲が3.3V~5Vと広く
 プルアップ抵抗も付いているので、電源と2本の信号線を繋ぐだけで
 Arduino(5V)でもRaspberryPi Pico(3.3V)でも使えます
 ※レギュレータが付いていないモノもあるようなので注意

 ArduinoIDEでの使用例も多く、ライブラリも数種類あり使いやすいです。

OLED SSD1306のコマンドと送信手順

SSD01306のコマンドはI2Cの手順に則り 以下の3パターンで送信する



コマンドの詳細は SSD1306のスペックシートを参照
※2バイトバイト命令や複数の命令をまとめて送信する場合は複数命令タグ(0x00)を使用する
※送信するのは命令かデータのどちらかで、命令とデータを混ぜて送ることはできない。

初期化に必要なコマンドを抜粋:スクロールとか色々あるので詳細はデータシート参照
命令コード データ データ長 命令内容
20 00~02 1 メモリーアドレッシングモード設定
00:水平アドレッシングモード 、01:垂直アドレッシングモード
02:ページアドレッシングモード ※リセット時 02
81 00~FF 1? 表示コントラスト リセット時 0x7F?
A4 0 描画 ON : 画面の書き換えを行う?
A5 0 描画 OFF?: 画面の書き換えを停止
A6 0 通常表示 : データビット1を黒、0を白で表示する
A7 0 反転表示 : 画面の白黒を反転
A8 00~3F 1 画面の解像度 : 表示するLine数 +1した値になります
DA 12 or 02 1 表示モード設定: 0x02:Alternative 、0x12:Sequential
AE 0 画面を非表示にする : 描画は行われる?
AF 0 画面を表示する
A0 0 水平描画方向 : → 右から左
A1 0 水平描画方向 : ← 左から右
C0 0 垂直描画方向 : ↓ 上から下
C8 0 垂直描画方向 : ↑ 下から上
D3 00~3F 1 縦方向のオフセット : この値を連続して変化させると縦スクロールができます
40~7F 0 描画開始Line ※ 0x3FとANDを取った値(下位6Bitのみ有効)
B0~B7 0 描画ページを指定する?
10~1F 0 描画開始位置 横方向の上位4ビット
00~0F 0 描画開始位置 横方向の下位4ビット
26 7 右水平スクロール:スクロール範囲とスクロール速度
27 7 左水平スクロール:スクロール範囲とスクロール速度
29 6 右水平垂直スクロール:スクロール範囲とスクロール速度
2A 6 左水平垂直スクロール:スクロール範囲とスクロール速度
A3 2 垂直スクロールエリア指定:固定Line数、スクロールLine数
2E 0 スクロール停止
2F 0 スクロール開始

表示モード

Sequential モード
128x64 Dot のOLEDは大体この形式
Alternative モード
128x32 DotのOLEDは大体この形式

SSD1306のデータマップ

スペックシートの 8.7 Graphic Display Data RAM (GDDRAM) を見た方が分かりやすいかも


1バイト(8ビット)が縦に並び、横方向に128バイト繋がります。
この128バイト(縦8ピクセル、横128ピクセル)を1ページとして
縦方向に8ページ繋がっています。

SSD1306のデータ送信では、ページ番号と開始バイト位置を設定して
1バイト単位でビットデータを送信します。

描画位置をPage0の0ピクセル目からに設定し
0x01,0x02,0x04,0x08,0x01,0x02,0x04,0x08 の 8バイトをデータをして送信した場合
←図のPAGE0の左側のようにドットが設定されます。





-- SSD1306 初期化例 : 動作が分かりやすいようにしてます。流石に こんなのを毎回書くのは大変なので関数にしますよ --

#include <Wire.h>
uint8_t oledWidth = 128;  // OLEDの幅(ピクセル数)
uint8_t oledPages = 8;    // OLEDのページ数

void setup() {
  Wire.begin();	// Wireクラスの初期化

  // SSD1306の初期化
  Wire.beginTransmission(0x3C);	// I2Cアドレス
  Wire.write(0x00);		// 複数バイトコマンドタグ
  Wire.write(0xC8);		// [C0]/C8:上下の描画方向
  Wire.write(0xA1);		// [A0]/A1:左右の描画方向
  Wire.write(0xA8);Wire.write(0x3F);	// 画面の解像度 [3F]:64Line / 1F:32Line
  Wire.write(0xDA);Wire.write(0x12);	// [12]:Sequential / 02:Alternative
  Wire.write(0xD3);Wire.write(0x00);	// 縦方向のオフセット
  Wire.write(0x40);		// 縦方向の描画開始位置
  Wire.write(0xA6);		// 表示方法 - A7にすると画面反転
   Wire.write(0x8D);Wire.write(0x14);	// OLEDパネルの供給電圧と思われる 14hに設定しないとダメらしい
  Wire.endTransmission();

  // 画面の初期化:黒塗り
  for (uint8_t m = 0; m < oledPages; m++) {
    oledSendCommand3(0xB0 | (m & 0x07) , 0x10 , 0x00) ;

    Wire.beginTransmission(0x3C);
    Wire.write(0x40);	// データタグ
    for (uint8_t x = 0; x < oledWidth; x++) {
      if (Wire.write(0x00) == 0) {
        // --- 送信に失敗したら
        // ArduinoのWireは一度に32バイトまでしか送信できないので33バイト目は必ず送信失敗します。
        // 送信できなかった場合、一旦送信を終了し、再度送信セッションを開いて続けます
        Wire.endTransmission();
        Wire.beginTransmission(0x3C);
        Wire.write(0x40);  // データタグ
        Wire.write(0x00);
      }
    }
    Wire.endTransmission();
  }
  oledSendCommand3(0xB0 , 0x10 , 0x00) ;

  // 画面表示
  Wire.beginTransmission(0x3C);	// I2Cアドレス
  Wire.write(0x80);		// 1バイトコマンドタグ
  Wire.write(0xAF);		// 画面表示
  Wire.endTransmission();
}

ビットマップ画像を表示するサンプルスケッチ:参考動画で使用しているプログラムとデータです。
-- SSD1306TEST.ino --

128x32 Dot OLED用スクロール表示サンプル:参考動画で使用しているプログラムとデータです。
-- SSD1306_128x32_Sample.zip --

BITMAPデータの作成

BITMAPの向きがWindowsなどと違うために、BITMAPデータを作るのが結構大変だったります。
image2cpp
を利用すればArduinoIDEで使えるSSD1306用のビットマップデータが簡単に作れます。
※Chrome推奨



解説動画