IchigoJam  i2cインタフェースのLCDの接続 | オヤジのブログ

オヤジのブログ

Yahooからの避難組/FC2と2足のわらじ/趣味やら日々の出来事やら

IchigoJamでi2c:16x2 LCDモジュール
イメージ 1
こんなものを買ってきた。
マルツMI2CLCD-01。
Linkman社製の16桁x2行のキャラクタLCD、BO1602DGRNJB$に、プルアップ抵抗なんかを載せたマルツ製のピッチ変換基板を抱き合わせた製品。
3.3V駆動なので、RaspberryPiやIchigoJamなんかでそのまま扱える。
そこで、とりあえず、IchigoJamもファーム1.00あたりから、BASICにi2cコマンドが実装されたので、試してみた。
イメージ 2
接続は、
LCD側        IchigoJam
  SCL  -->      EX1  (プルアップ 基盤のジャンパで設定してもOK)
  SDA  -->     IN2 (          〃         )
  GND  -->     GND
  VDD  -->     VCC
とこんな感じ。
 
あ、ちなみに、このLCDは半完成品ということで、LCDそのものはフラットケーブルを基盤に差し込むだけだけど、基盤の方にはピンヘッダなり配線のハンダ付けが必要。
 
で、プログラム、IchigoJamのi2c送信コマンドを使って、LCDにコマンドとデータを送信して動作させることになるが、i2cに関して書いてあるサイトやブログはたくさんあるので、詳細な説明はそちらを参照していただくとして...
要は、2本の信号線を使って、親機からシリアルでコマンドやデータのビット列を送信することで様々な機器(子機)をコントロールする規格といえばいいか。
そのビット列の中には、先頭に子機(スレーブ)に対するユニークなアドレスを含み、子機は自分のアドレスの付いたコマンドなりデータだけを受け取る方式なので、2本の信号線だけで(実質は電源があるので4本)複数の子機をコントロールすることができるというもの。
 
プログラムとしては、IchigoJamのi2cwという関数を使って、
スレーブアドレス(7ビット)、R/W(マスターからの送信か読み込みかの決定1ビット)、コマンドorデータ、コマンドorデータ・・・・という繰り返しになる。
 
で、いざプログラムを書こうと思ったら、付いてきた説明書をどうひっくり返してみても、スレーブアドレスが見当たらない。
製品によってはスイッチやジャンパでアドレスを変えられるものもあるようだけど、これにはそういったものはなさそうなので、おそらく固定だと思うが・・
で、見つけたのがこれ。
イメージ 3
アドレスは冒頭の7ビットだから、0b0111110=0x3E=62ということか。
ヒントは絵の中にありました・・・・って、判じ物じゃあるまいし、ちゃんと書いといてくれ~。
 
