2020年5月20日水曜日

OLED(SH1106 128x64 I2C)を噛じる

AliExpressを散歩してると
OLED moduleを見つけました。
巷ではよく使われてるやつですが、
マーティーは、まだFull Graphicのを使ったことないのです^^;

買ったのは、1.3inch 128x64 IIC I/Fのです。
US$ 2.67(18% OFF、送料 $0.29)

で、早速、テスト動作させようと思ったけど
IICアドレスがどこにも書いてありません。
どうも、基板の裏のアドレス設定は、これが一般的らしいのですが、
マーティーに届いてるのは、袋のラベルには、
IIC OLED「SH1106」とだけ
基板の裏が、異なってるんです。
どうやら、この2つのチップで調整するらしい
ということは、4通りかな?
Google先生に聞くも、設定情報を見つけれずにいたら
i2c_scanner」ってのが見つかりました!
下の方に行って
スケッチをコピーして~

Arduino IDE Ver.1.8.3で新規作成して、貼り付けます。
「#include <Wire.h>」見たことないな~
Arduino Unoにして
ちょっと[検証・コンパイル]だけしてみます。
何事もなく通りました!
何も環境を追加しなくても大丈夫そうです。

次に気になるのが、電源電圧です。
どこで見つけたか忘れましたが、ほぼこの回路図のようです。
「SSH1106」とあるけど「SH」の間違いでしょう。
左下に3.3VのRegulatorを積んでますね~
IICアドレス調整のパターンは載ってません(T_T)
SH1106のDatasheetは、このPDFです。

マーティーが入手したボードにもそれっぽいのが付いていますが
シルクが「Q1」ってのが気になります。
三端子レギュレータだったら普通「U1」なんだけどな~
どうしても気になるので、写真で拡大!
「662K」と読めます。
ググってみると、ありました!
トレックス・セミコンダクター株式会社のこのXC6206シリーズ
低ESRコンデンサ対応 正電圧レギュレータ
日本の会社ですね~ 頑張れ日本!(^O^)/
Datasheetは、ここのPDFです。
入出力間電圧:250mV の低損失型です。
P14をみると、のSOT-23パッケージのマーキング「662K」意味がわかりました。
1番目の「6」:製品番号(XC6206Pxxxxxシリーズ)
2番目の「6」:電圧 3.1~6.0V(入力のことでしょう)
3番目の「2」:出力電圧 3.3V
4番目の「K」:製造ロット

ということで、やっと、安心してVccに5V印加できます^^;
Arduino UNOとの結線図です。
 OLED    Arduino
  Vcc  ・・・  5V 
  GND ・・・ GND
  SDA ・・・  A4
  SCL  ・・・  A5

ちなみに、Fritzingのパーツデータは、ここから
「SSD1306 128x64」をダウンロードしました。
Arduino UNOと空中配線して、
PCとUSBで接続して
Arduino IDE Ver.1.8.3を起動!
[シリアルモニタ]を起動します。
ん?何も反応しないと思ったら
115200bpsにしてました(-_-;)
9600 bpsに変更すると
メッセージがでました!
I2C address 0x3C
5秒毎に更新されるので、同じものがどんどん出てきます。
この2つのチップ位置を変えると変更できるのでしょうが
今回は、面倒なのでパス(-_-;)
ようやく、スケッチを試せます。
が、どうやら、多く見かけるGitHubのライブラリ
「Adfruit SSD 1306」と「Adfruit GFX Library」は、
SSD1306専用のようです(T_T)

ここに、両方対応しているドライバがあるな~
Supported OLED display chip: SSD1306 or SH1106.
Supported Interface: I2C (internal driven)
実は、これ、マーティーのでは、動きませんでした。まあ記録です。
そのサイトからGitHubの方に飛ぶと、使い方がありました。
スケッチ上でI2Cアドレスやピクセル数も記述できるようです。

Branchの所を見ると
Version 1.0.0だけです。
「arduino-lib-oled-master.zip」をダウンロードします。
執筆時点では、最初のサイト(www.arduinolibraries.info)の
「OLED_SSD1306___SH1106-1.0.0.zip」と中身は同じでした。
Arduino IDE(Ver.1.8.3)で
[スケッチ]-[ライブラリをインクルード]の
[.ZIP形式のライブラリをインストール]して
サンプルを実行しようと
[スケッチの例]の[OLED SSD1306 - SH1106]を見ると、
ファイル名が妙で「WIFI-Kit-8」ってのが頭についてます。
WIFIモジュールがないとダメなんだろうか?
取り敢えず、開きます。
ざっと中身を見ると
WIFI関連のスケッチはなさそうなので、何か表示されるでしょう。
[検証・コンパイル]してみると
エラーがでました(T_T)
*********
Arduino:1.8.3 (Windows 10), ボード:"Arduino/Genuino Uno"
~~~
スケッチをコンパイルしています...
~~~"C:\Users\marty\AppData\Local\Temp\arduino_build_415961\sketch\WIFI-Kit-8-DEMO.ino.cpp.o"
In file included from C:\Users\marty\Documents\Arduino\libraries\arduino-lib-oled-master\examples\WIFI-Kit-8-DEMO\WIFI-Kit-8-DEMO.ino:2:0:

