I2C接続AQMシリーズのキャラクタ表示LCDをMicro:bitで使う (1) AQM0802

Micro:bitの開発をArduino IDEで行う

 Arduino IDEではC/C++ライクな言語でプログラムの開発を行います。たくさんの参考資料があるので、事例の多くはインターネットで検索すると解決できます。Micro:bitには専用の開発環境がありますが、ここではArduino IDEを使います。

 搭載されているマイコンnRF51822(Cortex-M0)、Cortex-M0+(USBインターフェース用)は3.3Vで動作します。SPIやI2C、I/O関連はnRF51822の端子が外部に出ています。

 電子工作では表示部分にキャラクタ表示のLCDが使われてきました。この十年、パラレル接続の製品が多かったのですが、ArduinoのI/Oポートがそれほど多くないので、2本で接続できるI2C接続のキャラクタ表示LCDが望まれていました。キャラクタ表示のLCDの内部は、HD44780という相当古いコントローラ・コンパチブルのICで制御されているので、カーソルを移動することや文字を表示するコマンドは、どの製品もほぼ同じです。

 ただし、日本国内で流通しているデバイスと海外で一般に入手できるデバイスは異なるようです。I2Cのインターフェースは独自の製品が多く、特に、スレーブ・アドレスは様々です。

 Arduinoには、I2C通信ができるWireライブラリがあります。

安価な秋月電子通商扱いのAQM0802の仕様

 AQM0802は、1行に8文字、2行表示のコンパクトなキャラクタ表示LCDです。

 スレーブ・アドレスは0x3eです。

 2017年10月現在、販売価格は320円ですが、接続ピンの間隔が狭いので、ブレッドボードで利用できるようにした変換基板付きの製品は600円です。変換基板の販売は当初なかったので、スイッチサイエンスで購入したものを使いました。こちらは885円です。ここでは3.3V用を使っています。リセット端子(XRST)は接続しません。

Arduino IDEの準備

 2017年10月現在最新のArduino IDE 1.8.5を利用します。Windows10ユーザならば、通常Windows Installerを選びます。クリックしてダウンロードのページが出ます。ここで、JUST DOWNLOADをクリックすると、インストーラがダウンロードされます。古いバージョンがインストールされていたら、uninstallが走り、最新版がインストールされます。

 Micro:bitが利用できる準備をします。

 メニューから、

ファイル > 環境設定 > 設定 

 追加のボードマネージャのURLに、

https://sandeepmistry.github.io/arduino-nRF5/package_nRF5_boards_index.json

を入れ、OKを押します。

 メニューから、ボードマネージャを起動します。

ツール> ボード > ボードマネージャ 

 検索欄にnRF5 を入れます。見つけてきた「Nordic Semiconductor nRF5 Boards by Sandeep Mistry」をインストールします。画面はすでにインストールが終わった状態です。

ツール> ボード > ボードマネージャ 

 利用するボードとしてBBC micro:bitを選択します。

 ツールからSoftDevice (Nordic Semiconductorのプロトコル・スタック)をクリックし、 S110を選びます。

 ツールからシリアルポートをクリックし、Micro:bitの仮想ポートを選びます。

 サンプル・スケッチを入れます。

 書き込みます。

 LEDが点滅します。

 以上で、Arduino IDEを用いて開発する準備ができました。

※参考ページ;https://learn.adafruit.com/use-micro-bit-with-arduino/install-board-and-blink

接続

 Micro:bitのI/Oは独自形式で、22(20)ピンのエッジ・コネクタになっています。ブレッドボードで配線しやすいように変換コネクタをスイッチサイエンスから購入しました。

 ピン番号は順序良く並んでいません。I2Cの2本の信号線は、端に取り出されています。ピンヘッダをはんだ付けしてから使います。回路図を見ると、1kΩでプルアップされています。

 ピンヘッダを2列です。横同志はショートしています。SPIの信号にチップ・セレクトが足りません。ライブラリを使うときは近くにある16(P16)がSSになるようです。

 I2Cは、SCLとSDAの二つの信号線と電源、合計4本だけの配線で通信できます。

Micro:bitの端子 AQM0802の端子
3V VDD
0V GND
SCL SCL
SDA SDA

 I2Cには、二つのデバイスがすでにぶら下がっています。

  • 0x0e 磁気センサMAG3110
  • 0x1d 加速度センサMMA8653

I2C-LCDのスケッチをWireライブラリで記述

#include <Wire.h>
unsigned char lcd_address = 0x3e; // スレーブ・アドレス

