SSD1306有機ELディスプレイOLEDの使い方、簡単2画面表示の方法も紹介

OLED液晶SSD1306 2画面表示

有機ELディスプレイ SSD1306(OLED)の使い方について紹介します。

SSD1306には画面サイズ違いで2種類(128×64、128×32)あり、比較的安価(どちらも500~700円程)で購入できます。
I2C通信とSPI通信に対応したものがありますが、I2C通信の方が通信線が2本で電源線と合わせても全部で4本のため扱いやすいです。

液晶表示の無い「ATOM LITE」や「ESP32」「Arduino」等に接続して「Adafruit社」から提供されているライブラリを使用することで簡単に制御できます。

画面表示ライブラリについては「lovyanGFX」が日本語も簡単に表示できるので紹介記事を追加しました。以下リンクで詳しく紹介しています。
SSD1306 OLEDで日本語表示 lovyanGFXの使い方
SSD1306でlovyanGFXを使用した日本語表示方法を紹介。ATOM LITEを使ってますがArduinoでも基本は同じで、他のOLEDでも初期設定を変えるだけです。

今回は「ATOM LITE」を使って「SSD1306」について紹介します。
「Arduino」等でもヘッダーファイル以外はほぼ同じです。

「ATOM LITE」については以下のリンクで詳しく紹介しています。

ATOM LITE プログラミング初心者におすすめ超小型で高機能!
マイコンボードはRaspberry Pi、Arduino、M5Stack等がありますが、一通りやってみてそれぞれの良さはあるものの「最初に何を?」と聞かれたらATOM LITEが一番お手軽♪プログラミング初心者におすすめ
「開発環境の準備」がまだの方は → こちら

「Raspberry Pi Pico」を使用したSSD1306の使い方も以下で詳しく紹介しています。

ラズパイPicoでSSD1306有機ELディスプレイの使い方 C言語編
液晶表示器のないRaspberry Pi PicoでOLED SSD1306の使い方を詳しく紹介。まずはArduinoIDEを使用したC言語での使用方法を紹介します。
ラズパイPicoでSSD1306有機ELディスプレイの使い方 MicroPython編
液晶表示器のないRaspberry Pi PicoでOLED SSD1306の使い方をMicroPythonのサンプルプログラムで紹介。開発環境はTonnyを使用します。
スポンサーリンク

1.外観と配線の接続方法

SSD1306には4つの端子(GND、電源3.3~5V、SCL、SDA)があります。
付属品として4ピンのピンヘッダが付属していますので、下画像のようにはんだ付けして使用できます。

上画像の左が「128×64」で右が「128×32」です。
どちらも使い方は一緒で画面の高さ(Height)の設定(64か32)を変えるだけです。

上画像は基板の裏側で部品が剥き出しです。
金属が触れると壊れるのでビニール絶縁テープ等を貼っておくのがおすすめです。

ピンヘッダをはんだ付けしておけばブレッドボードに差し込んで使ったり、上画像のように「メスピンヘッダとGroveコネクタ付き配線」接続して使うこともできます。

上画像は「Groveコネクタ付き配線」を直接はんだ付けしたものです。
「Groveコネクタ」でしか使えなくなりますがコンパクトに使えるので1つあると便利です。

「Groveコネクタ」の配線は白線と黄線をクロスさせています。
「ATOM LITE」の製造元である「M5テクノロジー社」製の他のI2C通信を使ったユニットの「Groveコネクタ」は、白線がSCL、黄線がSDAになっているので合わせておくと他のユニットに接続する時でもそのまま使用できます。

「SSD1306」の端子配列は「128×64」と「128×32」で同じです。
「ATOM LITE」の「Groveコネクタ」と「SSD1306 128×64」の結線は下画像のようになります。

I2C通信線(SCL、SDA)を接続した「ATOM LITE」の端子をプログラム内でそれぞれ「SCL」「SDA」用として設定します。「ESP32」や「Arduino」でも同じです。

SSD1306の接続方法
「Groveコネクタ」配線の色は製造元によって違うことがあるので注意しましょう。
「M5テクノロジー社」と「SEEED社」では黄線と白線が逆になるので使う前によく確認しましょう。
スポンサーリンク