C:\Users\marty\Documents\Arduino\libraries\arduino-lib-oled-master\src/oled.h:306:18: error: no members matching 'Print::printf' in 'class Print'

     using Print::printf;

次のフォルダのライブラリarduino-lib-oled-masterバージョン1.0.0を使用中:C:\Users\marty\Documents\Arduino\libraries\arduino-lib-oled-master 
exit status 1
ボードArduino/Genuino Unoに対するコンパイル時にエラーが発生しました。
*********

「oled.h」の306行目の「printf」がエラーになってるようです。
「oled.h」ファイルは、
[C:\Users\marty\Documents\Arduino\libraries\]配下の
[arduino-lib-oled-master\src]にあります。
「oled.h」を見てみます。
エラーが出た「printf」の306行目は、これだけですね~
取り敢えず、そのまま。
で、最初の方を眺めてると
@param isSH1106 Must be true=SH1106 chip, false=SSD1306 chip
とあったので
height=32, bool isSH1106=false
⇒ height=64, bool isSH1106=true
に変更して、保存して~
再度
「WIFI-Kit-8-DEMO」を[検証・コンパイル]してみます。
が、エラーは、消えず(T_T)

サンプルスケッチをここまで削っても
*********
#include <Arduino.h>
#include <oled.h>

void setup()
{
    display.begin();   
}

void loop()
{
}
*********

エラーだあ~(T_T)
どうやらArduino UNOでは、ダメなようです。
*********
Arduino:1.8.3 (Windows 10), ボード:"Arduino/Genuino Uno"
~~~
GetFileAttributesEx C:\Users\marty\AppData\Local\Temp\arduino_cache_493885: The system cannot find the file specified.

ボードArduino/Genuino Unoに対するコンパイル時にエラーが発生しました。
*********

ちなみに「WIFI-Kit-8」ってのは、これのようです。
このライブラリは諦めます(-_-;)
[OLED SSD1306 - SH1106]ライブラリのUninstallは、
[C:\Users\marty\Documents\Arduino\libraries\]配下の
[arduino-lib-oled-master]フォルダごと削除して、
Arduino IDEを再起動します。

さて、どうしたもんか?
色々探してると、GitHubのこっちがいけそうな予感^^;
多くのDisplayに対応してて「SH1106」も一覧にあります。
Arduino IDEのlibrary managerからinstallできると書いてあります。
右側の「Installation(Arduino IDE)」から飛んでいくと
やったことある手順です。
では、Arduino IDE(Ver.1.8.3)を起動して
[スケッチ]-[ライブラリをインクルード]-[ライブラリを管理...]
します。
しばらくは、下のバーが進行が終了したら
右上の欄に「u8g2」を入力して、
出てきた「U8g2 by oliver」(赤枠部)をクリックすると
右下に[インストール]が現れるのでクリックします。
サンプルスケッチの数字で始まる名前がダメだと警告が出ました。
たぶん、Arduino IDEバージョンが古いからでしょう?
[OK]します。
「U8g2 by oliver」の横に INSTALLED が出てれば
インストールできてるので[閉じる]します。
また、さっきの警告が出たので[OK]
[スケッチ]-[ライブラリをインクルード]のリストの一番下に
[U8g2]が追加されてます。
[ファイル]-[スケッチの例]のリストの下の方にも
[U8g2]が追加されています。
では、[スケッチの例]-[U8g2]-[u8x8]の
[HelloWorld]にします。
ボード設定は、Arduino UNOです。
まずは、[検証・コンパイル]
あちゃ~またエラー(T_T)
落ち着いてスケッチを眺めると
Display Typeが全てコメントアウトされていました(-_-;)
マーティーのは、SH1106 128x64 I2Cのなので
63行目のSH1106のI2Cのコメントを外して、
再度、コンパイル!
無事通りました\(^o^)/
スケッチを眺めますが、I2Cアドレスを記入する所がありません。
取り敢えず、Arduino UNOに書き込んでみると
お~っ!動きました!
ただの「Hello World」ですがね^^;

スケッチのコメントと不要な部分を削ぎ落とすと
結局、これだけのスケッチなんですね。
PICでは随分複雑なので、こんなにも簡単と(・o・)
*********
#include <Arduino.h>
#include <U8x8lib.h>

U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);