int i2cwritecmd(byte cmd) { // LCDへコマンドを送る
Wire.beginTransmission(lcd_address);
Wire.write((byte)0x00);
Wire.write(cmd);
return Wire.endTransmission();
}

int i2cwritedata(byte data) { // LCDへデータを送る
Wire.beginTransmission(lcd_address);
Wire.write(0x40);
Wire.write(data);
return Wire.endTransmission();
}

void init_lcd() { // LCDの初期化。コントラストはデータでセット
delay(145);
i2cwritecmd(0x38);delay(1); //
i2cwritecmd(0x39);delay(1); // 拡張モード・コマンドへ
i2cwritecmd(0x14);delay(1); // 発振周波数
i2cwritecmd(0x73);delay(1); // コントラスト
i2cwritecmd(0x56); // ブースタOFF。電圧3.3V
delay(1);
i2cwritecmd(0x6c);delay(300); // フォロワ・コントロール
i2cwritecmd(0x38);delay(1); // ノーマル・モード・コマンドへ
i2cwritecmd(0x01);delay(2); //  ディスプレイON
i2cwritecmd(0x0C);delay(2); //  画面クリア
}

void setup() {
Wire.begin();
init_lcd();
}
void loop() {
  i2cwritedata(0x41); //A
  i2cwritedata(0x42); //B
  i2cwritedata(0x43); //C
delay(1000);
}

 実行例です。

アナログのサンプル・スケッチを参考に

 動作テスト用に、void loop() 内を、次のスケッチを追加しました。

   sensorValue = analogRead(sensorPin);
lcd.print(sensorValue); lcd.print(" ");
lcd.print(sensorValue/1024.0*3.3); lcd.print("V"); 

 6本のアナログ入力ピンが用意されています。

I/O番号 P2 P10 P1 P4 P0 P3
アナログ A2 A5 A1 A4 A0 A3

 A0端子を3V端子へつなぎます。読み取ったデータと電圧を表示しました。

スケッチ

 制作したスケッチです。

#include <Wire.h>
unsigned char lcd_address = 0x3e; // LCD slave
int n = 0;

int i2cwritecmd(byte cmd) {
Wire.beginTransmission(lcd_address);
Wire.write((byte)0x00);
Wire.write(cmd);
return Wire.endTransmission();
}

int i2cwritedata(byte data) {
Wire.beginTransmission(lcd_address);
Wire.write(0x40);
Wire.write(data);
return Wire.endTransmission();
}

void lcdcu_set(int x, int y) {
byte ca = (x + y * 0x40) | (0x80); i2cwritecmd(ca);
}

void lcdclear() {
i2cwritecmd(0x01);
}

void lcdhome() {
i2cwritecmd(0x02);
}

void dsift_l() {
i2cwritecmd(0x1C);
}

void dsift_r() {
i2cwritecmd(0x18);
}

void i2cprint( String pdata) {
int n = pdata.length();
for (int i = 0; i < n; i = i + 1) {
i2cwritedata(pdata.charAt(i));
delay(1);
}
}

void init_lcd() {
delay(145);
i2cwritecmd(0x38);delay(1);
i2cwritecmd(0x39);delay(1);
i2cwritecmd(0x14);delay(1);
i2cwritecmd(0x73);delay(1);
i2cwritecmd(0x56); //3.3V
delay(1);
i2cwritecmd(0x6c);delay(300);
i2cwritecmd(0x38);delay(1);
i2cwritecmd(0x01);delay(2);
i2cwritecmd(0x0C);delay(2);
}

int sensorPin = A0;
int sensorValue = 0;

void setup() {
Wire.begin();
init_lcd();
Serial.begin(9600);
}

void loop() {
lcdclear();
sensorValue = analogRead(sensorPin);
Serial.println(sensorValue);
i2cprint(String(sensorValue));i2cprint(String(" "));
i2cprint(String(sensorValue/1024.0*3.3));i2cprint(String("V"));
delay(1000);
}

 実行例です。

(2017/11/17)ABC書き込みプログラムのloop内のデータ書き込み関数が間違っていたので修正した。

コラム AQM0802のACK信号


 キャラクタ表示LCDのAQM0802は、消費電流が1mAと少ない省エネ・デバイスです。ラズパイではI2C信号を1.8kΩでプルアップしているため、ACKがLowになるときに電流が足りなく、マスタであるラズパイが通信に失敗します。

 実際に信号を見ました。Micro:bitでは、ACKは約0.8VでLowと認識され、通信が正常に行われています。ただし、0.8VはLowと認識されるぎりぎりの高い電圧なので、デバイスによっては、通信に失敗するかもしれません。