ArduinoでAQM1602液晶を使う場合、通常はWireライブラリを使用しますが、ATtinyなどの小メモリ環境では容量や速度の面で不利になることがあります。そこで本記事では、Wireを使わずにSoftI2Cで動作する軽量なAQM1602ライブラリを自作し、その使い方を分かりやすく解説します。低メモリ環境でも安定して動作し、コントラスト設定や位置指定表示にも対応しています。サンプルコード付きで、すぐに動かせる内容になっています。
完成ライブラリ
ライブラリーはgithubに載せておきましたので下記のURLからダウンロードしてお使いください。
リポジトリはこちら:
AQM1602_SoftI2C.h 今回作成したのはこちらのlibraryです。
https://github.com/asa-lab-bit/AQM1602_SoftI2C.h
SoftI2C_VPORT.h こちらと組み合わせて使います。
https://github.com/asa-lab-bit/SoftI2C_VPORT_tinyAVR
AQM1602_SoftI2C.h
#ifndef AQM1602_H
#define AQM1602_H
#ifndef AQM1602_SOFTI2C_H
#define AQM1602_SOFTI2C_H
#include <Arduino.h>
#include <SoftI2C_VPORT.h>
class AQM1602 {
public:
AQM1602(SoftI2C_VPORT& i2c);
void begin(uint8_t contrast = 0x72, uint8_t power = 0x52);
void clear();
void setCursor(uint8_t col, uint8_t row);
void print(const char* text);
void print(int value);
void printAt(uint8_t col, uint8_t row, const char* text);
void printAt(uint8_t col, uint8_t row, int value);
private:
SoftI2C_VPORT& _i2c;
void sendCommand(uint8_t cmd);
void sendData(uint8_t data);
};
#endifAQM1602_SoftI2C.cpp
#include "AQM1602_SoftI2C.h"
#define AQM1602_ADDR 0x3E
AQM1602::AQM1602(SoftI2C_VPORT& i2c) : _i2c(i2c) {}
void AQM1602::begin(uint8_t contrast, uint8_t power) {
_i2c.begin();
delay(50);
sendCommand(0x38);
delay(20);
sendCommand(0x39);
delay(20);
sendCommand(0x14);
delay(20);
sendCommand(contrast);
delay(20);
sendCommand(power);
delay(20);
sendCommand(0x6C);
delay(20);
sendCommand(0x38);
delay(20);
sendCommand(0x0C);
delay(20);
sendCommand(0x01);
delay(4);
}
void AQM1602::clear() {
sendCommand(0x01);
delay(2);
}
void AQM1602::setCursor(uint8_t col, uint8_t row) {
if (row == 0) {
sendCommand(0x80 + col);
} else {
sendCommand(0xC0 + col);
}
}
void AQM1602::print(const char* text) {
_i2c.start();
_i2c.write(AQM1602_ADDR << 1);
_i2c.write(0x40);
while (*text) {
_i2c.write(*text++);
}
_i2c.stop();
}
void AQM1602::print(int value) {
if (value == 0) {
sendData('0');
return;
}
if (value < 0) {
sendData('-');
value = -value;
}
char buf[6];
uint8_t i = 0;
while (value > 0) {
buf[i++] = (value % 10) + '0';
value /= 10;
}
while (i--) {
sendData(buf[i]);
}
}
void AQM1602::printAt(uint8_t col, uint8_t row, const char* text) {
setCursor(col, row);
print(text);
}
void AQM1602::printAt(uint8_t col, uint8_t row, int value) {
setCursor(col, row);
print(value);
}
void AQM1602::sendCommand(uint8_t cmd) {
_i2c.start();
_i2c.write(AQM1602_ADDR << 1);
_i2c.write(0x00);
_i2c.write(cmd);
_i2c.stop();
}
void AQM1602::sendData(uint8_t data) {
_i2c.start();
_i2c.write(AQM1602_ADDR << 1);
_i2c.write(0x40);
_i2c.write(data);
_i2c.stop();
}ライブラリの設計ポイント
- SoftI2Cを外から渡す設計
- クラス設計の意図
- メモリ削減の工夫
基本的な使い方(サンプルコード)
sample.ino
#include <SoftI2C_VPORT.h>
#include <AQM1602_SoftI2C.h>
// ★ I2Cをここで作る
SoftI2C_VPORT i2c(1, 2); //使用するPinを設定する SDA=PA1, SCL=PA2
// ★ 渡す
AQM1602 lcd(i2c);
void setup() {
lcd.begin(0x73, 0x56); //コントラスト設定 電圧設定3.3V向け5Vでは0X52です
int aa= -23;
lcd.printAt(2, 0, "Hello");
lcd.printAt(8, 0, "Hello");
lcd.setCursor(0,1);
lcd.print(aa);
lcd.print(" abcdef");
}
void loop() {
}今回の接続方法です(すいませんでした、最初接続図を間違えていました。
こちらが正しい接続図です26年5月14日)。
AQM1602側で内部プルアップしています。

関数一覧と使い方
■ begin()
void begin(uint8_t contrast = 0x72, uint8_t power = 0x52);LCDの初期化を行います。
電源投入後、必ず最初に呼び出します。
- contrast:コントラスト調整
- power:内部電源設定
👉 初心者はデフォルトのままでOK
コントラスト内部電源の設定の仕方
lcd.begin(0x72, 0x52);引数の意味:
| 引数 | 内容 |
|---|---|
| contrast | コントラスト値 |
| power | 内部電源設定 |
■ clear()
void setCursor(uint8_t col, uint8_t row);表示位置を指定します。
- col:列(0〜15)
- row:行(0 or 1)
例:
lcd.setCursor(5, 1);👉 2行目の6文字目に移動
■ print(文字列)
void print(const char* text);文字列をそのまま表示します。
例:
lcd.print("Hello");■ print(整数)
void print(int value);整数を表示します。
特徴:
- itoa不使用(軽量)
- メモリ節約
■ printAt(おすすめ)
lcd.printAt();位置指定+表示を1発で行う便利関数です。
例:
lcd.printAt(0, 0, "Temp"); // 文字列
lcd.printAt(6, 0, 2345); // 数値👉 一番よく使う関数
軽量化の工夫
- Wire未使用
- sprintf / itoa未使用
- 最小限の関数構成
- 参照渡しでコピー削減
👉 ATtinyでも余裕で動作
まとめ
今回は、AQM1602液晶をSoftI2Cで動かす軽量ライブラリを紹介しました。Wireを使わないことで、ATtinyのような小さなマイコンでも無理なく扱えるのがポイントです。シンプルな構成ながら、位置指定やコントラスト設定にも対応しているので、ちょっとした表示用途には十分使えます。ぜひサンプルコードを動かしながら、自分の環境でも試してみてください。
Attiny202でも問題なく動きます。


