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

コンピュータ、組み込み

RP2040 picoを使って単色OLEDモジュールの表示制御をします。
使用するモジュールには、I2Cで制御するモデルと、SPIで制御するモデルがありますが、
今回はI2Cのモデルを使用します。

紹介するもの

OLED SSD1306 0.96inch

特徴

4線式I2Cにより動作します。
単色表示

製品情報
サイズ0.96inch
解像度(X, Y)128, 64
表示色白、青、黄、黄+青
黄+青の場合、それぞれのエリアが決まっていて、
色の変更はできないようです。
電源電圧3.3 – 5.0V
通信方式I2C (アドレスは 0x3c, または0x3dのどちらかを選択)
SPI
ドライバSSD1306
入手電子部品ショップ、ネットショップ
入手性は非常に良く、安く大量買いする場合はAli Express
外観

前面

背面

使用感

とても小さいモジュールです。
I2Cでの使用では少ない配線で簡単に表示ができるので、プログラムのデバッグや結果の表示などに重宝します。
各種モジュールの中では使用頻度は高い部類になるので、1つは持っておきたいモジュールです。

準備

OLEDのI2Cアドレス確認

OLEDモジュールの裏面を確認して、現在のI2Cアドレスの設定を確認します。
使用するモジュールのアドレスは、0x3cまたは0x3dのどちらかを選択できます。
今回は両方のアドレスの使い方を紹介しますが、はんだ作業が必要となるので自信のない方は現在の設定のまま使用することをお勧めします。

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

ライブラリ

ライブラリは以下2つのライブラリを使用します。

ライブラリAdafruit SSD1306 by Adafruit Ver2.5.1
Adafruit GFX Library Ver 1.11.1
※Verは 記事編集時 2022/6/19 のバージョンです。
赤太字箇所をライブラリマネージャの検索欄に入力することで検索できます。

使い方

I2Cによる表示

I2C0を使ったOLEDの表示です。
一番多く使われると思います。

配線

RP2040 picoワイヤ色SSD1306(0x3c)
3.3VVCC
GNDGND
GP0SDA
GP1SCL
()はI2Cアドレス

スケッチ

//Programing by たまねぎ
//【スケッチの説明】
//RP2040 CPU搭載基板で使用できます。
//OLED画面に "TAMANEGI"
//使用しているI2CラインとI2Cアドレスを表示させます。
//
//【準備】
//・RP2040 pico側
//本スケッチでは SDA に GP0, SCL に GP1 を使用します。
//・SSD1306 OLED側
////I2Cアドレスは 0x3c 
//
//【バージョン情報】
// 2022/6/19 : 新規

#include <SPI.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() {
}

結果

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

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

配線

RP2040 picoワイヤ色SSD1306(0x3c)SSD1306(0x3c)
3.3VVCCVCC
GNDGNDGND
GP0SDASDA
GP1SCLSCL
()はI2Cアドレス

スケッチ

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

結果

I2C0を使ったデュアルモニタ

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

配線

RP2040 picoワイヤ色SSD1306(0x3c)SSD1306(0x3d)
3.3VVCCVCC
GNDGNDGND
GP0SDASDA
GP1SCLSCL
()はI2Cアドレス

スケッチ

//Programing by たまねぎ
//【スケッチの説明】
//RP2040 CPU搭載基板で使用できます。
//I2Cアドレスの違うOLED画面を2つ使用し、個別に表示します。
//それぞれのOLED画面に "TAMANEGI"
//使用しているI2CラインとI2Cアドレスを表示させます。
//
//【準備】
//・RP2040 pico側
//本スケッチでは SDA に GP0, SCL に GP1 を使用します。
//・SSD1306 OLED側
// I2Cアドレスは 0x3c と 0x0dを設定します。
//
//【バージョン情報】
// 2022/6/19 : 新規

#include <SPI.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_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() {
}

結果

I2C1による表示

RP2040 pico にはI2CのラインがI2C0 と I2C1 の2本あります。
I2C1を使った表示について記載します。

配線

RP2040 picoワイヤ色SSD1306(0x3c)
3.3VVCC
GNDGND
GP2SDA
GP3SCL
()はI2Cアドレス

スケッチ

//Programing by たまねぎ
//【スケッチの説明】
//RP2040 CPU搭載基板で使用できます。
//OLED画面に "TAMANEGI BLOG"と表示させます。
//
//【準備】
//・RP2040 pico側
//本スケッチでは SDA に GP2, SCL に GP3 を使用します。
//・SSD1306 OLED側
////I2Cアドレスは 0x3c 
//
//【バージョン情報】
// 2022/6/19 : 新規

#include <SPI.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, &Wire1, OLED_RESET);
                                        //表示制御にはAdafruit製 SSD1306を使用する。
                                        //初期化時には I2C1を使用する (Wire)
                                        
void setup() {
  
  Wire1.setSDA(2);                       //I2C1で使用するGPは SDA = 2, SCL = 3
  Wire1.setSCL(3);

  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("I2C1 0x3c"));

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

void loop() {
}

結果

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

同じI2CアドレスのOLEDを、別ラインのI2Cに配線します。
同じI2Cアドレスであっても、別のラインのため干渉しないで個別の表示ができます。

配線

RP2040 picoワイヤ色SSD1306(0x3c)SSD1306(0x3c)
3.3VVCCVCC
GNDGNDGND
GP0SDA
GP1SCL
GP2SDA
GP3SCL
()はI2Cアドレス

スケッチ

//Programing by たまねぎ
//【スケッチの説明】
//RP2040 CPU搭載基板で使用できます。
//同じI2CアドレスのOLED画面を2つ使用し、個別に表示します。
//それぞれのOLED画面に "TAMANEGI"
//使用しているI2CラインとI2Cアドレスを表示させます。
//
//【準備】
//・RP2040 pico側
//本スケッチでは I2C0 には SDA に GP0, SCL に GP1 を使用します。
//I2C1 には SDA に GP2, SCL に GP3 を使用します。
//・SSD1306 OLED側
// I2Cアドレス2個ともに 0x3c。
//
//【バージョン情報】
// 2022/6/19 : 新規

#include <SPI.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をコピーしました