単色OLEDモジュールを使う(SSD1306 / I2C)

it


小型の単色OLEDモジュール SSD1306を使います。
RaspberryPi PicoとESP32-WROOMほか、Arduino環境で使用できるマイコンを使って簡単な表示サンプルを作ります。

記事の目的と内容

本記事では、単色OLEDモジュール SSD1306について記載します。
・RP2040搭載基板、RaspberryPi Picoでの配線と簡単な表示スケッチ
・ESP32-WROOM搭載基板、NODE-MCUでの配線と簡単なスケッチ
また、SSD1306を複数接続する場合の配線とスケッチを紹介します。

そのほかの単色OLEDモジュールには、
・1.3inch SSH1106
・1.54inch SSD1309
・2.42inch SSD1309
等あります。
このうちSSD1309を使用している1.54inchと2.42inchはArduino上で使用するモジュールライブラリ(Adafruit製)は同じライブラリと同じスケッチを使用できます。

SSH1106 1.3inchについては同じライブラリを使用することができません。
スケッチも一部修正が必要なので別途記事で記載します。

OLED SSD1306について

Arduino環境で使用できるマイコンで手軽に表示できる小型の表示器です。

主なスペック

サイズ0.49, 0.91, 0.92, 1.54, 2.42inch
他にも数種類
解像度(X, Y)0.49inch : 128, 64 (有効表示エリアは64, 32)
0.91inch : 128, 32
0.92inch : 128, 64 (本記事では こちらを紹介)
表示色白、青、黄、黄+青
黄+青の場合、それぞれのエリアが決まっていて、
色の変更はできないようです。
電源電圧3.3 – 5.0V
通信方式I2C(アドレスは 0x3c, または0x3dのどちらかを選択)
SPI
ドライバSSD1306
入手電子部品ショップ、ネットショップ
入手性は非常に良く、安く大量買いする場合はAli Express

ピン配置

外観(I2C)

前面

背面

まとめ

Good

簡単な接続とスケッチで表示制御ができる。
I2Cでの接続なので少ない配線で表示制御ができるので作業性がよいです。
はっきりとした明るい発色。

Bad

輝度、色の変更ができないので、鮮やかな表現ができない。
使用できるI2Cアドレスは2種類(3c(h), 3d(h))なので、3個以上接続するのは不向き。
SPIと比べると表示速度が遅い。
画面サイズが大きくなっても解像度は上がらない。
(スケッチの変更なくサイズ違いのOLEDモジュールを使用できるが、Goodと考えることもできる)

そのほか

0.96inchは特に安価で入手性がよいですが、少し小さいと感じます。
画面サイズは大きくなっても解像度は変わりませんが視認性はよくなります。
価格は1.54inchで0.96inchの3倍程度するので、気安く購入しにくくなります。

Adafruit製のライブラリを使用していますが、命令がシンプルで使いやすいと思います。
簡単な命令と配線で表示ができるので、解像度の低いゲームやメニューに使用するほか、プログラムのデバッグや結果の表示などに重宝します。
結果的にBadを多く列挙しましたが、各種モジュールの中では使用頻度は高い部類になるので、1つは持っておきたいモジュールです。

準備

ライブラリのインストール

ArduinoIDEでSSD1306を使用するために必要なライブラリをインストールします。
ライブラリは以下2つのライブラリを使用します。

ライブラリ名検索動作確認Ver
Adafruit SSD1306 by AdafruitSSD13062.5.9
Adafruit GFX Library by AdafruitGFX1.11.9

マイコン側に必要なボードライブラリは使用するマイコンに対応したボードライブラリをインストールします。

OLEDのI2Cアドレス確認

SSD1306モジュールのI2Cアドレスは3c(h)または3d(h)のどちらかを選択して使用します。
OLEDモジュールの裏面の「IIC ADDRESS SELECT」の抵抗の位置を確認します。
初期位置は3c(h)と思います。

なお、Adafruitライブラリを使用していますが、サンプルのアドレスは3d(h)です。モジュールの抵抗付け替えをしない場合はスケッチ側で修正します。


面実装抵抗をはがすスキルはそれなりに必要なので、自信のない方は現在の設定のまま使用することをお勧めします。
※無理にはがすとOLEDパターンをはがしてしまい、OLEDが使用できなくなることがあります。

I2Cアドレスを設定する抵抗を外した
I2Cアドレスを0x3dになるように取り付けた

サンプル(基本)