2.画面サイズ128×64と128×32の表示比較

画面サイズ「128×64」と「128×32」にASCII文字(94種類)を文字サイズ「1」と「2」で表示させたものが下画像になります。

モノクロ仕様のものを使用しましたがバックライトは白や青っぽいもの、黄色等もあります。
下画像では「128×64(大きい方)」が白、「128×32(小さい方)」が青っぽいものになります。

OLED液晶SSD1306 2画面表示

文字サイズ「1」の場合は上画像のようになります。
1行で21文字表示されるので「128×64」では94文字全て表示されますが「128×32」では4行で81文字までの表示になります。

OLED液晶SSD1306 2画面表示

文字サイズ「2」の場合は上画像のようになります。
1行で10文字表示されるので「128×64」では4行で40文字。「128×32」では2行で20文字の表示になります。

文字サイズは「1」を基準に、設定した数値の倍率で拡大されていきます。
下画像のように文字サイズ「3~8(×3~×8)」も表示してみました。
「5」以上では文字が切れてしまうので「4」が限界のように思います。
SSD1306文字サイズ3~8
スポンサーリンク

3.サンプル画面の紹介(ATOM LITE使用)

基本的な表示内容として「SSD1306」の「128×64」を使用して下画像のようなサンプル画面を準備しました。

OLED液晶SSD1306デモ画面

①タイトル表示
②ボタンの動作で内容が変化
③ボタンを押した回数を表示
④指定した座標から平行線
⑤始点終点を座標で指定した線
⑥指定した座標から垂線
⑦円と塗り潰し円
⑧三角と塗り潰し三角
⑨四角と塗り潰し四角

4.サンプルプログラム(コピペ)

サンプル画面を表示するプログラムは以下のようになります。
「コピペ」して書き込んでください。

※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

#include <M5Atom.h>           //Arduino.h / Wire.h / FastLED.h含む
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h> //別途「Adafruit BusIO」ライブラリ必要

// OLED設定
#define SCREEN_WIDTH 128  //OLED 幅指定
#define SCREEN_HEIGHT 64  //OLED 高さ指定
#define OLED_RESET -1     //リセット端子(未使用-1)

// I2Cに接続されたSSD1306用「display」の宣言
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// 変数宣言
int cnt = 0;  //ボタンを押した回数カウント用
// FastLED(CRGB構造体)設定
CRGB dispColor(uint8_t r, uint8_t g, uint8_t b) {
  return (CRGB)((r << 16) | (g << 8) | b);
}
// 初期設定 --------------------------------------------------
void setup() {
  // 本体初期化(UART無効, I2C有効, LED有効)
  M5.begin(false, true, true);
  Wire.begin(26, 32);   //Grove端子をI2C設定(SDA,SDL)

  // OLED初期設定
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306:0 allocation failed"));
    for (;;); //エラーなら無限ループ
  }
  // OLED表示設定
  display.setTextColor(SSD1306_WHITE);  //文字色
}
// メイン -------------------------------------------------
void loop() {
  M5.update();                //ボタン状態更新
  display.clearDisplay();     //表示クリア

  // タイトル表示
  display.setTextSize(1);     //文字サイズ(1)
  display.setCursor(4, 0);    //表示開始位置左上角(X,Y)
  display.println("OLED");    //表示内容
  display.setCursor(4, 10);   //表示開始位置左上角(X,Y)
  display.println("TEST");    //表示内容

  display.setTextSize(2);     //文字サイズ(2)
  display.setCursor(39, 2);   //表示開始位置左上角(X,Y)
  display.println("SSD1306"); //表示内容

  // 本体ボタンON/OFF状態表示
  display.setTextSize(1);     //文字サイズ(1)
  display.setCursor(5, 28);   //表示開始位置左上角(X,Y)
  if (M5.Btn.isPressed()) {   //ボタンが押されていれば(ずっと)
    M5.dis.drawpix(0, dispColor(0, 0, 100));  //本体LED青
    display.println("BTN = ON");              //表示内容
  } else {                    //ボタンが押されてなければ
    M5.dis.drawpix(0, dispColor(20, 20, 20)); //本体LED白
    display.println("BTN = OFF");             //表示内容
  }
  // 本体ボタンON回数カウント表示
  if (M5.Btn.wasPressed()) {  //ボタンが押されていたら(押された時だけ)
    cnt++;                    //カウント+1
  }
  display.setCursor(72, 28);          //座標を指定
  display.printf("CNT=%04d\n", cnt);  //カウント数

  // 図形表示
  display.drawLine(0, 20, 128, 20, WHITE);   //線(始点終点指定)
  display.drawFastVLine(64, 22, 17, WHITE);  //線(指定座標から垂線)
  display.drawFastHLine(0, 40, 128, WHITE);  //線(指定座標から平行線)

  display.drawCircle(10, 55, 8, WHITE);      //円
  display.fillCircle(30, 55, 8, WHITE);      //円(塗り潰し)

  display.drawTriangle(46, 62, 54, 48, 62, 62, WHITE); //三角
  display.fillTriangle(66, 62, 74, 48, 82, 62, WHITE); //三角(塗り潰し)

  display.drawRect(90, 47, 16, 16, WHITE);   //四角
  display.fillRect(110, 47, 16, 16, WHITE);  //四角(塗り潰し)

  display.display();  //表示実行

  delay(100);
}

