既に基板化しているのですが、ここでは、まず最初にブレッドボードでCQカチャ(WSN282)を使ったI2C化キットをつくり作動させます。
●回路構成
I2C化コントローラの回路は、ArduinoでLCDに文字を出すだけのなんの変哲もない回路です。ArduinoにはI2CのI/Fがあるので、ArduinoをI2Cのスレーブにして、コマンドを受け取れるようにし、そのコマンドでLCDを制御するようなプログラム(ファームウェア)を作成します。
このコントローラはArduinoでなくても良いのですが、開発が簡単なので、Arduinoを利用します。ファームウェアの書き換えも簡単です。
次の図はI2C化回路の基本的なものです。代表的な14ピンタイプのLCDの結線例で、図左下は制御端子が1列に並んだタイプ、右下は2列×7のもっとも一般的なタイプのLCDの配線です。
配線量を減らすため、LCDは4ビットモードで使用します。
次の写真は制御端子2列タイプで16文字×2行のLCDで製作したコントローラです。コンパクトにするために、WSN234 LCD BB直結アダプタを使用してLCDをブレッドボードに直結していますが、回路的には上図右下の回路と等価です。
●制御コマンド
LCDを制御するコマンド(I2Cで受信する2バイトのデータ)は、1バイト目がレジスタセレクトの0×00(LCDコマンド)か0×01(LCDデータ)、2バイト目がコマンドコードか文字コードとなっています。
●プログラム/ファームウェア(I2CLcdCtrl.ino)
動作の概要は、まず、LCDを初期化して、I2Cスレーブに設定し、I2Cの受信を待ちます。I2Cでスレーブ受信したら、内容に応じてLCDへデータを送ります。
次にコードを示します。典型的なI2Cのスレーブ受信処理です。
// // I2C制御 LCDコントローラ // copyright (c) 2013 http://www.wsnak.com // // 汎用LCDモジュールのI2C化キット // // 12/11/15 // /* 汎用のLCDへ接続して、I2Cデバイス化する、Arduino使用のコントローラ */ #include <Wire.h> /* LCD data PORTD D4~D7 LCD E D8 LCD RS D9 */ #define E_ON digitalWrite(8, HIGH) #define E_OFF digitalWrite(8, LOW) #define RS_CMD digitalWrite(9, LOW) // RS=0 #define RS_DATA digitalWrite(9, HIGH) // RS=1 #define LCD_DAT PORTD // LCD DB0~DB7 #define TST_SW !(PINC&(1<<3)) // PC3 (A3) ジャンパショート時テスト byte CmdCnt; byte Cmd, Data; // プロトタイプ void writeCmd(void); void WriteData(byte dat); void WriteCmd(byte dat); void Write4bitCmd(byte data); void Write4bitData(byte data); void LcdInit(void); void E_Pulse(void); void setup(void) { // 入力ポートのデジタルバッファをイネーブルにする DIDR0 &= ~(1<<ADC3D); // ADC3 // A3(PC3) ディジタル入力に再設定 DDRC &= ~(1<<3); // input PORTC |= (1<<3); // pullup enable // Wire.begin(0x50); Wire.begin(0x20); Wire.onReceive(hSlvRcv); CmdCnt = 0; pinMode(4, OUTPUT); // LCD DB4 pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); // LCD DB7 pinMode(8, OUTPUT); // LCD E pinMode(9, OUTPUT); // LCD RS E_OFF; RS_CMD; LcdInit(); // テスト表示(A3ポートのジャンパ設定による) if(TST_SW) { delay(100); WriteData('T'); WriteData('E'); WriteData('S'); WriteData('T'); } } // ----------------------- // メインループ // ----------------------- void loop(void) { } // スレーブ受信ハンドラ void hSlvRcv(int cnt) { int i; for(i = 0; i < cnt; i+=2) { Cmd = Wire.read(); Data = Wire.read(); writeCmd(); } } // ----------------------- // コマンド書き込み // ----------------------- void writeCmd(void) { if(Cmd == 0x00) { // LCDコマンド WriteCmd(Data); } else { // LCDデータ WriteData(Data); } } // ********************************* // LCD初期化 (4ビットモード) // ********************************* void LcdInit(void) { delay(15); Write4bitCmd(0x3); // delay(5); Write4bitCmd(0x3); // delay(5); Write4bitCmd(0x3); // delay(5); Write4bitCmd(0x2); // delay(5); WriteCmd(0x01); // clear delay(5); WriteCmd(0x06); // entry mode set delay(5); WriteCmd(0x0C); // display on/off control delay(5); WriteCmd(0x1C); // cursor/display shift delay(5); WriteCmd(0x28); // function set delay(5); WriteCmd(0x02); // home delay(5); } // LCDデータ書き込み void WriteData(byte dat) { Write4bitData(dat >> 4); // 上位4bit Write4bitData(dat); // 下位4bit } // LCDコマンド書き込み void WriteCmd(byte dat) { Write4bitCmd(dat >> 4); // 上位4bit Write4bitCmd(dat); // 下位4bit } // 4ビットLCDコマンド書き込み void Write4bitCmd(byte data) { RS_CMD; LCD_DAT = data << 4; E_Pulse(); } // 4ビットLCDデータ書き込み void Write4bitData(byte data) { RS_DATA; LCD_DAT = data << 4; E_Pulse(); } // eパルス出力 void E_Pulse(void) { E_OFF; delayMicroseconds(1); E_ON; delayMicroseconds(1); E_OFF; delayMicroseconds(100); }
22~25行目は各制御信号を切り替えるマクロです。
45~49行目はA3(アナログ)をディジタル入力ポートに再設定して、プルアップも有効化しています。ここにジャンパを付けて、起動時のテスト表示の有無を切り替えます。
52行目でI2Cスレーブに設定しています。ここではスレーブアドレスは0×20にしています。
53行目はI2Cでスレーブ受信した時に呼び出されるハンドラ(処理関数)を登録しています。受信があると、”hSlvRcv()”という関数が呼び出されるた、そこで受信データを取り出して処理します。
57~63行目は使用するディジタルポートを出力に設定しています。
68行目の”LcdInit()”関数でLCDを4ビットモードに初期化して画面をクリアさせています。
71行目でA3(ディジタル入力に再設定済)の状態を読み出し、ジャンパショート時はテスト文字を表示させます。
88行目の”hSlvRcv()”はI2Cスレーブ受信時に呼び出されるハンドラです。2バイト読み出して、”Cmd”と”Data”というグローバル変数にデータを保存し、”writeCmd()”という関数へ渡します。
101行目の”writeCmd()”で”Cmd”の内容に応じて、LCDコマンド設定関数”WriteCmd()”またはLCDデータ設定関数”WriteData()”をよびだします。
114行目は起動直後にLCDを初期化する関数です。4ビットモード、画面クリア、カーソル位置クリアなど、LCDを初期化します。
●I2C化コントロール・プログラム ダウンロード
I2C化ファームウェア(40文字×4行専用) ZIPファイルI2CLcdCtrl
●WSN318(14ピンLCD)用プログラム
基板化した回路では、40文字×4行のC-51849NFJと回路を兼用にするため、ディジタルポートのアサインが上記プログラムと一部異なります。
LEDの”E”がD10が、”RS”がD12にアサインされています。前項のプログラム で一部を修正すれば使用できます。
22~25行目を次のように修正します。
#define E_ON digitalWrite(10, HIGH) #define E_OFF digitalWrite(10, LOW) #define RS_CMD digitalWrite(12, LOW) // RS=0 #define RS_DATA digitalWrite(12, HIGH) // RS=1
62、63行目を次のように修正します。
pinMode(10, OUTPUT); // LCD E pinMode(12, OUTPUT); // LCD RS
上記の修正をしたWSN318用のコントロールプログラムを掲載しておきます。
WSN318用I2C化ファームウェア(14ピン専用) ZIPファイル I2CLcdCtrl318
適当なフォルダに解凍して使ってください。他のファイルと同様、親フォルダも含めて日本語文字は使えないので注意してください。なお、このプログラムは40文字×4行のLCDには使えません。専用のプログラムは後述します。
次の写真は、プログラム書き込みの際にWSN283(P2:USB/電源部)をアダプタWSN319を通して接続したところです。この状態でWSN318はArduino Duemilanove互換となります。
注意:WSN318にはあらかじめArduinoファームウェアを書き込んでおく必要があります。
Arduinoを使ったLCDや7セグメントLEDのI2C化の記事は書籍「Arduino実験キットで楽ちんマイコン開発」でも取り扱っています。なお、同書籍では上記写真のように試作機をブレッドボードで製作しましたが、現在は次のような専用の小型基板を用意しています。それぞれ、Arduinoを専用コントローラとして使っていますが、プログラムは通常のArduinoとして作成し、そのまま作動します。
参考文献