ESP32でST7735 TFT LCD液晶ディスプレイを使ってみる

はじめに
この記事では、ST7735チップ搭載のTFT LCD液晶ディスプレイをESP32で使う方法をまとめました。ディスプレイデバイスとはSPI接続します。ライブラリを使えばプログラミングは簡単です。ESP32だけでなく、他のArduinoでも動作します。
ゴール
こちらの動画のように、ESP32とTFT LCD、ローターリーエンコーダーを使って、数字を表示するまでをこの記事のゴールとします。このシステムはPTCヒーターを使った温度制御に組み込む予定です。
TFT LCDとESP32の配線
TFT LCDとESP32は次のとおり配線しました。BLピンは使いません。

TFT LCD | ESP32 | Arduino Uno | 説明 |
---|---|---|---|
BL | 未接続 | 未接続 | バックライト制御 |
CS | 5 | 10 | チップセレクト |
DC | 2 | 8 | データ/コマンド制御 |
RES | 4 | 9 | リセット信号入力 |
SDA | 23 | 11 | シリアルデータ入力 |
SCL | 18 | 13 | シリアルクロック |
VCC | 3.3V | 5V | 電源 |
GND | GND | GND | Ground |
Arduino Unoで使う場合、3.3V端子から電圧を供給すると表示が不安定でした。ですから、5V電源に繋いでいます。TFT LCDにはレギュレーターが設置されているので、5Vの電圧でも大丈夫なようになってます。
ライブラリのインストール
ST7735搭載のTFT LCDを動かすには、最低限
Adafruit_GFX
Adafruit_SPITFT
Adafruit_ST77xx
Adafruit_ST7735
gfxfont
が必要になります。事前に下記GitHubリポジトリからインストールしてください。
- https://github.com/adafruit/Adafruit-GFX-Library
- https://github.com/adafruit/Adafruit-ST7735-Library
私は最近、VS
CodeにPlatformIOを入れてArduino開発してます。そのため下記のような構成でライブラリを配置してます。基本ライブラリマネージャーは使っておらず、ソースコードをそのままダウンロードして配置させてます。ここでは
display_test.ino
にサンプルプログラムを記述しました。
.
├── include
│ └── README
├── lib
│ ├── README
│ └── TFT_ST7735
│ ├── Adafruit_GFX.cpp
│ ├── Adafruit_GFX.h
│ ├── Adafruit_SPITFT.cpp
│ ├── Adafruit_SPITFT.h
│ ├── Adafruit_ST7735.cpp
│ ├── Adafruit_ST7735.h
│ ├── Adafruit_ST77xx.cpp
│ ├── Adafruit_ST77xx.h
│ ├── examples
│ │ └── test_display
│ │ └── test_display.ino
│ ├── gfxfont.h
│ └── glcdfont.c
├── platformio.ini
├── src
│ └── main.cpp
└── test
└── README
platformio.ini
には次のように記述し、test_display.ino
を対象にESP32とArduino
Unoの開発環境でビルドできるようにしてます。
[platformio]
src_dir = lib/TFT_ST7735/examples/test_display
[env:esp32]
platform = https://github.com/platformio/platform-espressif32.git
board = esp32dev
framework = arduino
monitor_speed = 115200
platform_packages = framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32#2.0.2
[env:uno]
platform = atmelavr
board = uno
framework = arduino
monitor_speed = 115200
ST7735に数字を表示してみる
前回の記事 の最後で紹介したプログラムを、ST7735版に書き換えました。詳しい説明は前回の記事をご覧ください。
ソースコード(test_display.ino)
/**
* @date 2022-11-22
* @author Toshihiko Arai
* @copyright https://101010.fun
*/
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#if defined(ESP32)
#define TFT_RST 4 // IO4
#define TFT_DC 2 // IO2
//#define TFT_MOSI 23 // VSPID
//#define TFT_SCLK 18 // VSPICLK
//#define TFT_BACKLIGHT 7 // IO7
#define TFT_CS 5 // VSPICS0
#else
#define TFT_CS 10
#define TFT_RST 9
#define TFT_DC 8
#endif
= Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
Adafruit_ST7735 tft
int number = 0;
void setup(void) {
.begin(115200);
Serial.initR(INITR_GREENTAB);
tft.fillScreen(ST77XX_MAGENTA);
tft.setRotation(1);
tft.setTextWrap(false);
tft
.setTextSize(2);
tft.setCursor(5, 5);
tft.print("Ready...");
tft(3000);
delay}
void loop() {
char buff[4];
(buff, "%2d", number); // 数字を右寄せで表示させるため
sprintf.setTextWrap(false);
tft
.fillScreen(ST77XX_MAGENTA);
tft.setCursor(20, 30);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(10);
tft.println(buff);
tft(500);
delay
++;
number}
こちらの動画ではESP32とArduino Unoを使って、ST7735 LCDに文字表示をしている様子がご覧いただけます。
画面のチラつき問題(フリッカー)
TFTディスプレイで文字表示を更新する際に、以前から気になっていた画面のチラつき(フリッカー)。ST7735だとだいぶ改善されてます。Arduino Unoの内部クロック周波数は16MHzだったのに対し、ESP32では標準クロック周波数が240MHzと10倍以上の性能が1つの要因でしょう。動画をみて貰えば分かりますが、ESP32の方は滑らかに数値が表示されるのに対し、Arduino Unoでは若干フリッカーが気になります。とはいえ、前回のST7789ほどではないです。こちらのLCDは128×160ドットだったのに対し、前回は240x240ドットでしたから処理速度の差も大きいのでしょう。
【発展】ロータリーエンコーダーを追加して数値を自在に操る
最初に紹介しました記事のゴールである「ロータリーエンコーダーで数値を自在に操る」ことをやってみましょう。ロータリーエンコーダーの使い方の詳しくは をご覧ください。
ESP32とTFT LCDとローターリーエンコーダーの配線
ロータリーエンコーダーは秋月電子通商さんのものを使いました。A、Bの2信号の位相差出力です。
https://akizukidenshi.com/catalog/g/gP-06358/
ロータリーエンコーダーを使うにあたって、プルアップ抵抗が必要になります。ここではESP32内蔵のプルアップ機能を使いました。ただし、ESP32のIO34~IO39はプルアップできないのでご注意ください。