5.必要なライブラリのインストールと初期設定

表示器を使うためには、まず表示するために必要なライブラリの追加を行います。
今回は「Adafruit社」から提供されているライブラリを使用します。
「ATOM LITE」では本体のフルカラーLEDを使用するために「FastLED」ライブラリも必要ですが「ESP32」「Arduino」等では不要です。

表示器を制御するためのライブラリをヘッダー部の1行目から以下のように記入します。

#include <M5Atom.h>           //Arduino.h / Wire.h / FastLED.h含む
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h> //別途「Adafruit BusIO」ライブラリ必要

1行目の「M5Atom.h」は「ATOM LITE」専用のもので「FastLED」ライブラリの使用も同時に宣言されます。(「ESP32」「Arduino」では不要)

2行目~3行目が「SSD1306」を使用するためのヘッダーファイルです。

今回必要なライブラリは以下になります。
・FastLED(ATOM LITEのみ必要)
・Adafruit GFX Library
・Adafruit SSD1306
・Adafruit BusIO

ライブラリの追加は「PlatformIO」の「ホーム」画面の「Libraries」からライブラリ名で検索して追加を行ってください。

※ライブラリの追加方法は以下のリンクで「FastLED」ライブラリの追加で紹介しています。

PlatformIOでのライブラリの追加方法は → こちら

次に5行目~11行目のように使用する表示器の画面サイズ、通信、リセット端子の設定を「display」コマンドとして宣言します。

// OLED設定
#define SCREEN_WIDTH 128  //OLED 幅指定
#define SCREEN_HEIGHT 64  //OLED 高さ指定
#define OLED_RESET -1     //リセット端子(未使用-1)

// I2Cに接続されたSSD1306用「display」の宣言
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_SSD1306 display( 画面幅, 高画面高さ, &wire, リセット端子 ) ;

Adafruit_SSD1306 display:「display」というコマンドを使用するための宣言
画面幅:SSD1306では「128」固定
画面高さ:「128×64」では「64」、「128×32」では「32」に設定
&wire:I2C通信の設定です。このまま記入
リセット端子:未使用なので「-1


15行目~18行目は「FastLED」ライブラリの設定です。(「ESP32」「Arduino」では不要)

// FastLED(CRGB構造体)設定
CRGB dispColor(uint8_t r, uint8_t g, uint8_t b) {
  return (CRGB)((r << 8) | (g << 16) | b);
}

「FastLED」ライブラリは「ATOM LITE」本体のフルカラーLEDを制御するためのものです。

「FastLED」ライブラリについての詳細は → こちら

23行目でI2C通信で使用する端子を設定しています。

Wire.begin(26, 32);   //Grove端子をI2C設定(SDA,SDL)
Wire.begin( SDASCL ) ;
Wire.begin:I2C通信を設定して開始するためのコマンド
SDA:I2C通信のデータ信号用端子番号を設定
SCL:I2C通信のクロック信号用端子番号を設定

