LCD1602(キャラクタータイプ液晶ディスプレイ) with Arduino IDE
はじめに
LCD1602(キャラクタータイプ液晶ディスプレイ)とは、I2Cプロトコルを用いて16×2(16列と2行)の液晶ディスプレイ(LCD)にテキストやキャラクターを表示するデバイスです。
比較的安価に、センサーの読み取り値やメッセージなどを表示するために使用できます。PCF8574 I2Cチップが内蔵されているため、ESP32との通信はI2Cにて実装します。

開発環境
OS : Windows 11 Pro
ESP32:ESP-WROOM-32
統合開発環境 : Arduino IDE 2.1.0
Arduino core for the ESP32:1.0.6
使用ライブラリ:LiquidCrystal_I2C(1.1.2)
使用パーツ
ESP32開発ボード(38Pin)

LCDディスプレイ (LCD1602)

※「I2C アダプター」を使用します。既にはんだ付けされているもの推奨。
ジャンパーワイヤー(メスーメス)

作業内容
配線図
LCD1602 とは I2C通信するため、GPIO 21(SDA) と GPIO 22(SCL) を使用して接続します。

LCD1602 | ESP32開発ボード(38Pin) |
GND | GND |
VCC | 5V |
SDA | GPIO 21(SDA) |
SCL | GPIO 22(SCL) |
ライブラリインストール
LiquidCrystal_I2C
LCD1602 と I2C通信するためのライブラリである LiquidCrystal_I2C をインストールします。

検索結果の1番上には表示されない可能性があるため、注意してください。
私の場合は、5番目に表示されていました。
スケッチ作成
「LCD1602」というフォルダを作り、「LCD1602.ino」というファイルを作成します。
以降、このファイルにスケッチを記載しています。
「スケッチブックの場所\LCD1602\LCD1602.ino」
通常(アルファベット/数字)表示
1行目に「HELLO WORLD!」2行目に「farmsoft」と表示するスケッチを描いてみます。
//LEDディスプレイ
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup()
{
Serial.begin(115200);
// ディスプレイ
lcd.init();
lcd.backlight();
lcd.setCursor(2, 0);
lcd.print("HELLO WORLD!");
lcd.setCursor(4, 1);
lcd.print("farmsoft");
}
void loop()
{
}
コード説明
先ほどインストールした、「LiquidCrystal_I2C」をインクルードします。
#include <LiquidCrystal_I2C.h>
LCD の I2Cアドレス、列数、行数を指定しています。
デフォルトでは[0x27]になっていると思いますが、別の場合は変更してください。
LiquidCrystal_I2C lcd(0x27, 16, 2);
まず、初期化します。
lcd.init();
バックライトをONにします。
※初期化完了時点ではバックライトはOFFになっています。
lcd.backlight();
バックライトをOFFにする場合は、lcd.noBacklight() で指定できます。
表示開始(カーソル)位置を指定します。
lcd.setCursor(2, 0);
<<引数>>
・uint8_t col:列数(0オリ)
・uint8_t row:行数(0オリ)
文字を表示させます。
lcd.print("HELLO WORLD!");

👈動作イメージ
1行目に「HELLO WORLD!」2行目に「farmsoft」と表示されます。
半角カタカナ表示
1行目に「HELLO WORLD!」2行目に「コンニチワ」と表示するスケッチを描いてみます。
先ほどのアルファベットのような表記では、カタカナは表示できません。
//LEDディスプレイ
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup()
{
Serial.begin(115200);
// ディスプレイ
lcd.init();
lcd.backlight();
lcd.setCursor(2, 0);
lcd.print("HELLO WORLD!");
lcd.setCursor(5, 1);
lcd.print("\xba\xdd\xc6\xc1\xdc"); // コンニチワ
}
void loop()
{
}
コード説明
カタカナは、このような表記をすることで表示させることができます。
lcd.print("\xba\xdd\xc6\xc1\xdc"); // コンニチワ

👈動作イメージ
2行目に「コンニチワ」と表示されます。
これは、キャラクタコード表のアドレスに従って指定しています。
【コ(0xba)ン(0xdd)ニ(0xc6)チ(0xc1)ワ(0xdc)】
キャラクタコード表

