初めに
Arduinoに複数のデバイスやセンサーを繋いで使用したい際に、ピン数が足りない、またはバッティングする、といったことはないでしょうか?
また、使用中のI2Cセンサーを、プログラムを書き換えることなく別のセンサーに置き換えたい、といったことはないでしょうか?
今回は、
・複数のI2Cデバイス
・ソフトウェアシリアル
・電磁リレー
等で複数ピンが使用されているArduinoに対して、さらに液晶モジュールを取り付けたいという要望のために液晶モジュールをI2C化しました。
経緯
はじめはI2C 16x2文字モノクロ液晶を使っていたのですが、
・もう少し大きく表示したい
・プログラムを変えずに液晶だけ置き換えたい
という要望があり、SPI接続の1.8インチTFT液晶モジュールをI2C 16x2文字モノクロ液晶とコマンド互換でArduinoとI2Cで接続できるようにすることにしました。
しくみ
SPI接続の1.8インチTFT液晶モジュールをI2Cモジュール化するために、
・TFT液晶を別のArduinoで制御
・メインのArduinoとI2Cで接続(TFT液晶側をスレーブにする)
・メインのArduinoからI2Cでコマンドを送り、スレーブ側のArduinoで表示
としました。
こうすることでArduinoのピンを新たに消費することなく液晶を追加することができます。
Arduino同士のI2C
Arduino同士をI2Cで接続する方法は
Arduino同士でI2C通信する方法
で詳しく解説されていますが非常に簡単です。
今回は、それまで使っていたI2C 16x2文字モノクロ液晶とアドレス互換、コマンド互換となるようにしました。
モノクロ液晶ではコマンド(文字出力、カーソル位置変更等)とデータ(位置、文字等)を0x40の符号で判断していたので、
Wire.beginTransmission(m_addr);
Wire.write(_isData ? 0x40 : 0x00);
Wire.write(_command[i]);
Wire.endTransmission();
スレーブ側のArduinoでもそれに合わせた仕様で受け取るようにしました。
if(isData==0){ // !0x40
if((v_data&0x80)==0x80){ // 0x80はカーソルセットコマンド
int x = (v_data&0x3f);
int y = ((v_data>>6)&0x1);
emu->SetCursor(x,y); // 16x2行を8x4行に
}
}else if(isData==0x40){ // 0x40は文字表示コマンド
emu->WriteCharReq(v_data);
}
else if(isData==0x10){ // 0x10は色変えコマンド(拡張)
emu->SetPalette(v_data); // 0xfront|back
}
まとめ
既存のデバイスをI2C化して動作させることができました。
グラフィック液晶を高速表示するような用途には向いていませんが、
・I2C接続されていたセンサー/デバイスを、仕様を変えることなく別のものに置き換えたい
・デバイスをなるべくモジュール化したい
といった用途には向いているのではないかと思います。