25行目~29行目で「SSD1306」の初期設定をします。
この中で「0x3C」はI2C通信のアドレスです。基本的には「0x3C」ですが、チップ抵抗をはんだ付けで付け換えて、もう一つの「0x3D」として使うこともできます。(後述
これ以外はこのまま記入します。

// OLED初期設定
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
  Serial.println(F("SSD1306:0 allocation failed"));
  for (;;); //エラーなら無限ループ
}

6.表示用コマンドの紹介

次にサンプル画面の各表示のコマンド(サンプルプログラム35行目~77行目)について紹介します。


①タイトル表示

まず、表示をするためのコマンドとして文字色の設定があります。
今回使用するものはモノクロなので全て白色として設定するため、サンプルプログラムの初期設定31行目で以下のように記入しています。
(カラー液晶の場合は「WHITE」の部分に個別で色を指定します。)

// OLED表示設定
display.setTextColor(SSD1306_WHITE);  //文字色

次に、サンプルプログラムからタイトル表示部を抜粋したものが以下になります。
文字サイズ「1」で「OLED/TEST」を表示し、文字サイズ「2」で「SSD1306」を表示しています。

display.clearDisplay();     //表示クリア

// タイトル表示
display.setTextSize(1);     //文字サイズ(1)
display.setCursor(4, 0);    //表示開始位置左上角(X,Y)
display.println("OLED");    //表示内容
display.setCursor(4, 10);   //表示開始位置左上角(X,Y)
display.println("TEST");    //表示内容

display.setTextSize(2);     //文字サイズ(2)
display.setCursor(39, 2);   //表示開始位置左上角(X,Y)
display.println("SSD1306"); //表示内容

文字を表示するための基本的なコマンドは以下になります。

display.clearDisplay() ;                   //表示クリア
display.setTextSize
文字サイズ ) ;
   //文字サイズを指定
display.setCursor ( xy ) ;              //座標を指定
display.println ( 表示内容 ) ;           //表示内容を指定(改行付き)
display.display () ;                           //表示実行

display.clearDisplay:表示を全てクリアします。
display.setTextSize:「文字サイズ」を数値で指定します。
 「文字サイズ」の数値は「1」を基準に数値の倍率で拡大されていきます。
display.setCursor:表示させたい位置を ( xy ) の座標で指定するコマンドです。
 座標の位置は文字の左上角になります。
canvas.println:表示内容を指定します「   」で挟まれた内容が表示されます。()
 改行なしの場合は「println」ではなく「print」とします。
display.display:このコマンドを実行する事で設定した表示内容を画面に表示します。

display.displayはサンプルプログラムでは全ての表示設定が終了した80行目で実行しています。基本的なコマンドになるのでここで紹介しておきます。

②ボタンの動作で内容が変化

ボタンの動作で表示内容が変化する部分を抜粋したものが以下になります。
「if文」で本体ボタンの状態に応じて表示内容を切り替えます。
本体ボタンを押すと「BTN = ON」と表示されます。
本体ボタンを離すと「BTN = OFF」と表示されます。

// 本体ボタンON/OFF状態表示
display.setTextSize(1);     //文字サイズ(1)
display.setCursor(5, 28);   //表示開始位置左上角(X,Y)
if (M5.Btn.isPressed()) {   //ボタンが押されていれば(ずっと)
  M5.dis.drawpix(0, dispColor(0, 0, 20));  //本体LED青
  display.println("BTN = ON");              //表示内容
} else {                    //ボタンが押されてなければ
  M5.dis.drawpix(0, dispColor(20, 20, 20)); //本体LED白
  display.println("BTN = OFF");             //表示内容
}

文字サイズ、表示位置、表示内容の指定方法は「①タイトルの表示」と同じです。

M5.Btn.isPressed」は「ATOM LITE」の本体ボタンの状態を取得するコマンドです。
M5.dis.drawpix」は「ATOM LITE」のフルカラーLEDを制御するコマンドです。

「ATOM LITE」の本体ボタン、フルカラーLEDの使い方は以下のリンクで詳しく紹介しています。