ライブラリのインストール
ロータリーエンコーダーのプログラミングはかなり複雑なので、ライブラリを使うと良いです。
▼
下記サイトより、RotaryEncoderのライブラリRotaryEncoder.h
と RotaryEncoder.cpp
拾ってきます。
また、Org_01.h
を追加してTFT
LCDに表示させる文字のフォントを変えてみました。Org_01.h
は Adafruit-GFX-Library
に同包されてます。
▼ .ttf
フォントからC++のヘッダーファイルに変換してくれるツールも配布されてます。
私のPlatform IOのツリー構造は下記の通りです。
with_pot.ino
に新しくプログラミングしていきます。
.
├── include
│ └── README
├── lib
│ ├── README
│ └── TFT_ST7735
│ ├── Adafruit_GFX.cpp
│ ├── Adafruit_GFX.h
│ ├── Adafruit_SPITFT.cpp
│ ├── Adafruit_SPITFT.h
│ ├── Adafruit_ST7735.cpp
│ ├── Adafruit_ST7735.h
│ ├── Adafruit_ST77xx.cpp
│ ├── Adafruit_ST77xx.h
│ ├── Org_01.h
│ ├── RotaryEncoder.cpp
│ ├── RotaryEncoder.h
│ ├── examples
│ │ ├── test_display
│ │ │ └── test_display.ino
│ │ └── with_pot
│ │ └── with_pot.ino
│ ├── gfxfont.h
│ └── glcdfont.c
├── platformio.ini
├── src
│ └── main.cpp
└── test
└── README
ソースコード(with_pot.ino)
下記は、最初に紹介した動画のソースコードです。ロータリーエンコーダーを回すことで、TFTディスプレイに映される数値が変化します。ローターリーエンコーダの上限下限を設けるようにしてあります。詳しくはソースコードないの注釈をご覧ください。
/**
* @date 2022-11-22
* @author Toshihiko Arai
* @copyright https://101010.fun
*/
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <RotaryEncoder.h>
#include <SPI.h>
#include <Org_01.h>
/**
* @brief TFT LCD ST7735
*/
#define TFT_RST 4 // IO4
#define TFT_DC 2 // IO2
//#define TFT_MOSI 23 // VSPID
//#define TFT_SCLK 18 // VSPICLK
//#define TFT_BACKLIGHT 7 // IO7
#define TFT_CS 5 // VSPICS0
/**
* @brief Rotary Encoder用のPIN
* ESP32のIO34~IO39はプルアップしないので注意
*/
#define RE_A 25
#define RE_B 26
/**
* @brief LimitedRotator.inoを参考に、ロタリーエンコーダーの上限、下限を設定
* https://github.com/mathertel/RotaryEncoder/blob/master/examples/LimitedRotator/LimitedRotator.ino
*/
#define ROTARYSTEPS 1
#define ROTARYMIN 10
#define ROTARYMAX 60
/**
* @brief ST77XX_REDなどの色がおかしいので自分で定義している
* https://forum.arduino.cc/t/st7735-0-96-160x80-shows-wrong-colors/894996
*/
const uint16_t RED = 0x001f;
const uint16_t BLUE = 0xf800;
const uint16_t GREEN = 0x07e0;
const uint16_t YELLOW = RED | GREEN;
const uint16_t ORANGE = 0x02df;
= Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
Adafruit_ST7735 tft
(RE_A, RE_B, RotaryEncoder::LatchMode::TWO03);
RotaryEncoder encoder
int lastPos = -1;
void clearDisplay() {
.fillScreen(RED);
tft}
void setup(void) {
.begin(115200);
Serial.initR(INITR_GREENTAB);
tft
();
clearDisplay.setRotation(1);
tft.setTextWrap(false);
tft
.setFont(&Org_01);
tft.setTextSize(2);
tft.setCursor(20, 20);
tft.print("Ready...");
tft
// pinMode(RE_A, INPUT_PULLUP); RotaryEncoderのコンストラクタでプルアップされているので必要ない
// pinMode(RE_B, INPUT_PULLUP);
.setPosition(25 / ROTARYSTEPS);
encoder
(2000);
delay}
void loop() {
.tick(); // just call tick() to check the state.
encoder
int newPos = encoder.getPosition() * ROTARYSTEPS;
if (newPos < ROTARYMIN) {
.setPosition(ROTARYMIN / ROTARYSTEPS);
encoder= ROTARYMIN;
newPos
} else if (newPos > ROTARYMAX) {
.setPosition(ROTARYMAX / ROTARYSTEPS);
encoder= ROTARYMAX;
newPos } // if
if (lastPos != newPos) {
= newPos;
lastPos
char buff[5];
(buff, "%2d", newPos); // 数字を右寄せで表示させるため
sprintf.setTextWrap(false);
tft
();
clearDisplay
.setCursor(20, 15);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(1);
tft.println("Target temperature:");
tft
.setCursor(20, 80);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(10);
tft.println(buff);
tft
(50);
delay}
}
TFT LCDの色がおかしい
ソースコードのコメントにも書きましたが、ST77XX_RED
などの一部の色が青色になってしまい、TFT
LCDの色がおかしいバグがあります。そのため、独自で定義して色を反映させてます。
const uint16_t RED = 0x001f;
const uint16_t BLUE = 0xf800;
const uint16_t GREEN = 0x07e0;
const uint16_t YELLOW = RED | GREEN;
const uint16_t ORANGE = 0x02df;
関連記事
- ArduinoでTFT LCDディスプレイ(ST7789)を使ってみる
- ESP32でAdafruit STEMMA Soil Sensorを使って土壌水分量と温度の測定
- ESP32で照度センサTSL25721を使ってみた
- Raspberry PiでOLEDに文字表示
- 【Arduino】非接触温度センサ(GY-906)をつかってみた