チラシのうら

レゴとか、工作とか。

8pinoでI2C液晶パネルを使ってみる

一年位前に

自分の中でIoTブームが来た事があって、社内のRaspberryPi講座を受けさせてもらいました。

そのときに、教材として、色々と電子工作部品を戴いたなと、ハタと思い出したので、埃を被っていた袋をこじ開けて、これを見つけました。 初心者には、大変嬉しい完成版。

今回のゴール

液晶パネルが2行×8文字なので、
1行目 : 起動時間表示
2行目 : お店の看板みたいな文字列スクロール
をやってみようかと思います。

動かないんです

結線については、I2Cなので、V、GND、SDA、SCLを8pinoのそれらの専用端子に繋ぐだけです。何て、簡単。 f:id:tetunori_lego:20150603220553j:plain
iの24~28に差し込みます

f:id:tetunori_lego:20150603220608j:plain 差し込んだ後の図

で、格闘する事、小一時間。 うんともすんとも言ってくれません。 おんなじ部品で、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Ωの抵抗を結線する必要がありました。
嬉しいことに、こちらの基板、その抵抗が実装済みで、ちょっとハンダ盛るだけで、実現可能です。

f:id:tetunori_lego:20150603222222j:plain 対応前

f:id:tetunori_lego:20150603222250j:plain 対応後

原因2 : スレーブアドレス間違い

だって、説明書に0x7Cって。 f:id:tetunori_lego:20150604072903j:plain
なんか世の中のサンプルコード見てたら、みんな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のコードを見てみたのですが、割りとマジックナンバー系の調整?が沢山必要そうでした。
それもそのはず、表示のための仕様書がこうですもの f:id:tetunori_lego:20150604072740j:plain
とても、気軽に実装できる内容ではありません。
Arduinoには、LiquidCrystalというライブラリがありますが、私の環境では、何かが不満らしく、動作しません。

探してみると、神様が現れました。 こちらのblogで、本LCDパネルをサポートした、Arduino向けのライブラリ(しかも、LiquidCrystal api コンパチ!)が公開されていました!

ただ、これは、Arduino向けのライブラリですので、TinyWireM向けに、修正します。

Wire.を、TinyWireM.に  Wire.write()を、TinyWireM.send()に書き換えれば動く。

→ どこかで見つけた、修正方法

LCD Test

Test 1

とにかく表示させてみる。
8pino LCD Test 1
カーソルの点滅がそれらしさを醸し出します。

Test 2

Test 1に加えて、scrollDisplayLeft()を確認。 f:id:tetunori_lego:20150604075307j:plain
そういう事ね。

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研修でもらった部品があるので、次回はそちらを深堀してみます。