ところで、IchigoJamのi2cwというのも、ちょっと良くわからない関数で、直接、送信したい数値をパラメータで渡すんじゃなくて、メモリ上の値を、アドレスが指す位置から何個分という形で示す形式。
つまり、例えば、poke #700,0,1,3,4,5,6,7,8,9として予め必要なデータをメモリに書き込んでおいて、
a=i2cw(62,#700,1,#701,5)みたいにして送信する。
カッコ内の冒頭の62はスレーブアドレス、続くアドレス#700番のメモリから1個、#701番のメモリから5個送るという書き方をする。
よくわからない?、そうすごくわかりにくいっていうか面倒くさい。
なんで直接数値を指定するようになっていないのかと思うのだが、たとえばこういったLCDのようなキャラクタデバイスであれば、画面に表示した文字列を、VRAMである#900番地からの内容を読み取って転送してやれば、わざわざ文字コードに変換して羅列しなくても、簡単に文字を表示できるという利点はある。
 
取敢えず、プログラム。
 
まずは、説明書にしたがって、初期設定。
 
画面の設定を決めるFunction Set。
命令テーブルが2つあり、最後の1ビットISで切り替えで、0x38と0x39が並んでるんだけど、命令テーブル1の0x39しか使わないので、0x38は書かなくてもいいような気もするんだけど・・?
次に命令テーブル1の方のinternal OSC frequencyの設定。
5ビット目が1の命令で、後のビットはバイアスとフレーム周波数。
適当に10001として、0x11とする。
次はコントラストセット。
5,6,7が1ビットの命令で、0x70としてみる。
下の3ビットがコントラストの下3ビットに相当、だからここではコントラストゼロ。
次のパワー/アイコン/コントラスト設定の設定。
下2ビットと併せて5ビットのコントラスト調整、つまり全32諧調ってこと?。
でコントラストの5ビット目を1(という事は、16でだいたい半分ってとこ)へ設定で0x56
で電源関係のフォロワ回路の設定、0x6C。4ビット目がフォロワ回路のオンオフ。
下3ビットがフォロワ回路の強度で、これもよくわからないので、3ビット目を1で、8諧調のうち4でだいたい半分の設定。
 
ここで電源が安定するのをまって、200ミリ秒待ち、おもむろにDisplayONの為、0xC。
 
というわけで、説明書の通りに設定すると、
スレーブアドレスの0x3E,送信モードの0に引き続き、0x38,0x39,0x11,0x70,0x56,0x6Cを送信、少し待って、0xCをすると初期設定が終了するということだ。
 
実際には
poke #700,#38,#39,#11,#70,#56,#6C,#C,0,#40,1
としておいて、
a=i2cw(#3E,#707,1,#700,6)   ⇒ a=i2cw(#3E,#700,1,701,5)でも動く。
wait 12
a=i2cw(#3E,#707,1,#706,1)   ⇒ a=i2cw(#3E,#706,1,#706,1)同じコマンド重ねても動く。
のようにすると初期化が完了するはず。
 
ちなみに、i2cwは、コマンドじゃなく関数なので、代入式などの形を取る必要があり、こんな書き方になる。
 
ちなみに、2回目の送信のときのR/Wの0送信(#707,1)は、多分必要ないんだけど、i2cw関数の引数が、5個になってるので、数合わせに入れてみた。
 
そして、簡単に文字を表示するプログラムを作ってみた。
イメージ 4
10 poke #700,#38,#39,#11,#70,#56,#6C,#C,0,#40,1
20 a=i2cw(#3E,#707,1,#700,6)
25 wait 12
30 a=i2cw(#3E,#707,1,#706,1) この一個目の#707,1=0は不要
40 poke #730,#54,#45,#53,#54,#B0,#4C,#43,#44
50 a=i2cw(#3E,#707,1,#709,1) これも同じく1個目の0は不要
60 a=i2cw(#3E,#708,1,#730,8)

<2015.11.07 追記>
 
プログラムの具体的な説明追記。
 
10~30行は、前述の通り、LCDの初期設定用パラメータ。
 
40行はユーザーメモリアドレス#730へ、"TEST-LCD"の文字コードのメモリへの書き込み。
50行はR/Wビットの0と、画面クリアコマンドの"1"。
もの凄い勘違いをしていたんだけど、冒頭の0はR/W(リード・ライト)じゃなくて、Co(同種データの連続を示す)やR/S(データ”1”かコマンド”0”か)などのレジスタ選択を示す8ビットデータ(スイッチ?)。
8ビット目がCo、7ビット目がR/Sを示す(残り6ビットは無効?)。
だから、Coなし、データだと、0b01000000=0x40=#40になるし、コマンドだと0b00000000=0となる。
おそらく初期値が0なので、これを書いていたときはたまたまうまくいったけど、実際には省略は不可。
(2016/11/6追記 遅いって!!)

 
60行はLCDの表示用メモリアドレスの設定(これ以降のデータはこのメモリアドレスに書き込まれる)と、ユーザーメモリ#730から、書き込んだ"TEST-LCD"の文字コードを送信。
 
という感じ。
 
<追記終わり>
 
VRAMから直接文字データを渡すなどという事を書いていながら、結局40行に、文字コードを羅列してしまった。
 
実行するとこんな感じ。
イメージ 6
(って、冒頭の方に上げた写真とおんなじだけど)
 
ちなみに、Function SETの#39を、拡大文字設定の3ビット目をオン、つまり#3Dにすると、こうなる。
イメージ 5
正直、説明書だけではわからないことが多く、表示させるだけで2日かかった。
IchigoJamでは、ある程度自在に使えるようになったと思う
 
<2015.11.07 追記>
使えるようになったと思ったけど、改めてichigojamのリファレンス見てみたら、i2cwのあるいはi2crのアドレスビットの後には、自動的にR/Wビットが付加されるような記述があった。
確かに、i2cw,ic2rと送受信でコマンド分けてる訳だから、readかwriteかのビットは自動で付加するよな。
だけど、実際に初期設定を送る前には、0を送信しておかないと、デバイスが次のコマンド認識しないようなんだけど、この0ってなに?
RS&Coビットってこと?
じゃあ、次のパケットでも必ず0付加しなきゃならないんじゃないかと思うけど、付けなくてもコマンド通るよなあ。
確認したら、0はやはり自動で付加されているようで、入れても無意味というか、入れても無視されている?
だから、単純にi2cw(i2cスレーブアドレス,コマンドアドレス,長さ(個数)、コマンドorデータアドレス,長さ(個数))でいいみたい。
 
良くわからないので、もう少し勉強しなきゃだな。
というわけで、勉強のため、
<以下追記終わり>
 
次はこれをラズパイで動かしてみたいと思う。
 
I2Cについては、手前味噌ですが、こちらも・・というかこちらを是非ご覧ください。