LCD1602 は、すでに登録されているキャラクタのアドレスを指定することで表示しています。大半のキャラクタがASCIIコードと一致するように配置されています。
Arduino スケッチはユニコードで文字を扱います。そのため、アルファベットは、ユニコードと登録されているキャラクタのアドレス(ASCIIコード)が一致しているため、意識せずに表示することができました。しかし、カタカナの場合は、ユニコードとASCIIコードが一致しないため、直接アドレスを指定して表示させています。
カスタム文字(外字フォント)表示
あらかじめ、キャラクタコード表に文字を登録しておくことで、カスタム文字を表示させることができます。
キャラクタコード表の赤枠箇所(8個)に登録できます。
//LEDディスプレイ
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
byte heart[8] = { // ♡
B00000,
B01010,
B11111,
B11111,
B11111,
B01110,
B00100,
B00000
};
byte celsius[8] = { // ℃
B11000,
B11000,
B00111,
B01000,
B01000,
B01000,
B00111,
};
byte fahrenheit[8] = { // ℉
B11000,
B11000,
B00111,
B00100,
B00111,
B00100,
B00100,
};
byte postcode[8] = { // 〒
B00000,
B11111,
B00000,
B11111,
B00100,
B00100,
B00100,
};
void setup()
{
Serial.begin(115200);
// ディスプレイ
lcd.init();
lcd.createChar(0, heart);
lcd.createChar(1, celsius);
lcd.createChar(2, fahrenheit);
lcd.createChar(3, postcode);
lcd.backlight();
lcd.setCursor(2, 0);
lcd.print("HELLO WORLD!");
lcd.setCursor(0, 1);
lcd.write(0);
lcd.write(1);
lcd.write(2);
lcd.write(3);
delay(5000);
}
void loop()
{
for(int h = 0; h < 16; h++)
{
lcd.setCursor(0, 1);
for(int l = 0; l < 16; l++)
{
lcd.write((16 * h) + l);
}
delay(2000);
}
}
コード説明
ここで登録する外字フォントを作成しています。
byte heart[8] = { // ♡
B00000,
B01010,
B11111,
B11111,
B11111,
B01110,
B00100,
B00000
};
横5ドット縦8ドットで形成され、1ドットずつビットで指定します。
1つ目はハートを作成しています。
16行目以降も同じように、℃/℉/〒を登録しています。
次に作成した外字フォントを登録します。
lcd.createChar(0, heart);
lcd.createChar(1, celsius);
lcd.createChar(2, fahrenheit);
lcd.createChar(3, postcode);
<<引数>>
・uint8_t location:登録番号(0オリ)
・uint8_t charmap[]:外字フォント配列
8つまで登録できるので、0~7まで使用できます。
登録した外字フォントを表示します。
lcd.write(0);
lcd.write(1);
lcd.write(2);
lcd.write(3);
<<引数>>
・uint8_t value:表示アドレス
valueに表示する文字をキャラクタコード表のアドレスで指定します。
アドレスと登録番号が同じため、登録番号と同じ値となります。

👈動作時、2行目に4つの外字フォントが表示されます。
loop()では、キャラクタコード表の内容を順次表示させてみています。
void loop()
{
for(int h = 0; h < 16; h++)
{
lcd.setCursor(0, 1);
for(int l = 0; l < 16; l++)
{
lcd.write((16 * h) + l);
}
delay(2000);
}
}

👈2秒毎にキャラクタコード表の内容が表示されます。
☝️登録されていない外字フォントは(Ξ)三本線表記。
☝️なぜか「0x00~0x07」の内容で「0x08~0x0F」が表示されます。
ライブラリコード一覧
関数 | 説明 |
---|---|
init() | 初期化。最初に1度のみ呼び出す。 |
clear() | 画面クリア。 |
home() | 画面位置、カーソル位置を初期値に移動。 |
setCursor(uint8_t col, uint8_t row) | 任意の場所にカーソルを移動。 ・uint8_t col:列数(0オリ) ・uint8_t row:行数(0オリ) |
print(const char c[]) printstr(const char c[]) | 文字表示 |
noDisplay() | 画面の文字列を非表示。 ※バックライト操作はなし。 |
display() | 画面の文字列を表示。 ※バックライト操作はなし。 |
noCursor() cursor_off() | カーソル(_)非表示。 |
cursor() cursor_on() | カーソル(_)表示。 |
noBlink() blink_off() | カーソル点滅(■)非表示。 |
blink() blink_on() | カーソル点滅(■)表示。 |
scrollDisplayLeft() | 画面全体を1つ左へ移動。 |
scrollDisplayRight() | 画面全体を1つ右へ移動。 |
leftToRight() | カーソル移動時、左から右へ移動指定。 |
rightToLeft() | カーソル移動時、右から左へ移動指定。 |
autoscroll() | 自動スクロール設定。 文字入力時、自動で画面全体を入力文字数分左へ移動。 |
noAutoscroll() | 自動スクロール設定解除。 |
createChar (uint8_t location, uint8_t charmap[]) createChar (uint8_t location, const char *charmap) load_custom_character (uint8_t char_num, uint8_t *rows) | |
noBacklight() setBacklight(uint8_t new_val) | バックライトなし。 ・uint8_t new_val:0x00 |
backlight() setBacklight(uint8_t new_val) | バックライトあり。 ・uint8_t new_val:0x00 以外 |
おわりに
うまく表示されることができましたか?
LCD1602は、安価かつ簡単に文字を表示することができるため、使用頻度がかなり高めです。ぜひ活用してみてください。
スクロールについて
スクロール系の操作をするには、LCDのコントローラ仕様(DDRAM容量など)を把握する必要があります。また、自動で指定間隔毎にスクロールしてくれるわけではなく、文字入力をしてトリガをあたえる必要もあることや、スクロールの対象は画面全体となり、1行ごとに指定したりもできません。
そのため、アプリ側でLCD表示タスクを生成して、スクロールするコードを自作する方が現実的なのかなと思いました。私の場合は、スクロールする必要性もないため、また必要になった時にでもチャレンジしてみようと思います。
コメント