I2C の使用例として、これまで二つ紹介しました。
- キャラクターディスプレイ・・・出力
- 三軸加速度センサー・・・入出力(コマンド送信、センサー値受信)
今回は I2C モジュールを二つ接続してみます。
I2C のメリットは、複数のモジュールがあっても信号線 2本+電源の接続で済むこと。
I2C の概要は こちら のエントリーを参照していただければ。
■ I2CDevice の継承クラス / ADXL345 固有のクラス
.NET Micro Framework の I2CDevice クラスを使いやすくする拡張、および ADXL345 (三軸加速度センサー)は、こちらのコード がそのまま使えます。
特に変更する必要はありません。名前空間が気に入らなければ適当に変更してください。
■ キャラクターディスプレイのクラス
キャラクターディスプレイクラスは こちらのコード が使える・・・のですが、今回は 8×2行の別のモジュール、AQM0802A-RN-GBW を使ってみました。
理由は、実験用シールドに加速度センサーとキャラクターディスプレイの両方を載せるため。
キャラクターディスプレイは多くがHD44780 互換なのですが、AQM0802A は拡張機能セットを使います。
標準的な機能セットと共通の部分が多いのですが、モジュールの初期化コマンドおよびキャラクター出力コマンドが標準とは異なります。
ということで、以下のコードにします。
public class Aqm0802A : I2CDeviceEx { private bool _displayOn = true; // ディスプレイをオンにするか private bool _cursorOn = false; // カーソルを表示するかどうか private bool _blinkOn = false; // カーソル位置でブリンクするか private readonly int _commandWait = 1; // コマンド実行後のウェイト public Aqm0802A(ushort aqm0802A, int defaultClockRateKhz, int timeout) : base(aqm0802A, defaultClockRateKhz, timeout) { Thread.Sleep(1000); // AQM0802A は HD44780 の拡張機能セットを使用する // 以下は拡張機能セットでの初期化コマンド // 標準機能セットを使用するモジュールについては以下を参照 // yseosoft.wordpress.com/2015/12/31/i2c_clcd_demo/ の記事 // GrFamilyLibrary のソースコード (github.com/netmf-lib-grfamily/GrFamilyLibrary) WriteCommand(0x38); // 標準機能セットを指定 WriteCommand(0x39); // 拡張機能セットを指定 WriteCommand(0x14); // 内部オシレーター周波数を指定 WriteCommand(0x70); // コントラストを指定(下位4ビット) WriteCommand(0x56); // コントラストを指定 (上位4ビット) WriteCommand(0x6c); // フォロワーコントロール WriteCommand(0x38); // 標準機能セットに戻す WriteCommand(0x0c); // 表示オン WriteCommand(0x01); // 表示クリア WriteCommand(0x06); // カーソルと表示のシフト設定 WriteCommand(0x0c); // カーソルとブリンクの表示をオフ Thread.Sleep(100); } public void Print(string msg) { for (var i = 0; i < msg.Length; i++) { WriteCharactor((byte)msg[i]); } } // 表示クリア public void Clear() { WriteCommand(0x01, 5); // Clear Displayはウェイトが必要 } // カーソルを初期位置に戻す public void Home() { WriteCommand(0x02, 5); // Return Homeはウェイトが必要 } public void DisplayOn(bool displayOn) { ControlDisplay(displayOn, _cursorOn, _blinkOn); _displayOn = displayOn; } // カーソル表示オン・オフを切り替える public void CursorOn(bool cursorOn) { ControlDisplay(_displayOn, cursorOn, _blinkOn); _cursorOn = cursorOn; } // カーソル位置のブリンクのオン・オフを切り替える public void BlinkOn(bool blinkOn) { ControlDisplay(_displayOn, _cursorOn, blinkOn); _blinkOn = blinkOn; } public void SetCursor(int row, int col) { var addr = (byte)(((byte)row) << 6) + (byte)col; WriteCommand((byte)(0x80 | addr)); } private void ControlDisplay(bool displayOn, bool cursorOn, bool blinkOn) { var cmd = (byte)0x08; if (displayOn) cmd |= 0x04; if (cursorOn) cmd |= 0x02; if (blinkOn) cmd |= 0x01; WriteCommand(cmd, _commandWait); } public void WriteCharactor(byte data) { // AQM0802A は拡張機能セットを使うので 0x40 // 標準機能セットの場合は 0x80 RegWrite((byte)0x40, data); } public void WriteCommand(byte cmd, int wait = 1) { var reg = (byte)0x00; RegWrite(reg, cmd); Thread.Sleep(wait); } }
■ アプリケーションのコード例
アプリケーションのコード例は以下の通り。
public class Program { private const ushort Adxl345Address = 0x1d; // ADXL345のアドレス private const ushort Aqm0802AAddress = 0x3e; // AQM0802A-RN-GBWのアドレス private const int DefaultClockRateKhz = 100; // 転送速度 (KHz) private const int Timeout = 1000; // 送受信ごとのタイムアウト public static void Main() { var prog = new Program(); prog.Run(); } private void Run() { var accel = new Adxl345(Adxl345Address, DefaultClockRateKhz, Timeout); var lcd = new Aqm0802A(Aqm0802AAddress, DefaultClockRateKhz, Timeout); while (true) { Int16 x; Int16 y; Int16 z; accel.Measure(); accel.GetXYZ(out x, out y, out z); lcd.Clear(); lcd.Print(x.ToString() + "," + y.ToString()); lcd.SetCursor(1, 0); lcd.Print(z.ToString()); Thread.Sleep(1000); } } }
加速度センサーの使い方、キャラクターディスプレイの使い方が分かれば、(当然ですが)特に不思議なところも難しいところもないですね。
■ 結線
結線は以下の通り。
I2C モジュールは信号線をパーティーライン状に接続するだけです。通信時にモジュールのアドレスが含まれているので(.NET Micro Framework では隠蔽されていますが)、どちらに対しても正しくデータを送受信できます。