8pinoでI2C液晶パネルを使ってみる
一年位前に
自分の中でIoTブームが来た事があって、社内のRaspberryPi講座を受けさせてもらいました。
そのときに、教材として、色々と電子工作部品を戴いたなと、ハタと思い出したので、埃を被っていた袋をこじ開けて、これを見つけました。 初心者には、大変嬉しい完成版。
今回のゴール
液晶パネルが2行×8文字なので、
1行目 : 起動時間表示
2行目 : お店の看板みたいな文字列スクロール
をやってみようかと思います。
動かないんです
結線については、I2Cなので、V、GND、SDA、SCLを8pinoのそれらの専用端子に繋ぐだけです。何て、簡単。
iの24~28に差し込みます
差し込んだ後の図
で、格闘する事、小一時間。 うんともすんとも言ってくれません。 おんなじ部品で、Arduinoで実現している人沢山いるのに。
あまりに放置したから、壊れた?
原因を探る
原因1 : pull-up抵抗足りなかった
こちらのサイト曰く、
The pull-up resistors are necessary when using the ATtiny85. They are not necessary on the arduino because the arduino has internal pull-ups enabled when using the I2C interface.
SDA, SCLの共に、10kΩの抵抗を結線する必要がありました。
嬉しいことに、こちらの基板、その抵抗が実装済みで、ちょっとハンダ盛るだけで、実現可能です。
対応前
対応後
原因2 : スレーブアドレス間違い
だって、説明書に0x7Cって。
なんか世の中のサンプルコード見てたら、みんな0x3Eで実装している人が沢山いて、薄々おかしいなとは思っていました。
0x7C(0111 1100)を右に1ビットずらしたら、0x3E(0011 1110)となることに気が付いて、試してみたら動作しました!
調べてみたら、I2Cのアドレスは7bitだそうで。うーん、果たして誰が悪いのか。俺か。
ソフトウェアの準備
TinyWireM
ArduinoでI2Cを使うには、通常、Wire Libraryを使う様ですが、ATTiny85 では非対応な様で、 8pino公式サイトにもあるように
[I2C通信について]
下記のTinyWireMライブラリをご利用ください。
TinyWireM
https://github.com/adafruit/TinyWireM
TinyWireMライブラリを使います。 インストール方法等は、下記を参考にさせていただきました。
LCD表示のためのライブラリ
上で紹介したblogのコードを見てみたのですが、割りとマジックナンバー系の調整?が沢山必要そうでした。
それもそのはず、表示のための仕様書がこうですもの
とても、気軽に実装できる内容ではありません。
Arduinoには、LiquidCrystalというライブラリがありますが、私の環境では、何かが不満らしく、動作しません。
探してみると、神様が現れました。 こちらのblogで、本LCDパネルをサポートした、Arduino向けのライブラリ(しかも、LiquidCrystal api コンパチ!)が公開されていました!
ただ、これは、Arduino向けのライブラリですので、TinyWireM向けに、修正します。
→ どこかで見つけた、修正方法
LCD Test
Test 1
とにかく表示させてみる。
カーソルの点滅がそれらしさを醸し出します。
Test 2
Test 1に加えて、scrollDisplayLeft()を確認。
そういう事ね。
Test 3
目的の1つだった、autoscroll()を試します。
スクロールはしてくれるのですが、インターフェースがわかりにくいのと、行毎のスクロール非対応っぽいので、使わないと、判断。
スクロールはAPI使わず実現すれば良いです。
本対応
出来ました。
起動開始からの時刻の表示は、millis() を利用しています。
LCD使えると、とたんに表現力が上がるなと感じます。デバッグにも良いでしょうし。
コードはこちら
#include <TinyWireM.h> #include <ST7032.h> // ST7032 lcd( int i2c_addr ); // i2c_addr: slave address // omit i2c_addr -> 0x3E will be set. // AE-AQM0802 works well with the default setting above. ST7032 lcd; #define _8PINO_LCD_NUM_OF_COLUMNS ( 8 ) #define _8PINO_LCD_NUM_OF_ROWS ( 2 ) #define _8PINO_LCD_CONTRAST ( 30 ) #define _8PINO_LCD_TEXT_SCROLL_DELAY ( 200 ) void setup(){ // For LCD Panel. lcd.begin( _8PINO_LCD_NUM_OF_COLUMNS, _8PINO_LCD_NUM_OF_ROWS ); lcd.setContrast( _8PINO_LCD_CONTRAST ); /* // TEST 1 lcd.print("8pino:"); lcd.setCursor(0, 1); lcd.print("Awesome"); lcd.cursor(); lcd.blink(); */ /* // TEST 2 lcd.print("8pino:"); lcd.setCursor(0, 1); lcd.print("Awesome"); lcd.cursor(); lcd.blink(); lcd.scrollDisplayLeft(); */ /* // TEST 3 lcd.setCursor(0, 0); for (int thisChar = 0; thisChar < 8; thisChar++) { lcd.print(thisChar); delay( _8PINO_LCD_TEXT_SCROLL_DELAY ); } lcd.setCursor(8, 1); // set the display to automatically scroll: lcd.autoscroll(); for (int thisChar = 9; thisChar < 8; thisChar++) { lcd.print(thisChar); delay( _8PINO_LCD_TEXT_SCROLL_DELAY ); } // turn off automatic scrolling lcd.noAutoscroll(); lcd.clear(); */ } void loop(){ int i = 0; int str_head_pos = 0; char teststr[] = " 8pino -> The minimalist's arduino/trinket compatible! "; while( 1 ){ // Text Scroll lcd.setCursor( 0, 1 ); for ( i = str_head_pos; i < str_head_pos + _8PINO_LCD_NUM_OF_COLUMNS; i++ ){ lcd.print( teststr[i] ); } str_head_pos++; if( str_head_pos > sizeof( teststr ) - _8PINO_LCD_NUM_OF_COLUMNS ){ str_head_pos = 0; } // Time unsigned long time; time = millis(); lcd.setCursor( 0, 0 ); lcd.print( "Sec:" ); lcd.print( ( time / 10000 ) % 10 ); lcd.print( ( time / 1000 ) % 10 ); lcd.print( "." ); lcd.print( ( time / 100 ) % 10 ); delay( _8PINO_LCD_TEXT_SCROLL_DELAY ); } }
まだ
他にも、RaspberryPi研修でもらった部品があるので、次回はそちらを深堀してみます。