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

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

この記事では、ST7735チップ搭載のTFT LCD液晶ディスプレイをESP32で使う方法をまとめました。ディスプレイデバイスとはSPI接続します。ライブラリを使えばプログラミングは簡単です。ESP32だけでなく、他のArduinoでも動作します。

ゴール

こちらの動画のように、ESP32とTFT LCD、ローターリーエンコーダーを使って、数字を表示するまでをこの記事のゴールとします。このシステムはPTCヒーターを使った温度制御に組み込む予定です。

つかうもの

この記事で使うものをご紹介いたします。

TFT LCD(ST7735)

こちらのST7735チップ搭載のTFT LCDを使用しました。Arduino開発では一番よく使っているディスプレイです。ピン端子はあらかじめはんだ付けされてます。

スペックは次のとおりです。

項目
サイズ1.8インチ
表示モードTFT
入力データSPIインタフェース
ドライブICST7735S
解像度128RGB×160ポイント
アクティブエリアLCD28.03(W)×35.04(H)
動作温度-20〜70℃

前回の ArduinoでTFT LCDディスプレイ(ST7789)を使ってみる で使用したST7789と違って、こちらの製品にはCS(チップセレクト)端子があります。ですから複数のSPIデバイスを接続できます。SPI通信の場合は必ずCSがついているものを選ぶようにしましょう。

▼ 解像度が128x128のものもあります。

ESP32

今回はST7735をESP32で動かしました。以下、私がよく使っている技適が通っているESP32を紹介しておきます。

秋月電子通商さんで販売されているESP32と同じで、38ピン備わってます。

WayinTopのESP32
WayinTopのESP32

無線通信の必要ない場合は、普通のArduinoでも構いません。

その他

また、ブレッドボードやジャンプワイヤもあると便利です。

TFT LCDとESP32の配線

TFT LCDとESP32は次のとおり配線しました。BLピンは使いません。

ESP32とTFT LCDの配線
ESP32とTFT LCDの配線

TFT LCDESP32Arduino Uno説明
BL未接続未接続バックライト制御
CS510チップセレクト
DC28データ/コマンド制御
RES49リセット信号入力
SDA2311シリアルデータ入力
SCL1813シリアルクロック
VCC3.3V5V電源
GNDGNDGNDGround

Arduino Unoで使う場合、3.3V端子から電圧を供給すると表示が不安定でした。ですから、5V電源に繋いでいます。TFT LCDにはレギュレーターが設置されているので、5Vの電圧でも大丈夫なようになってます。

ライブラリのインストール

ST7735搭載のTFT LCDを動かすには、最低限 Adafruit_GFX Adafruit_SPITFT Adafruit_ST77xx Adafruit_ST7735 gfxfont が必要になります。事前に下記GitHubリポジトリからインストールしてください。

GitHub - adafruit/Adafruit-GFX-Library: Adafruit GFX graphics core Arduino library, this is the 'core' class that all our other graphics libraries derive from GitHub - adafruit/Adafruit-ST7735-Library: This is a library for the Adafruit 1.8" SPI display http://www.adafruit.com/products/358 and http://www.adafruit.com/products/618

私は最近、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に数字を表示してみる

前回の記事 ArduinoでTFT LCDディスプレイ(ST7789)を使ってみる の最後で紹介したプログラムを、ST7735版に書き換えました。詳しい説明は前回の記事をご覧ください。

ソースコード(test_display.ino)

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 = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

int number = 0;

void setup(void) {
    Serial.begin(115200);
    tft.initR(INITR_GREENTAB);
    tft.fillScreen(ST77XX_MAGENTA);
    tft.setRotation(1);
    tft.setTextWrap(false);

    tft.setTextSize(2);
    tft.setCursor(5, 5);
    tft.print("Ready...");
    delay(3000);
}

void loop() {
    char buff[4];
    sprintf(buff, "%2d", number);  // 数字を右寄せで表示させるため
    tft.setTextWrap(false);

    tft.fillScreen(ST77XX_MAGENTA);
    tft.setCursor(20, 30);
    tft.setTextColor(ST77XX_WHITE);
    tft.setTextSize(10);
    tft.println(buff);
    delay(500);

    number++;
}

こちらの動画ではESP32とArduino Unoを使って、ST7735 LCDに文字表示をしている様子がご覧いただけます。

画面のチラつき問題(フリッカー)