M5Stack 本体ボタンの使い方、ボタン操作関数一覧(Arduinoプログラミング)
M5Stackシリーズの本体ボタンは Arduino のコマンドで簡単に制御できます。「Lチカ」のサンプルプログラムを使用して紹介しますので用途に応じて使い分けられるようになりましょう♪
定番の Lチカ!(ATOM LITE編)で遊びながら自然と身につくプログラミング
プログラミング初心者ならとりあえず「Lチカ」やりましょう!LEDを点灯、消灯(チカチカ)させるものです。サンプルプログラムをコピペでとりあえず動作確認。LEDの色は数値を変えるだけ。いろいろ試して遊びながら学びましょう♪

③ボタンを押した回数を表示

ボタンを押した回数を表示する部分を抜粋したものが以下になります。
ボタンが押されるごとに変数「cnt」のカウント数を+1して表示しています。

// 本体ボタンON回数カウント表示
if (M5.Btn.wasPressed()) {  //ボタンが押されていたら(押された時だけ)
  cnt++;                    //カウント+1
}
display.setCursor(72, 28);          //座標を指定
display.printf("CNT=%04d\n", cnt);  //カウント数

文字サイズはこの前に既に「1」として設定されているので、ここでは指定していません。
表示位置の指定方法は「①タイトルの表示」と同じです。
表示内容はここでは「C言語」の標準出力である「printf」を使用しています。

display.printf ( “CNT=%04d\n” ,  cnt) ;  //カウント数
カウント数「cnt」が「10」の時の表示は以下になります。
CNT=0010

%04d」は「,」の後に指定している「cnt」の値を表示しています。
%d」ならそのまま(整数で)「10」を、「%4d」なら4桁(右揃え)で「    10」を、「%04」でゼロ付きで「0010」と表示されます。


④指定した座標から平行線

指定した座標から平行線を描く場合は以下のように指定します。

display.drawFastHLine(0, 40, 128, WHITE);  //線(指定座標から平行線)
display.drawFastHLine(x, y, 長さ); 

x, yで座標を指定して、その座標からの長さを数値で指定します。
はこの液晶はモノクロなのでWHITEとなります。


⑤始点終点を座標で指定した線

始点終点を座標で指定した線を描く場合は以下のように指定します

display.drawLine(0, 20, 128, 20, WHITE);   //線(始点終点指定)
display.drawLine(x1, y1, x2, y2, );

始点をx1, y1、終点をx2, y2で指定してそれぞれを結ぶ線を描きます。
はこの液晶はモノクロなのでWHITEとなります。

⑥指定した座標から垂線

指定した座標から垂線を描く場合は以下のように指定します。

display.drawFastVLine(64, 22, 17, WHITE);  //線(指定座標から垂線)
display.drawFastVLine(x, y, 長さ,); 

x, yで座標を指定して、その座標からの長さを指定します。
長さは指定した座標から下へ向けての指定となります。
はこの液晶はモノクロなのでWHITEとなります。

⑦円と塗り潰し円

円と塗り潰し円は以下のように指定します。

display.drawCircle(10, 55, 8, WHITE);      //円
display.fillCircle(30, 55, 8, WHITE);      //円(塗り潰し)
display.drawCircle(x, y, 半径, );
※塗り潰しはdisplay.fillCircleで指定

円の中心をx, yで指定して、半径を指定することで円を描きます。
はこの液晶はモノクロなのでWHITEとなります。

⑧三角と塗り潰し三角

三角と塗り潰し三角は以下のように指定します。

display.drawTriangle(46, 62, 54, 48, 62, 62, WHITE); //三角
display.fillTriangle(66, 62, 74, 48, 82, 62, WHITE); //三角(塗り潰し)
display.drawTriangle(x1, y1, x2, y2, x3, y3);
※塗り潰しはdisplay.fillTriangleで指定

座標 x1, y1x2, y2x3, y3 を結ぶ三角を描きます。
はこの液晶はモノクロなのでWHITEとなります。

⑨四角と塗り潰し四角

四角と塗り潰し四角は以下のように指定します。

display.drawRect(90, 47, 16, 16, WHITE);   //四角
display.fillRect(110, 47, 16, 16, WHITE);  //四角(塗り潰し)
display.drawRect(x, y, , 高さ, );
※塗り潰しはdisplay.fillRectで指定

四角の左上座標を x, y で指定して高さを指定して四角を描きます。
高さは指定した座標から下へ向けての指定となります。
はこの液晶はモノクロなのでWHITEとなります。