Arduino環境で使用できる代表的なマイコンボードを使って簡単なサンプルを動かします。

RP2040系 Raspberry Pi Picoを使った表示

説明

I2C0を使ったOLEDの表示です。
画面に “TAMANEGI” と “I2C0 0x3c”と表示します。

Setup()関数の先頭でI2C0に使用するピンをWireオブジェクトを使って変更しています。

配線

SSD1306 OLEDのI2Cアドレスは3c(h)です。

スケッチ

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128                //解像度 128 x 64 で使用します。
#define SCREEN_HEIGHT 64                //SCREEN_HEIGHTは 32 に設定することができます。

#define OLED_RESET     -1               //使用しないので -1を設定する。
#define SCREEN_ADDRESS 0x3C             //I2Cアドレスは 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
                                        //表示制御にはAdafruit製 SSD1306を使用する。
                                        //初期化時には I2C0を使用する (Wire)
                                        
void setup() {
  
  Wire.setSDA(0);                       //I2C0で使用するGPは SDA = 0, SCL = 1
  Wire.setSCL(1);

  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    for(;;);
  }

  display.clearDisplay();               //何か表示されている場合に備えて表示クリア

  display.setTextSize(2);               //フォントサイズは2(番目に小さい)
  display.setTextColor(SSD1306_WHITE);  //色指定はできないが必要
  display.setCursor(20, 10);            //テキストの表示開始位置
  display.print(F("TAMANEGI"));         //表示文字列
  display.setCursor(10, 30);
  display.print(F("I2C0 0x3c"));

  display.display();                    //バッファ転送(表示)
}

void loop() {
}

結果

ESP32系 ESP32-WROOMを使った表示

I2C0を使ったOLEDの表示です。
画面に “TAMANEGI” と “I2C0 0x3c”と表示します。

I2Cに使用するピンをWireオブジェクトを使って変更します。
サンプルスケッチでは、ESP32-WROOM (NodeMCU)のデフォルトI2Cを使用するため、ピンの変更をしていませんが、以下のコメントを解除することで、任意のピンに変更することができます。

// Wire.setPins(PIN_SDA, PIN_SCL);

配線

スケッチ

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH (128)              //解像度 128 x 64 で使用します。
#define SCREEN_HEIGHT (64)              //SCREEN_HEIGHTは 32 に設定することができます。

#define OLED_RESET     (-1)             //使用しないので -1を設定する。
#define SCREEN_ADDRESS (0x3C)           //I2Cアドレスは 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
                                        //表示制御にはAdafruit製 SSD1306を使用する。

//任意の位置にピン設定する場合の定義
#define PIN_SDA (3)
#define PIN_SCL (1)                                   

void setup()
{
//  任意のピンをI2Cに設定する場合コメントの解除
//  Wire.setPins(PIN_SDA, PIN_SCL);

  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    for(;;);
  }

  display.clearDisplay();               //何か表示されている場合に備えて表示クリア

  display.setTextSize(2);               //フォントサイズは2(番目に小さい)
  display.setTextColor(SSD1306_WHITE);  //色指定はできないが必要
  display.setCursor(20, 10);            //テキストの表示開始位置
  display.print(F("TAMANEGI"));         //表示文字列
  display.setCursor(10, 30);
  display.print(F("I2C0 0x3c"));

  display.display();                    //バッファ転送(表示)
}

void loop()
{
}

結果

サンプル(応用)

SSD1306 OLEDの複数使用などのサンプルを掲載します。
サンプル数が多くなるので代表してRaspberryPi Picoで実装します。

I2C0を使ったコピーモニタ<非推奨>

I2C0ライン上に同じI2Cアドレスを持ったモジュールを配線することで、コピーモニタになります。
※I2Cではマスタからスレーブにデータを送信するときに、スレーブからACK/NACKを受け取ります。
同じアドレスが重複するとどちらの返答かわからなくて不具合の原因となるため、推奨できません

配線

SSD1306のI2Cアドレスは2つともに3c(h)。

スケッチ

「RP2040系 I2Cによる表示」と同じスケッチを使用します。

結果

期待通りの表示はできていますが、潜在的な不具合が発生する可能性があります。

I2Cアドレスを変更した使ったデュアルモニタ

同じI2C0 ライン上には異なるI2Cアドレスのモジュールを使用します。
スケッチにはそれぞれのアドレスに対して個別の表示ができます。