TFTディスプレイで文字表示を更新する際に、以前から気になっていた画面のチラつき(フリッカー)。ST7735だとだいぶ改善されてます。Arduino Unoの内部クロック周波数は16MHzだったのに対し、ESP32では標準クロック周波数が240MHzと10倍以上の性能が1つの要因でしょう。動画をみて貰えば分かりますが、ESP32の方は滑らかに数値が表示されるのに対し、Arduino Unoでは若干フリッカーが気になります。とはいえ、前回のST7789ほどではないです。こちらのLCDは128×160ドットだったのに対し、前回は240x240ドットでしたから処理速度の差も大きいのでしょう。

【発展】ロータリーエンコーダーを追加して数値を自在に操る

最初に紹介しました記事のゴールである「ロータリーエンコーダーで数値を自在に操る」ことをやってみましょう。ロータリーエンコーダーの使い方の詳しくは M5StickC PLUSとロータリーエンコーダ をご覧ください。

ESP32とTFT LCDとローターリーエンコーダーの配線

ロータリーエンコーダーは秋月電子通商さんのものを使いました。A、Bの2信号の位相差出力です。 ロータリーエンコーダ(ノンクリックタイプ): パーツ一般 秋月電子通商-電子部品・ネット通販

ロータリーエンコーダーを使うにあたって、プルアップ抵抗が必要になります。ここではESP32内蔵のプルアップ機能を使いました。ただし、ESP32のIO34~IO39はプルアップできないのでご注意ください。

ESP32とTFT LCDとローターリーエンコーダーの配線
ESP32とTFT LCDとローターリーエンコーダーの配線

ライブラリのインストール

ロータリーエンコーダーのプログラミングはかなり複雑なので、ライブラリを使うと良いです。

▼ 下記サイトより、RotaryEncoderのライブラリRotaryEncoder.hRotaryEncoder.cpp 拾ってきます。 GitHub-mathertel / Rotary Encoder : Rotary Encoder Arduino Library

また、Org_01.h を追加してTFT LCDに表示させる文字のフォントを変えてみました。Org_01.hAdafruit-GFX-Library に同包されてます。 Adafruit-GFX-Library/Fonts at master · adafruit/Adafruit-GFX-Library · GitHub

.ttf フォントからC++のヘッダーファイルに変換してくれるツールも配布されてます。 Adafruit-GFX-Library/fontconvert at master · adafruit/Adafruit-GFX-Library · GitHub

私の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ディスプレイに映される数値が変化します。ローターリーエンコーダの上限下限を設けるようにしてあります。詳しくはソースコードないの注釈をご覧ください。

with_pot.ino
/**
 * @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 = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

RotaryEncoder encoder(RE_A, RE_B, RotaryEncoder::LatchMode::TWO03);

int lastPos = -1;

void clearDisplay() {
    tft.fillScreen(RED);
}

void setup(void) {
    Serial.begin(115200);
    tft.initR(INITR_GREENTAB);
    
    clearDisplay();
    tft.setRotation(1);
    tft.setTextWrap(false);

    tft.setFont(&Org_01);
    tft.setTextSize(2);
    tft.setCursor(20, 20);
    tft.print("Ready...");

    // pinMode(RE_A, INPUT_PULLUP); RotaryEncoderのコンストラクタでプルアップされているので必要ない
    // pinMode(RE_B, INPUT_PULLUP);

    encoder.setPosition(25 / ROTARYSTEPS);

    delay(2000);
}

void loop() {
    encoder.tick();  // just call tick() to check the state.

    int newPos = encoder.getPosition() * ROTARYSTEPS;
    
    if (newPos < ROTARYMIN) {
        encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
        newPos = ROTARYMIN;

    } else if (newPos > ROTARYMAX) {
        encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
        newPos = ROTARYMAX;
    }  // if

    if (lastPos != newPos) {
        lastPos = newPos;

        char buff[5];
        sprintf(buff, "%2d", newPos);  // 数字を右寄せで表示させるため
        tft.setTextWrap(false);

        clearDisplay();

        tft.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);

        delay(50);
    }
}

TFT LCDの色がおかしい

ソースコードのコメントにも書きましたが、ST77XX_RED などの一部の色が青色になってしまい、TFT LCDの色がおかしいバグがあります。そのため、独自で定義して色を反映させてます。

cpp
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互換機
Arduinoで人気の周辺パーツ
あると便利な道具
Arduinoのオススメ参考書

▼ Arduino初心者向きの内容です。ほかのArduino書籍と比べて図や説明がとてもていねいで読みやすいです。Arduinoで一通りのセンサーが扱えるようになります。

▼ 外国人が書いた本を翻訳したものです。この手の書籍は、目からうろこな発見をすることが多いです。

▼ Arduinoの入門書を既に読んでいる方で、次のステップを目指したい人向きの本です。C言語のプログラミングの内容が中心です。ESP32だけでなく、ふつうのArduinoにも役立つ内容でした。

関連記事