7.I2C通信のスレーブアドレス(0x3C/0x3D)について

SSD1306でI2C通信を行うために使用するスレーブアドレスは基本的に「0x3C」ですが、はんだ付けでチップ抵抗を付け替えて「0x3D」として使用することができるものもあります。

今回使用したSSD1306の「128×64」でも可能で、チップ抵抗は下画像のように基板裏側にあります。

OLED液晶SSD1306アドレス

4.7kΩのチップ抵抗のはんだ付け位置が「0x78」側か「0x7A」側かで以下のようにアドレスが決まります。

はんだ付け位置I2C通信スレーブアドレス
0x780X3C
0x7A0x3D

はんだ付け位置に表示されている内容とアドレスが同じだとわかりやすいのですが、違う表示になっています。
これは表示されているものがスレーブアドレスレジスタ(8bit)の16進数表記のためです。

SSD1306のデータシートを見るとスレーブアドレスのレジスタ構成は以下のようになっています。

OLED液晶SSD1306 スレーブアドレス構成

1~7ビット目(b1~b7)の7ビットがスレーブアドレスで、0ビット目(b0)は読み/書き選択ビットになっており、この0ビット目(b0)を含んだ8ビットの16進数表記が基板には表示されています。

プログラム内で指定するスレーブアドレスは0ビット目(b0)を除いた1~7ビット目(b1~b7)の7ビットの16進数表記となります。

1ビット目(b1)はアドレス選択ビットでチップ抵抗のはんだ付け位置で「0」か「1」かが決まります。

1~7ビット目(b1~b7)を以下のように2進数と16進数で表記するとわかりやすいです。

はんだ付け位置I2C通信スレーブアドレス
b1~b7のみ2進数表記
I2C通信スレーブアドレス
b1~b7のみ16進数表記
0x78b’0111100′0x3C
0x7Ab’0111101′0x3D

わかりやすいと言いつつもぱっと見ではわかりにくいですね・・・さらに確認したい方は16進数の計算できる計算機やアプリ等を使うと確認できます。

16進数で「0x78」は2進数で「b’01111000’」となり、0ビット目を除いた7桁は「b’0111100’」でこれを16進数に変換すると「0x3C」になるのが確認できると思います。

これは「0x78」の2進数「b’01111000’」を右へ1ビットシフト(一つずらす)したことと同じになり「b’00111100’」となり、同じように16進数に変換すると「0x3C」となります。

右に1ビットシフトするということは「0x78」を16進数の計算できる計算機で2で割ることと同じです。

実際に計算すると 0x78 ÷ 2 = 0x3C になるのが確認できると思います。
同様に 0x7A ÷ 2 = 0x3D となるのが確認できると思います。

SSD1306のI2C通信のスレーブアドレスは基本的には「0x3C」で覚えておけば大丈夫ですが、アドレスを選択できるもので基板裏に表示されているアドレスに設定しても使用できない場合は、16進数の計算機で2で割った数値を設定してみましょう。

8.2画面表示の方法

需要はないかもしれませんが・・・冒頭の画像でも使用している2画面表示する方法を紹介します。

下画像のように「SSD1306 128×64」を「Groveコネクタ」へ「SSD1306 128×32」を「G、5V、G25、G21」端子に差し込んで使用します。

OLED液晶SSD1306 2画面表示

I2C通信を使用するのでスレーブアドレスが異なるものを使用すればよいのですが、今回はスレーブアドレスが同じSSD1306を2つ使用して2画面表示しています。

「ESP32」系のマイコンが搭載された「ATOM LITE」にはI2C通信が2系統あり、同時に使用することができます。
この2系統のI2C通信を使用することで2画面表示が可能です。


サンプル画面を表示するプログラムは以下のようになります。「コピペ」して書き込んでください。

※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

#include <M5Atom.h>           //Arduino.h / Wire.h / FastLED.h含む
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h> //別途「Adafruit BusIO」ライブラリ必要

//OLED設定
#define SCREEN_WIDTH 128  // OLED 幅指定(メイン、サブ共通)
#define SCREEN_HEIGHT 64  // OLED 高さ指定(メイン)
#define SCREEN_HEIGHT1 32 // OLED 高さ指定(サブ)
#define OLED_RESET -1     // リセット端子(未使用-1)

