ArduinoでAQM1602Yを触ってみる
TOP > てきとうにこらむ > ゲーム作りとプログラミング日記 > ArduinoでAQM1602Yを触ってみる
AQM1602Y
I2Cで扱えるI2CのLCDである。今回はAQM1602Y-NLW-BBWを使った。黒く、白い文字で表示され、LEDが付いている。
使い方を調べる
データシートを見て結構難儀した。最初バックライトのピンはどこー?と探したが、なかなか見つからない。実はピンではなく両端の金属片がそうだったらしく穴が空いていた。
また、2.54mmピッチではあるものの、上記の金属片(LEDのアノードとカソード)によってピンがブレッドボードに刺さらないという問題も発見。この問題はピンソケットを間にかませることで回避。
データシートの6.0 PIN ASSIGNMENTによると、3にCAP1N、4にCAP1Pとある。これはキャパシタを積むらしいが、最初必要ないだろwと思って刺さなかったら表示されなかった。データシートどおりに1uFのキャパシタを刺したら動いた。
I2CアドレスがわからなかったのでI2C Scannerでアドレスを調べた。0x3eだった。
文字を表示できないとデータシートを目を皿のように見たらST7032iというICを使ってディスプレイを表示させているようなので、そちらのデータシートも読む必要があった。すると、最初の8ビットでどのような命令を送り、次の8ビットでデータを送ることが判明。マジか
使用方法
そして最終的に判明したソースコードはこちら。
初期化
データシートの13.0 RECOMMENDED INITIAL CODEのままを入力したい。このディスプレイでは、最初の8ビットでどういうモードを選択して、次の8ビットで具体的な命令になる。
初期化などのコマンドを設定するのは0x0を送信した後にコマンドを送出する。0x38(Function Set)を設定したいなら、実際にI2Cで送るのは0x0と0x38である。
Wire.write(0x0);
Wire.write(0x38);
文字を送信する
文字を送信する場合。最初にI2Cで送信するのは0x40を送信する。つぎの1バイトで12.0 STANDARD CHARACTER PATTERNSはを元に送信する。0x20(スペース)から0x7f(←)までの範囲はASCIIコードでもある。
Wire.write(0x40);
Wire.write('b');
これをまとめてwriteData関数にまとめた。
半角カナも存在するけれども、機種依存文字で実際にArduino IDEで半角カナを指定しても文字化けする。なので、実際にはコードを決め打ちしたほうが良い。
// コレハテスト
writeData(0xba);
writeData(0xda);
writeData(0xca);
writeData(0xc3);
writeData(0xbd);
writeData(0xc4);
表示されている文字を更新したい
例えば数字をカウントするなどして書いてある内容を更新したい場合には、表示するアドレスを変更するコマンドが必要。ST7032のDisplay Data RAMの2-line displayには以下のように記述されている。
00 01 02 ..
40 41 42 ..
なので、2行目以降は0x40をかけてあげる。ということをsetLcdCursorメソッドでやらせている
ソースコード
ちなみにではあるが、恐らくライブラリはあると思う。これらはエラー処理を施していないので注意。
#include <Wire.h> | |
#define AQM1602Y_ADDR 0x3e | |
int writeCommand(byte command) { | |
Wire.beginTransmission(AQM1602Y_ADDR); | |
Wire.write(0x0); | |
Wire.write(command); | |
return Wire.endTransmission(); | |
} | |
int writeData(byte data) { | |
Wire.beginTransmission(AQM1602Y_ADDR); | |
Wire.write(0b01000000); | |
Wire.write(data); | |
return Wire.endTransmission(); | |
} | |
void initLcd() { | |
delay(100); | |
writeCommand(0x38); // Function Set | |
delay(1); | |
writeCommand(0x39); // Unction Set | |
delay(1); | |
writeCommand(0x14); // BS=0:1/5 BIAS; F2 F1 F0: 100 | |
delay(1); | |
writeCommand(0x73); // Contrast set | |
delay(1); | |
writeCommand(0x5e); // Icon on, booster circuit on | |
delay(1); | |
writeCommand(0x6c); // Follower circuit on | |
delay(1); | |
writeCommand(0x0c); // Entire display on | |
delay(1); | |
writeCommand(0x01); // Clear display | |
delay(1); | |
writeCommand(0x06); // Entry Mode Set, increment | |
delay(1); | |
} | |
void setLcdCursor(int x, int y) { | |
y *= 0x40; | |
y += x; | |
y |= 0b10000000; | |
writeCommand(y); | |
} | |
int writeChar(byte c) { | |
if (c < 0x20) { | |
return -1; // error | |
} | |
if (0x7f < c) { | |
return -1; // error | |
} | |
return writeData((byte)c); | |
} | |
void writeLine(char *s) { | |
int len = strlen(s); | |
int ret = 0; | |
for (int i = 0;i < len; i++) { | |
writeChar(s[i]); | |
} | |
} | |
void setup() { | |
Serial.begin(9600); | |
Wire.begin(); | |
initLcd(); | |
// コレハテスト | |
writeData(0xba); | |
writeData(0xda); | |
writeData(0xca); | |
writeData(0xc3); | |
writeData(0xbd); | |
writeData(0xc4); | |
writeCommand(0b10001111); | |
writeChar('b'); | |
//writeCommand(0b11000000); | |
setLcdCursor(1, 1); | |
writeLine("Hello World"); | |
delay(5000); | |
} | |
void loop() { | |
static int counter = 0; | |
setLcdCursor(0, 1); | |
char countLine[17] = {0}; | |
snprintf(countLine, 16, "%03d", counter); | |
writeLine(countLine); | |
counter++; | |
delay(100); | |
} |
回路
LEDの抵抗に330Ωを使った。別にまあいいかという感じで。ただ、これは結局はユニバーサル基板でまとめたほうがよかったので結局まとめた。
- 3と4番にコンデンサ入れる
- 5番に3.3V
- 6番にGND
- 7番にSDA
- 8番にSCL
- 9番は3.3V