I2Cアドレス 3c(h)用のオブジェクト display1と、3d(h)用のオブジェクトdisplay2を使用します。
使用するI2Cラインはどちらも同じI2C0なので、Wireオブジェクトを使用します。

オブジェクトの制御開始関数 display1.beginの引数にI2C 3c(h)のアドレス、
display2.beginの引数にI2C 3d(h)アドレスを与えています。

配線

OLED SSD1306のI2Cアドレスは 3c(h)と3d(h)を使用します。
配線の並びは、3c(h)と3d(h)のどちらが先でも構いません。
配線は、「I2C0を使ったコピーモニタ<非推奨>」と同じです。

スケッチ

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH (128)                //解像度 128 x 64 で使用します。
#define SCREEN_HEIGHT (64)                //SCREEN_HEIGHTは 32 に設定することができます。

#define OLED_RESET     (-1)               //使用しないので -1を設定する。
#define SCREEN_ADDRESS_M1 (0x3C)          //OLED 1のI2Cアドレスは0x3C
#define SCREEN_ADDRESS_M2 (0x3D)          //OLED 2のI2Cアドレスは0x3d

//それぞれを個別制御するためにそれぞれのオブジェクトを用意します。
Adafruit_SSD1306 display1(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_SSD1306 display2(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


void setup() {
  
  Wire.setSDA(0);                       //I2C0で使用するGPは SDA = 0, SCL = 1
  Wire.setSCL(1);

  if(!display1.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS_M1)) {
    for(;;);
  }
  if(!display2.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS_M2)) {
    for(;;);
  }

  //ここは OLED1の表示処理
  display1.clearDisplay();

  display1.setTextSize(2);
  display1.setTextColor(SSD1306_WHITE);
  display1.setCursor(20, 10);
  display1.print(F("TAMANEGI"));
  display1.setCursor(10, 30);
  display1.print(F("I2C0 0x3c"));

  display1.display();

  //ここから OLED2の表示処理
  display2.clearDisplay();

  display2.setTextSize(2);
  display2.setTextColor(SSD1306_WHITE);
  display2.setCursor(20, 10);
  display2.print(F("TAMANEGI"));
  display2.setCursor(10, 30);
  display2.print(F("I2C0 0x3d"));

  display2.display();

}

void loop() {
}

結果

I2Cを2ライン使ったデュアルモニタ

説明

I2Cが2ライン以上あるマイコンでは同じI2CアドレスのモジュールでもそれぞれのI2Cラインを使用することで個別に制御できます。

この例ではOLED SSD1306を2つ使用しますが、I2Cアドレスはどちらも3c(h)です。
片方はI2C0のWireオブジェクトを使用し、もう片方をI2C1のWire1オブジェクトを使用します。


配線

SSD1306のI2Cアドレスは2つともに3c(h)。

スケッチ

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH (128)                //解像度 128 x 64 で使用します。
#define SCREEN_HEIGHT (64)                //SCREEN_HEIGHTは 32 に設定することができます。

#define OLED_RESET     (-1)               //使用しないので -1を設定する。
#define SCREEN_ADDRESS (0x3C)             //I2Cアドレスは0x3C

//それぞれを個別制御するためにそれぞれのオブジェクトを用意します。
Adafruit_SSD1306 display1(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_SSD1306 display2(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire1, OLED_RESET);


void setup() {
  
  Wire.setSDA(0);                       //I2C0で使用するGPは SDA = 0, SCL = 1
  Wire.setSCL(1);

  Wire1.setSDA(2);                       //I2C1で使用するGPは SDA = 2, SCL = 3
  Wire1.setSCL(3);

  if(!display1.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    for(;;);
  }
  if(!display2.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    for(;;);
  }

  //ここは OLED1の表示処理
  display1.clearDisplay();

  display1.setTextSize(2);
  display1.setTextColor(SSD1306_WHITE);
  display1.setCursor(20, 10);
  display1.print(F("TAMANEGI"));
  display1.setCursor(10, 30);
  display1.print(F("I2C0 0x3c"));

  display1.display();

  //ここから OLED2の表示処理
  display2.clearDisplay();

  display2.setTextSize(2);
  display2.setTextColor(SSD1306_WHITE);
  display2.setCursor(20, 10);
  display2.print(F("TAMANEGI"));
  display2.setCursor(10, 30);
  display2.print(F("I2C1 0x3c"));

  display2.display();

}

void loop() {
}

結果

コメント

タイトルとURLをコピーしました