// I2Cに接続されたSSD1306用 displayとdisplay1の宣言
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);   //メイン
Adafruit_SSD1306 display1(SCREEN_WIDTH, SCREEN_HEIGHT1, &Wire1, OLED_RESET);  //サブ

//ASCII文字 0x21~0x7e(94文字)
char str[] = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";

// 初期設定 --------------------------------------------------
void setup() {
  // 本体初期化(UART有効, I2C有効, LED有効)
  M5.begin(true, true, false);
  Serial.begin(9600);

  Wire.begin(26, 32);   //Grove端子をI2C設定(SDA,SDL)
  Wire1.begin(21, 25);  //サブ画面接続端子のI2C設定(SDA,SDL)

  // OLED初期表示
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306:0 allocation failed"));
    for (;;); //エラーなら無限ループ
  }
  // OLED1初期表示
  if (!display1.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306:1 allocation failed"));
    for (;;); //エラーなら無限ループ
  }
  // OLED表示(メイン画面)
  display.clearDisplay();               //表示クリア
  display.setTextSize(2);               //文字サイズ
  display.setTextColor(SSD1306_WHITE);  //文字色
  display.setCursor(0, 0);              //表示開始位置左上角(X,Y)
  display.println(str);                 //表示内容
  display.display();                    //表示実行

  // OLED表示(サブ画面)
  display1.clearDisplay();              //表示クリア
  display1.setTextSize(2);              //文字サイズ
  display1.setTextColor(SSD1306_WHITE); //文字色
  display1.setCursor(0, 0);             //表示開始位置左上角(X,Y)
  display1.println(str);                //表示内容
  display1.display();                   //表示実行
}
// メイン -------------------------------------------------
void loop() {
  delay(500);
}

5行目~13行目で、使用する2画面の画面サイズを設定します。
「WIDTH」は共通で「HEIGHT」と「HEIGHT1」を設定し、2系統のI2C通信設定「wire」と「wire1」の使用を設定、表示用コマンドとして「display」と「display1」を宣言します。

//OLED設定
#define SCREEN_WIDTH 128  // OLED 幅指定(メイン、サブ共通)
#define SCREEN_HEIGHT 64  // OLED 高さ指定(メイン)
#define SCREEN_HEIGHT1 32 // OLED 高さ指定(サブ)
#define OLED_RESET -1     // リセット端子(未使用-1)

// I2Cに接続されたSSD1306用 displayとdisplay1の宣言
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);   //メイン
Adafruit_SSD1306 display1(SCREEN_WIDTH, SCREEN_HEIGHT1, &Wire1, OLED_RESET);  //サブ

24行目~25行目で2系統のI2C通信設定「wire」と「wire1」で使用する端子をそれぞれ設定します。

Wire.begin(26, 32);   //Grove端子をI2C設定(SDA,SDL)
Wire1.begin(21, 25);  //サブ画面接続端子のI2C設定(SDA,SDL)

27行目~36行目で初期設定を行います。
「display」か「display1」の違いだけで他は同じ内容です。

// OLED初期表示
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
  Serial.println(F("SSD1306:0 allocation failed"));
  for (;;); //エラーなら無限ループ
}
// OLED1初期表示
if (!display1.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
  Serial.println(F("SSD1306:1 allocation failed"));
  for (;;); //エラーなら無限ループ
}

表示内容の指定は1画面の時と同じです。
「display」を使用するか「display1」を使用するかで、それぞれの画面の表示内容を指定できます。

同じ内容でよければ、下画像のようにブレッドボード等を使用して通信線をパラレル(並列)に接続するだけでも2画面表示は可能です。
(チップ抵抗の位置を付け替えてスレーブアドレスを別にすれば違う内容の表示も可能)
SSD1306並列接続で2画面

9.日本語表示

日本語については「lovyanGFX」が簡単に表示できるので紹介記事を追加しました。
以下のリンクで詳しく紹介しています。
SSD1306 OLEDで日本語表示 lovyanGFXの使い方
SSD1306でlovyanGFXを使用した日本語表示方法を紹介。ATOM LITEを使ってますがArduinoでも基本は同じで、他のOLEDでも初期設定を変えるだけです。

