やっぱ表示モノは面白いです。こんなに嵌るとは思いませんでした^^;
ちょっと思いつきで、1個のArduinoで複数のOLEDを制御してみました。
まずは、[スケッチの例]のリストの下の方のスケッチ例の
[sh1106_128x64_i2c]を開いて
シリアルを複数のやる時は、
mySerial.begin(9600);
とかで名前を変えられてたので
たぶん、同じ様にいけるんじゃないかな?
一番怪しいのは、この32行目*********
display(OLED_RESET);
⇒
display_01(OLED_RESET);
*********
に変えてみます。
で、スケッチ全体の
「display.」⇒「display_01.」に
こんな風に置換して
いざ、コンパイル!
お~っ!通りました!
動くかな~
書き込んでみると~
動きますね~\(^o^)/
上手くいったので
[スケッチの例]のリストの下の方の
[sh1106_128x64_spi]を開きます。
SPIは、ピン数が多い分、引数も多いです。
実は、最近、SPI I/FのOLEDが届いたのです。
ドライバは、SH1106の128x64です。
スケッチと順番が異なってて配線を間違えそうなので
シルク表示と同じ順番になるように書き換えて、PINもPD8~PD12にします。
SCK:OLED_SCK
SDA:OLED_MOSI
RES:OLED_RESET
DC :OLED_DC
CS :OLED_CS
スケッチのここを書き換えるだけです。
配線して書き込むと、無地動作しました。
BLUEのOLEDで、目視では、真っ青ですが、写真ではかなり白っぽいです。
そのSPI用のExample[[sh1106_128x64_spi]の
フラッシュメモリ、グローバル変数(RAM)の使用量です。
I2C用のExample[[sh1106_128x64_i2c]も
フラッシュメモリ、グローバル変数(RAM)の使用量は全く同じです。
このまま、SPI用とI2C用を合体すると
使用量オーバーは確実のようです。
では、I2CのExampleスケッチから
ロゴ、円、TEXTなどを取り去って、LINEアートだけにして
コンパイル!
ん~ん、フラッシュメモリの使用量はかなり減ったけど
グローバル変数使用量が思ったより減ってないですね~(T_T)
まあ、やってみることにします。
LINEアートだけにしたI2C用のスケッチに
SPI用を追加していきます。
SPI.h:SPI用、Wire.h:I2C用 です。
1つ目のOLEDは、I2Cタイプで、「display_01」にします。
2つ目のOLEDは、SPIタイプで、「display_02」にします。
void setup() は、これです。
*********
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH1106.h>
#define OLED_01_RESET 4
Adafruit_SH1106 display_01(OLED_01_RESET);
#define OLED_02_CLK 8
#define OLED_02_MOSI 9
#define OLED_02_RESET 10
#define OLED_02_DC 11
#define OLED_02_CS 12
Adafruit_SH1106 display_02(OLED_02_MOSI, OLED_02_CLK, OLED_02_DC, OLED_02_RESET, OLED_02_CS);
void setup() {
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
display_01.begin(SH1106_SWITCHCAPVCC, 0x3C); // initialize for OLED_01 I2C
display_02.begin(SH1106_SWITCHCAPVCC); // initialize for OLED_02 SPI
}
*********
display_01 と display_02 に同じものを交互に描画するだけです。
まずは、コンパイルだけ
おっ!グローバル変数は、まだ余裕があります\(^o^)/
書き込んでみると~
お~~っ!意外やあっけなく動きました\(^o^)/
今回はArduino NANOにしております。
コンパクトにOLEDメーターができそうです。
ちなみに、その後、わかったのですが
SPI.h:SPI用、Wire.h:I2C用 がなくても動きました。
OLED制御分までAdafruitライブラリに含まれてるんですね。
まあ、メモリ使用量は変わらないので、お守りに入れておいてもいいでしょう(-_-;)
所が~~~
display_01には、ラインアートだけ
display_02には、TEXTだけを表示させようとしたら、
後で思うに、何でこんな行に追加したんだろう(-_-;)
display_01にライン1本描画する毎に
display_02にTEXTを出したかった気もするが・・・(-_-;)
*********
void loop() {
//* for文の後に置いても、No.1にも表示される
display_02.setTextSize(1);
display_02.setTextColor(WHITE);
display_02.setCursor(80, 1);
display_01.clearDisplay();
display_02.clearDisplay();
for (int16_t i=0; i<display_01.width(); i+=4) { //・・・A
display_01.drawLine(0, 0, i, display_01.height()-1, WHITE);
display_02.print("No.2 SPI");
display_01.display();
display_02.display();
}
for (int16_t i=0; i<display_01.height(); i+=4) {//・・・B
display_01.drawLine(0, 0, display_01.width()-1, i, WHITE);
display_01.display();
}
delay(250);
}
*********
display_01:左、、display_02:右 ですが
左にもTEXT「No.2 SPI」が描画されて、
右には、上のスケッチ「・・・A」のforルーチンのラインが描画されるのです(T_T)
「・・・B」のforルーチンのラインは左だけに描画されます。
そこでTEXT表示ルーチンを「・・・A」のforルーチンの外に出し後に置くと
*********
void loop() {
display_01.clearDisplay();
for (int16_t i=0; i<display_01.width(); i+=4) { //・・・A
display_01.drawLine(0, 0, i, display_01.height()-1, WHITE);
display_01.display();
}
display_02.setTextSize(1); //★ FONT Size x1
display_02.setTextColor(WHITE); //★
display_02.setCursor(80, 1); //★
display_02.clearDisplay();
display_02.print("No.2 SPI"); //★・・・どの場所においてもNo.1にもTEXTが表示される
display_02.display(); //★
for (int16_t i=0; i<display_01.height(); i+=4) { //・・・B
display_01.drawLine(0, 0, display_01.width()-1, i, WHITE);
display_01.display();
}
delay(250);
}
*********ラインアートのスケッチ「・・・A」部は、
右:display_02には描画されなくなりました。
が、右:display_02 だけのTEXT「No.2 SPI」描画のはずが
左:display_01にも「No.2 SPI」が描画されるのです(T_T)
ラインアートのスケッチ「・・・B」部は、右:display_02には描画されません。
もしかして「print()」命令は、複数対応できないのかな~(T_T)
ここまで来ると何とかしたいですね~
気分転換してもうひと頑張りします^^;
・・・そうだ!左のdisplay_01にもTEXTを描画してみよう
*********
void loop() {
display_01.clearDisplay();
display_01.setTextSize(1);
display_01.setTextColor(WHITE);
display_01.setCursor(80, 30);
display_01.print("No.1 I2C");
display_01.display();
for (int16_t i=0; i<display_01.width(); i+=4) {
display_01.drawLine(0, 0, i, display_01.height()-1, WHITE);
display_01.display();
}
display_02.clearDisplay();
display_02.setTextSize(1);
display_02.setTextColor(WHITE);
display_02.setCursor(80, 1);
display_02.print("No.2 SPI");
display_02.display();
for (int16_t i=30; i<64; i+=2) {
display_02.drawLine(0, i, 127, i, WHITE);
display_02.display();
}
*********
上手くいきました\(^o^)/
最初からdisplay_01とdisplay_2を分ければ良かったんですね~
このスケッチ全体は、Google Driveのここの
「MultiOLED_I2C_SPI_D.ino」です。
最初に入れたTEXTの位置が悪くて、ちょっと手こずりましたが(-_-;)
本命の、1つのArduinoで2つのメーターをやりたいと思います。
まずは、この時やったVolt MeterをI2C-typeでは、
メモリ使用量は、これです。
次は、その後やったタコメーターをSPI-typeでやると、
メモリ使用量は、これです。
単純に足し算されると完全にメモリオーバーです。
上の2つを夫々、display_01、display_02にして
変数名が被らないように修正して、単純に合体します。
ぎりぎりでもいいからオーバーしないことを祈って、コンパイル!
おっ!オーバーしてないです。これはいけますね~
いざ、書き込み!・・・・・・動きました!
NANOの入力pinを指で触るとメーターが振れるので
正常に動作してます\(^o^)/
1個のArduino NANOで、2個のOLED(I2CとSPI)を制御できました。
NANOだとボードも小さいのでコンパクトに納められそうです。
上記のようなメーターであれば、3個までメモリはもちそうですね~
スケッチは、Google Driveのここの
「MultiOLED_I2C_SPI_Volt_Tacho_Meter_A.ino」です。
USBは書き込み時しか使わないので
同じATmega
NANOの価格とほぼ同じですが、この辺りをポチっておきます^^;
US$ 1.25(21% OFF、送料 $ 0.62)
書き込み用のUSB~Serial変換器は、使い慣れたCH340Gのをポチッ!
US$ 0.82(10% OFF)
こうなると、3つやってみたくなりました^^;
I2Cは、チップ抵抗を移動してアドレス変えないといけないので
SPI 2個とI2C 1個でやろうと思います。
上の2個の時のVolt MeterとTachometerに加え
3個目にもVolt Meterを追加しました。
コンパイル!
お~っ!2個の時からフラッシュメモリ 73 ⇒ 81%と
グローバル変数 69 ⇒ 71%!思ったより増加が少ないですね~^^;
で、2個のSPI typeの配線は、
CSだけOLED毎に独立させればいいかとやったのですが、
display_0x.begin(SH1106_SWITCHCAPVCC);
を最後にやったSPI OLEDだけ描画され、他方のSPI typeは真黒なのです。
DCも分離してみますが、ダメです(T_T)
ん~ん SPIができないはずはない、Google先生に聞いてみると
ここにSPI OLED 2個の結線図がありました。
眺めると、まさかのRESETが独立配線になってます(・o・)
で、結局、CSとRESETの2本を独立に配線にしたら
3個で動きました\(^o^)/
左 WHITE:I2C type(display_01)
右 BLUE:SPI type(display_02)
中 BLUE:SPI type(display_03)
中央のは表示だけ「A」で中身は電圧計です^^;
スケッチは、Google Driveのここの
「MultiOLED_I2C_SPIx2_Volt_Tacho_Meter_A.ino」です。
配線はこれです。
SPIのOLEDは、Fritzingパーツがないですね~
仕方ないのでGIMPでパーツ作って、パワポで作図です(T_T)
ここまできたら、調子に乗って限界まで!
4個いけそうです^^; 同じく電圧計スケッチを追加して
2 ⇒ 3 ⇒ 4個で
フラッシュメモリ 73 ⇒ 81 ⇒ 88%
グローバル変数 69 ⇒ 71 ⇒ 74%
この調子だと、5個でも96%と77%辺りと推測され、
NANOの端子もD6、D13、A0、A7空いてるので5個までいけるでしょう。
まあ、メモリ的にもI/O的にも、限界は、5個ってことですね。
反応は若干遅れ気味です。0.2~0.3秒辺りのようです。
一応、スケッチはGoogle Driveのここの
「MultiOLED_I2C_SPIx3_Volt_Tacho_Meter_A.ino」です。
えいっ!ここまできたら5個だ!
また電圧計スケッチを追加してコンパイル!
さすがに「メモリが少なく・・・」の警告がでましたが、
2 ⇒ 3 ⇒ 4 ⇒ 5個で
フラッシュメモリ 73 ⇒ 81 ⇒ 88 ⇒ 95%
グローバル変数 69 ⇒ 71 ⇒ 74 ⇒ 80%
6個は無理ですね~^^;
5個並べるのも大変でしたが、圧巻ですね~
「A」「W」「G」はフェイクで、中身は全部電圧計「V」と同じです^^;
さすがに応答速度が0.5secに迫る遅さです(-_-;)
もはやオブジェ化してきましたが、スケッチは同Google Driveの
「MultiOLED_I2C_SPIx4_Volt_Tacho_Meter_A.ino」です。
ちょっと、loop()1周の最後にPIND命令で
オンボードのRXとTX LEDをトグルしたら
5個の全部の更新にほぼ0.43secですね~
配線図は、パスです(-_-;)
最後に、5個での反応速度を動画で!
その後、Multi OLEDを調べていると、GitHubのここに
I2Cの高速Read/Writeライブラリかな?を見つけました。
更にGitHubのこっちには、それを使って
I2Cの同じアドレスでも8台まで同時に接続できるライブラリがありました。
0x3Cと0x3Dのアドレスであれば、夫々8台で全16台のOLEDを制御できるようです。
しかも9wire・・・・8台で9本かな?
ちょっと忘備録、
実は、Exampleのラインアートの「display.width()」の意味がわからず
探してるとこの「SH1106 Class Reference」ってのが見つかりました。
adafruit_sh1106ライブラリにかなり近いようです。
更に同サイトのここに詳細なリファレンスがあります。
2 件のコメント:
OLEDの百花繚乱!これでどうするの!?て感じですね。
早いとこ、CNCのアナログコックピット風回転計に仕上げてください(笑)
そうなんですよね~
「これでどうするの~」本人も重々感じておりま~す(-_-;)
雨が続いて気力が出ないこの頃であります(T_T)
コメントを投稿