void setup(void)
{
  u8x8.begin();
  u8x8.setPowerSave(0); 
}

void loop(void)
{
  u8x8.setFont(u8x8_font_chroma48medium8_r);
  u8x8.drawString(0,0,"Hello World!");
  delay(2000);
}
*********

ちょっと調べてみると、ここに(PICの話ですが)
アドレス部が全て「0」の時は「General Call Address」と呼ばれ
「一斉同報」する。
とあるので、それを使ってて、I2Cアドレス設定が無いものと考えられます。

***訂正(2020.5.24)***
上の一斉同報という予想は間違いでした(-_-;)
U8g2ライブラリでは、I2Cアドレスを指定しない場合、
「u8g2.begin();」した時に、小さいアドレスから検索をかけて、
反応のあった一番小さいアドレスが自動的に指定される。とのことです。

ここにu8g2での指定の方法があり、
U8x8ライブラリでも同様に指定できたので追記します。
マーティー工房にはOLEDが1個しかないので
別のアドレス、I2Cアドレス:0x3D にしてみると
画面真っ黒になりました。
*********
  u8x8.setI2CAddress(0x3D * 2);  //I2Cアドレスを2倍して指定する仕様
  u8g2.begin();
*********

正しいI2Cアドレス:0x3Cにすると正常に表示されました。
*********
  u8x8.setI2CAddress(0x3C * 2);  //I2Cアドレスを2倍して指定する仕様
  u8g2.begin();
*********
ということで、U8x8ライブラリでも
このコードでI2Cアドレスを設定できることが確認できました。
***追記ここまで***

で、またまた、この警告が煩いので
フォルダ
[C:\Users\marty\Documents\Arduino\libraries\U8g2\examples\u8x8]
の中の[16x16Font]フォルダ名の頭に「_」アンダーバーを追加して
[_16x16Font]にしました。

次にグラフィックの方も試したいので
[スケッチの例]から
[full_buffer]-[U8g2Logo]ってのをやってみます。
まずは、Display Typeを設定。
SH1106 128x64 I2Cを探して
76行目のコメントアウトを外します。
*********
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
*********
今度は、I2Cアドレス設定があるハズなのでじっくり探すと
272行目!
###このアドレス指定は間違ってました(2020.5.22)###
*********
digitalWrite(9, 0);  // default output in I2C mode for the SSD1306 test shield: set the i2c adr to 0
*********
デフォルトでは、アドレス「0」になってるので、
一番最初に確認したアドレス「0x3C」に変更します。
*********
digitalWrite(9, 0x3C);
********* 
***上のアドレス指定の修正です(2020.5.22追記)***
U8g2ライブラリでは、I2Cアドレスを指定しない場合、
「u8g2.begin();」した時に、小さいアドレスから検索をかけて、
反応のあった一番小さいアドレスが自動的に指定される。とのことなのです。

で、ここに指定の方法があります。
「u8g2.begin();」に前に、このコードで指定できるということです。
「I2Cアドレスを2倍して指定する仕様」ってのは妙ですが、
マーティー工房にはOLEDが1個しかないので試してません(-_-;)
*********
  u8g2.setI2CAddress(0x3C * 2);  //I2Cアドレスを2倍して指定する仕様
  u8g2.begin();
*********
YYさんいつも情報ありがとうございますm(_ _)m
***追記ここまで***

***追伸(2020.5.24)***
上記の追記で
u8g2.setI2CAddress(0x3D * 2);  //・・・画面真っ黒になる
u8g2.setI2CAddress(0x3C * 2);  //・・・正常表示
になったので
このコードでI2Cアドレスを設定できることが確認できました。
***追伸ここまで***


[検証・コンパイル]してみます。
コンパイルが、えらく長くかって、無地終わりましたが、
メモリの残りが少ないと注意がでてます。
Arduino UNO R3ですが、ローカル変数が506バイトしか残ってないですね~(T_T)
いざ、書き込み!
書き込みが終わるとRESETがかかって
お~~っ!
これは、一発で動きました\(^o^)/
なかなか面白そうですね~
リビングのPCの上でも遊べそうだし、
これはしばらくハマりそ~^^;

2 件のコメント:

昔青年 さんのコメント...

LCDいじりは楽しいですね!
表示された瞬間は、ガッツポーズです。
TFTLCDでカラーで測定器の表示部を作られたら最高ですね。
当方はもっぱら、先輩諸氏のおこぼれをいただく程度ですが(笑)
マーティーさんのは、解説が詳しいので勉強になります。

マーティーの工房日誌 さんのコメント...

昔青年さん、こんにちは!
いやいや、早合点の間違いも多いの気をつけてくださいね(-_-;)
カラーLCDでオリジナル測定器とかできたらいいですね~
でもメモリ食うからESP32とかいうやつにしないとダメですかね?