秋月電子で販売している液晶ディスプレイAQM0802とAQM1602は、I2C接続でArduinoやESP32、RaspberryPiPicoなどに接続できます。動作電流が1mAなので、電池駆動したい場合などに重宝します。
ただ、文字が小さいため、温度や時刻などを表示すると空白が余ります。そこで大きな数字を表示できるようにしてみました。
(ちなみに、ここに書いた方法以外にも、FunctionSetコマンド(0x38)を送信してDHを1にすることで、縦が2倍のdoubleHeightFontを使うことができます)
RaspberryPiPicoとAQM0802の接続
- Pico -> AQM0802またはAQM1602
- GP20(I2C0SDA)-> SDA
- GP21(I2C0SCL) -> SCL
- 3V3 -> VDD
- GND->GND
RESETは変換基板上でVDDにプルアップされているためオープンでOK
ArduinoUNOなどの5Vデバイスで使用する場合の注意
SDA、SCLにレベル変換を入れるほうが良いと思います。
(入れなくても3.3Vにプルアップすれば動きますが、壊れても文句言わない)
Picoのボードファイルについて
mbedにする場合、SDA、SCLはGP6、GP7に固定されていますので注意が必要です。
特別こだわりがなければ、'Earle F. Philhower, III'バージョンを使ったほうがI2Cのピンを変更できたり、いろいろ便利です。
他の液晶
似たような液晶パネルに、ACM1602NIなどがありますが、キャラクタパターンが違うので使えません。
#include "AQM0802BigDigit.h" | |
//----- I2C interface ----- | |
void AQM0802BigDigit::WriteCommand(uint8_t data) | |
{ | |
Wire.beginTransmission(0x3E); | |
Wire.write(0x00); | |
Wire.write(data); | |
Wire.endTransmission(true); | |
} | |
void AQM0802BigDigit::WriteData(uint8_t data) | |
{ | |
Wire.beginTransmission(0x3E); | |
Wire.write(0x40); | |
Wire.write(data); | |
Wire.endTransmission(true); | |
} | |
void AQM0802BigDigit::createCustomChar(int index , const uint8_t* pattern) | |
{ | |
WriteCommand(0x40 + index * 8); | |
for (int i=0; i<8; i++) WriteData(pattern[i]); | |
} | |
void AQM0802BigDigit::setCursorAtRowAndColumn(int row, int col) | |
{ | |
WriteCommand(0x80 + col * 0x40 + row); | |
} | |
void AQM0802BigDigit::init() | |
{ | |
WriteCommand(0x38); // Function set | |
WriteCommand(0x39); // Function set | |
WriteCommand(0x14); // Internal OSC frequency | |
WriteCommand(0x73); // Contrast set | |
WriteCommand(0x56); // Power/ICON/Contrast set | |
WriteCommand(0x6c); // Follower control | |
delay(200); | |
WriteCommand(0x38); // Function set | |
WriteCommand(0x0c); // Display ON/OFF control | |
WriteCommand(0x01); // Clear Display | |
delay(1); | |
WriteCommand(0x0C); // Display ON/OFF control | |
createCustomChar(0,image0); | |
createCustomChar(1,image1); | |
createCustomChar(2,image2); | |
createCustomChar(3,image3); | |
createCustomChar(4,image4); | |
createCustomChar(5,image5); | |
} | |
void AQM0802BigDigit::displayBigDigitAtColumn(uint8_t digit, uint8_t pos_x) | |
{ | |
setCursorAtRowAndColumn(pos_x,0); | |
WriteData(bigDigitFull[digit][0]); | |
WriteData(bigDigitFull[digit][1]); | |
setCursorAtRowAndColumn(pos_x,1); | |
WriteData(bigDigitFull[digit][2]); | |
WriteData(bigDigitFull[digit][3]); | |
} | |
void AQM0802BigDigit::displayBigDigitHalfAtColumn(uint8_t digit, uint8_t pos_x) | |
{ | |
setCursorAtRowAndColumn(pos_x,0); | |
WriteData(bigDigitHalf[digit][0]); | |
setCursorAtRowAndColumn(pos_x,1); | |
WriteData(bigDigitHalf[digit][1]); | |
} |
#include <Arduino.h> | |
#include <Wire.h> | |
class AQM0802BigDigit | |
{ | |
private: | |
void WriteCommand(uint8_t data); | |
void WriteData(uint8_t data); | |
void createCustomChar(int index , const uint8_t* pattern); | |
void setCursorAtRowAndColumn(int row, int col); | |
public: | |
void init(); | |
void displayBigDigitAtColumn(uint8_t digit, uint8_t pos_x); | |
void displayBigDigitHalfAtColumn(uint8_t digit, uint8_t pos_x); | |
private: | |
//CGRAM character | |
const uint8_t image0[8] = { 0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111 }; | |
const uint8_t image1[8] = { 0b11111, 0b00001, 0b00001, 0b00001, 0b00001, 0b00001, 0b00001, 0b11111 }; | |
const uint8_t image2[8] = { 0b11111, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b11111 }; | |
const uint8_t image3[8] = { 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b11111 }; | |
const uint8_t image4[8] = { 0b00001, 0b00001, 0b00001, 0b00001, 0b00001, 0b00001, 0b00001, 0b11111 }; | |
const uint8_t image5[8] = { 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b11111 }; | |
//lookup table | |
const uint8_t bigDigitFull[10][4] = { | |
{0x09,0x0A,0x0B,0x0C}, //0 | |
{0x20,0x7C,0x20,0x7C}, | |
{0x00,0x01,0x0B,0x5F}, | |
{0xFF,0x01,0x5F,0x0C}, | |
{0x03,0x05,0x20,0x7C}, | |
{0x02,0x00,0x5F,0x0C}, | |
{0x02,0x00,0x0B,0x0C}, | |
{0x09,0x0A,0x20,0x7C}, | |
{0x02,0x01,0x0B,0x0C}, | |
{0x02,0x01,0x5F,0x0C} // 9 | |
}; | |
const uint8_t bigDigitHalf[13][2] = { | |
{0x20,0x20}, // ' ' | |
{0x7C,0x7C}, | |
{0x01,0x0B}, | |
{0x01,0x0C}, | |
{0x66,0x7C}, //4 | |
{0x02,0x0C}, | |
{0x02,0x66}, //6 | |
{0x0A,0x7C}, | |
{0x4F,0x4F}, //8 | |
{0x4F,0x0C}, //9 | |
{0x20,0x2E}, //. | |
{0xA5,0xA5}, //: | |
{0xFF,0x20} //- | |
}; | |
}; |
#include <Wire.h> | |
#include "AQM0802BigDigit.h" | |
// ------------------------------------------------------------------------------------------------------ | |
// AQM1602, AQM0802 | |
// This source code is written for Raspberry Pi pico, but it can also be used with ArduinoUNO by modifying the Wire settings. | |
// ## Raspberry Pi pico | |
// Please use 'Earle F. Philhower, III' version. | |
// When using the 'mbed' version, some changes are required in the wire definition, and the SDA and SCL port are fixed. | |
const uint8_t PIN_I2CSDA = 20; | |
const uint8_t PIN_I2CSCL = 21; | |
AQM0802BigDigit lcd; | |
void setup() { | |
Wire.setSDA(PIN_I2CSDA); | |
Wire.setSCL(PIN_I2CSCL); | |
Wire.begin(); | |
lcd.init(); | |
} | |
void loop() { | |
//Sample1 FM frequency | |
uint16_t freq = 740; | |
while (freq != 1080) { | |
lcd.displayBigDigitHalfAtColumn((freq / 1000 == 1),0); | |
lcd.displayBigDigitAtColumn((freq / 100) % 10, 1); | |
lcd.displayBigDigitAtColumn((freq / 10) % 10, 3); | |
lcd.displayBigDigitHalfAtColumn(10,5); // . | |
lcd.displayBigDigitAtColumn((freq) % 10, 6); | |
freq++; | |
delay(10); | |
} | |
//Sample2 clock | |
uint8_t time_hour = 0; | |
uint8_t time_min = 0; | |
while (time_hour < 13) { | |
time_min = 0; | |
while (time_min < 60) { | |
lcd.displayBigDigitHalfAtColumn((time_hour / 10), 0); | |
lcd.displayBigDigitAtColumn((time_hour % 10),1); | |
lcd.displayBigDigitHalfAtColumn(11,3); // : | |
lcd.displayBigDigitAtColumn((time_min / 10),4); | |
lcd.displayBigDigitAtColumn((time_min % 10),6); | |
time_min++; | |
delay(10); | |
} | |
time_hour++; | |
} | |
} |