ESP8266搭載D1 miniでI2C接続のOLEDを使う - SDA/SCLのピン変更

Oled

 ESP8266を搭載したWemos D1 miniというボードで いろいろテスト中。液晶に各種センサーで取得した情報を、PCではなくデバイス側で見られるようにしたく思い、AliExpressで300円以下の激安OLEDディスプレイモジュールを購入。I2C接続しようと思ったらちょっとはまった。

 購入したのは128×64のほんとに小さなOLEDディスプレイモジュール。画面サイズは0.96インチだそうだ。で、このモジュール。I2Cを使う。


 使用中のD1 miniにはすでに複数のセンサーだとかLEDがつながっており、空きのピンは3つのみ。最初は何も考えずに埋めていったのだけど、それはちょっとまずかったようだ。

 D1 miniに限らずArduino互換ボードの多くはI2Cで使われるSDA、SCLのピンが決まっている模様(D1 miniはSCLがD1、SDAがD2)。当方ではそのうち1つをすでに使ってしまっている。ブレッドボードじゃなく、プロトシールドにセンサーなどをはんだ付けしてしまっており、それらのピンはすでに動かせない。テストし始めたころはI2Cを使うことがあろうとは考えてもいなかった(そういうものの存在すらも知らなかった)ので、ちょっと後悔。

 しかし、調べてみると決まったピン以外でも問題ないよ、という情報を発見。プログラムで指定できればいいということなのだろう。

 I2Cは温度・湿度・気圧センサーのBME280で使ったことがあった。使用したライブラリではピンが指定できたので、空きのピンにうまいこと設定できたので、問題はなかった。

 このOLEDディスプレイモジュールはというと、どうか? ライブラリは以下の2つを使う。

 Adafruit SSD1306
 Adafruit GFX-Library

 参考にしたのは以下のQiitaの記事。

 ArduinoでOLEDディスプレイを試す – Qiita

 ここに気になる記述が。

「Adafruit SSD1306」は解像度が異なる種々のディスプレイに対応するためにヘッダーファイルを直接編集するのが公式の手順なのですが、次のissueでスケッチ側で制御できるような仕様変更がコメントで提案されています。

 見てみると、確かにヘッダーファイルの編集は不要になってる。昨年の11月のバージョンアップで仕様がけっこう変わってるそうだ(バージョン1.2以降)。で、コードを見てもピンの指定方法が見つからない。というかわからない。読み取れない。

 そこで、かなり検索を続けていると、答えは別のところにあった。Wireライブラリ側で指定できるのだそうだ(この言い方が合っているのかもわかりませんが)。

 Mutiple I2C Devices with SAME Address – SHT21/HTU21D – Everything ESP8266

 上記の例では、同じI2Cモジュールを複数切り替えて使うという話。以下のような感じでいけるっぽい。

 Wire.begin(4, 5);

 試した。うまくいった。

 というわけで、以下に雑なサンプルを挙げておく。

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// Reset pin # (or -1 if sharing Arduino reset pin)
#define OLED_RESET     -1 // もとは4 リセットピンはこの基板では使わないので -1 に
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//I2Cのピンを指定
const int i2c_sda_pin = D3; // SDA
const int i2c_scl_pin = D1; // SCL
void setup() {
Wire.begin(i2c_sda_pin ,i2c_scl_pin); //I2Cのピン指定
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) { // 0x3Dから変更
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
} else {
Serial.println(F("SSD1306 OK"));
}
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(5000); // Pause for 5 seconds
// Clear the buffer
display.clearDisplay();
}
void loop() {
display.clearDisplay();  // 画面クリア
display.setTextColor(WHITE);// テキスト色
display.setTextSize(4);  // テキストサイズ
display.setCursor(0, 0);  // テキスト開始位置
display.println("OLED"); //文字列
display.display();// 描画バッファの内容表示
display.setTextSize(2);  // テキストサイズ
display.setCursor(0, 32);  // テキスト開始位置
display.println("0123456789"); //文字列
display.println("ABCDEFGHIJ"); //文字列
display.display();// 描画バッファの内容表示
delay(5000);
//書き換えのため下半分だけ消去(黒で塗りつぶし)
display.fillRect(0, 32, 128, 32, BLACK); //(左上x, 左上y, 幅, 高さ, 線の色)
display.setTextSize(2);  // テキストサイズ
display.setCursor(0, 32);  // テキスト開始位置
display.println("abcfefghij"); //文字列
display.println("0123456789"); //文字列
display.display();// 描画バッファの内容表示
delay(5000);
display.clearDisplay(); //全部消去
}

 上記コードにはサンプルからのものも含め、ちょっとしたコメントを入れてある。実際に動作している模様は以下のビデオで。フリッカーが出てるのは、カメラの設定を手抜きしたため。実物を見るとそれは感じない。くっきりきれいなディスプレイです。保護シールもはがせばよかったかなあ。


128×64 OLED display module test

 そんなわけで数カ月後の自分のためにメモ。

 Amazonにも似たようなのが売っている。

コメント