前回の続きで、もう少しまじめに照度測定するために使えそうな部品を集めていたところ、I2C LCDモジュール(秋月通販コードK-08896)という文字表示用の液晶ディスプレイを発掘しました。
Sitronix ST7032 LCD Controller を搭載しており、データシートに can display alphanumeric, Japanese kana characters, and
symbols と記載されているように『かな文字(ってなんだろう)』と『記号』も表記できるという優れものです。
表示できる文字のそれぞれに 8bits のコードに割り当てられているので、要するに表示したい文字のコードを表示したい場所に割り当ててやれば良いわけです。
データシートも複雑でいかにも難しそうなので、キーボードの CTRL + Shift + i を同時に押して Library Manager を起動させたくなります。実際に製品型番で少し調べてみると、苦労しただの、ST7032 ライブラリが動かないだのという経験談がいくつも見つかります。
でも、これ特別なライブラリを入れなくても動くし、そんなに難しくもないよというのが今回の趣旨です。
というか、このモジュールで一番難しいところはおそらくソルダリングです。ブリッジングしてるんじゃないかと何度もルーペで確認することになりました。私は細かい作業ができないんですよ。
無事に接合ができましたら、付属の印刷物または公式ページが公開しているデータシートに目を通します。
そうすると Arduino との接続という項目がきちんと設けられていて、以下のようなスケッチが記載されていることが分かります。
引用開始
#include <Wire.h>
#define LCD_ADRS 0x3E
char moji[] = "AQM1602XA-RN-GBW";
//SCL=A5=LCDNo2 SDA=A4=LCDNo3
void setup()
{
Wire.begin();
init_LCD();
}
void loop() {
for (int i = 0; i < 16; i++) {
writeData(moji[i]);
}
writeCommand(0x40 + 0x80); // 2LINE TOP
for (int i = 0; i < 16; i++) {
writeData(i + 0xb1);
}
while (1) {} //stop
}
//-- main process ends here --
void writeData(byte t_data)
{
Wire.beginTransmission(LCD_ADRS);
Wire.write(0x40);
Wire.write(t_data);
Wire.endTransmission();
delay(1);
}
void writeCommand(byte t_command)
{
Wire.beginTransmission(LCD_ADRS);
Wire.write(0x00);
Wire.write(t_command);
Wire.endTransmission();
delay(10);
}
void init_LCD()
{
delay(100);
writeCommand(0x38);
delay(20);
writeCommand(0x39);
delay(20);
writeCommand(0x14);
delay(20);
writeCommand(0x73);
delay(20);
writeCommand(0x56);
delay(20);
writeCommand(0x6C);
delay(20);
writeCommand(0x38);
delay(20);
writeCommand(0x01);
delay(20);
writeCommand(0x0C);
delay(20);
}
引用終わり
データシートが示すように基本的な Wire コマンドで制御できるわけです。
これをマイコンに書き込み、モジュールのSDAとSCLとマイコンの該当ピンとを接続すると普通に動きますので、少なくともこのモジュールに関してはライブラリを使用しなくても良いんじゃないかなと個人的には思います。
自作の関数 init_LCD(), writeCommand(), writeData() はそれぞれディスプレイに文字を表示するために必要な機能なので置いておくとして、スケッチの中で注目すべきは loop() の中身です。
void loop() {
for (int i = 0; i < 16; i++) {
writeData(moji[i]);
}
writeCommand(0x40 + 0x80); // 2LINE TOP
for (int i = 0; i < 16; i++) {
writeData(i + 0xb1);
}
while (1) {} //stop
}
ディスプレイ上に文字を表示させているのは writeData() です。
このスケッチでは writeData() 関数がchar配列を引数にとってディスプレイ上に表示するので、この引数を好きなように書き換えれば良いわけです。
つまり
#include <Wire.h> #define LCD_ADRS 0x3E char moji[] = "Griaß eich, i bi kabra, kumm urspüngli aus Nidaöstareich :)";
と適当な文字列に書き換えれば、こうなるわけです。
この例から16文字以上の入力は無視されるっぽいこと、定義されていない表示文字は文字化けすること(※)が推定できます。
同様に2行目の文字列を表示させているのは writeData(i + 0xb1); なので
void loop() {
for (int i = 0; i < 16; i++) {
writeData(moji[i]);
}
writeCommand(0x40 + 0x80); // 2LINE TOP
for (int i = 0; i < 16; i++) {
writeData(i + 0xb1);
}
while (1) {} //stop
}
この元のコードを表示したい文字列に書き換えると2行目の表示も変わります。
もう全部書き換えちゃいましょう。
char firstRow[] = "Griass eich";
char secondRow[] = "i bi kabra";
void loop() {
for (int i = 0; i < 16; i++) { // The first row head
if (sizeof(firstRow) / sizeof(firstRow[0]) < i+1) {
writeData(' ');
} else {
writeData(firstRow[i]);
}
}
writeCommand(0x40 + 0x80); // The second row head
for (int i = 0; i < 16; i++) {
if (sizeof(secondRow) / sizeof(secondRow[0]) < i+1) {
writeData(' ');
} else {
writeData(secondRow[i]);
}
}
while (1) {} //stops
}
こうすると結果は以下のようになります。
書き換えたコードの中の if (sizeof(firstRow) / sizeof(firstRow[0]) < i+1) は何をやっているかと言うと、入力文字数が 16 に満たないときに空白を出力しています。
気をつけないといけないのは Arduino の sizeof 関数はバイト数を返してくる仕様なので、気づかずに使っていると意図せぬ動作を引き起こすことがあります。
あとはセンサの出力値のような目的の出力をその都度、char 配列に入れていけばいいのではないかと。
おそらく、こうすることが最も簡単ですが、他に良い方法があるかもしれません。
もちろん、制御用バイトつまり Wire.write(0x40); の 0x40 = 0100 0000 に文字コードを組み合わせて出力しても良いです。
Character Patterns は文字コードを2進数で表現しているので、それを16進数に変換してから 0x40 と結合させて Wire.write() の引数に与えます。つまり表示する文字がアなら 0xB1, 同様に ö なら 0x94 と言った具合に機械的に16進数に置き換えていけばいいです。
2進数の 1111 = 0x0F なので4桁ごとに切って見ていくと便利です。慣れてくると秒速で暗算できるようになります。
どうして 0x40 = 0100 0000 が文字出力になるのかの詳細は ST7032 のデータシート (ver 1.3) pp.20-27 を参照してください。
ドキュメントに必要なことは書いてあるので、まずは全部読みましょうということですね。
※ ST7032 のデータシート (ver 1.3) pp.16-17 を見ると 5x8 ドットで8種類の文字を独自に追加できそうな感じはあります