下画像のように日本語フォントデータを準備して読み込めば日本語表示することも可能ですが、私では説明しきれないところがありますので・・・ここでは紹介のみとさせていただきます。

こちらの「しかるのち」さんのサイトを参考にさせていただきました。
→ M5Atom:OLEDに日本語も表示しよう

OLED液晶SSD1306 日本語2画面表示

日本語フォントデータを準備して、書き込み時に使用する文字データをメモリ内に読み込んで使用することで日本語表示させることができます。

10.まとめ

SSD1306はマイコンボードに接続できる表示器 OLED(有機ELディスプレイ)として最も一般的なものです。

画面サイズ違いで2種類(128×64、128×32)あり、比較的安価(数個まとめて買っても1,000円前後)で購入でき、必要なライブラリを準備して、通信設定を行えば、簡単なコマンドで表示をすることができます。

I2C通信の物にピンヘッダやGroveコネクタ配線をはんだ付けしたものを準備しておけば「ATOM(S3) LITE」や「ESP32」「Arduino」等に表示器を追加したい時に手軽に実現できるのでとても便利に使えます。

コメント

  1. victories より:

    こんにちは。
    楽しく拝見しました。
    小さなディスプレイなのにたくさん表示できて便利ですね。
    有機ELなので液晶とかバックライトはないと思うのですが、どうなんでしょうか?

    • logikara より:

      こんにちは。
      ご指摘ありがとうございます。認識不足で申し訳ないです。
      タイトルから間違っていたわけですね(汗)。
      急いで修正いたしました。

  2. 古のちんぽぽ より:

    ArduinoやRaspberryPiを調べていてたどり着きました。ハードウェアとi/o周りはソフトウェア屋さんに渡す所までやってきたのですが、プログラム全くの初心者です。
    今まで小さなつまらない部分で引っかかって(例えばこの中だとなんでこんなピン番なの?みたいなw)何度となく投げ捨ててきましたが、この画面表示部分だけは説明が丁寧で理解できました。

    本の類も理解されている側の方が書くので、なかなかSDA,SCLのように1行ずつ説明されているテキストはないんですよね。これは、書いて頂いてる日本語訳から、setdataとsetclock?と勝手に推測できます。

    これでもまだやりたい動作ごとにコマンドを探すのはどうやるの?とか、
    SWITCHCAPVCCは、switch cap vcc??何?そもそもprintlnのln?f?って丸暗記で使えず病的なまでに気になる人にはプログラムって向いてないですね……とりあえず公式を覚えたらいいんだの数学みたいに、それで嫌になってしまう。英語はできるので、一旦バラした方がイメージしやすいんです。pppoeの正式名称を一般人が初見でイメージできますか?日本人ならぽぽぽぇって読むでしょみたいな。

    全部揃える値段考えたらちょっとやらないかなー○△□出た時点でタッチパネルかと思ってましたもん。年末にじっくり読ませていただきました。ありがとうございます。わかった気になれて楽しかったです。

    • logikara より:

      年末にコメントありがとうございます^^
      私もプログラミングはあまり得意ではないので、記事は基本的な内容が多いですが
      自分で理解しながら書いて、わかるようになった過程を漏らさず全部書くように心がけてます。
      そのせいでいつも記事が長くなりがちで、更新も時間がかかってますが、コメントいただけると励みになります。

      英語ができるようでうらやましい。
      確かにプログラムのコマンドや関数名は英語に由来するところが多いので、私はいつもgoogle翻訳片手にやってます(汗)
      「println」については英語的に考えると確かに意味不明ですね・・・。
      改行の指定は、プログラミングでは「¥n」や「\n」と書くので、「print」+「\n」で
      改行付き表示は「println」になったのだと思います。

      この記事はOLED表示について長々と書いていて、準備する部品も多いので、お試しでプログラミング体験なら以下の記事がおすすめです。
      https://logikara.blog/prog_lchika_atom/

      他にも「Raspberry Pi Pico」の記事も初心者の方にはおすすめです。
      https://logikara.blog/raspi-pico-init/
      動作確認については、どの記事もコピペ用サンプルプログラムを置いてますので、また見に来てください♪

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