Arduino環境で使用できるLCDモジュール ST7789を紹介します。
LCDパネルの仕組みの違いによる比較、ESP32系とRP2040系でのSPI接続によるLCD表示、JPG表示をしてみます。
今回紹介するもの
LCDモジュール (ST7789) 2.0inch
製品情報
Arduino環境で扱えるLCDとしては中型サイズです。
このモジュールのLCDはIPSを採用しているので、斜めからモニタを見た時の色変化が小さい。
解像度も高いので詳細な画像表示ができる。
サイズ | 2.0inch |
解像度(X, Y) | 320, 240 |
パネル方式 | IPS |
通信方式 | SPI |
ドライバ | ST7789 |
動作電圧 | 3.3V |
ST7789ドライバをマイコン基板に実装したモデルもあります。
こちらはESP32-WROOM32 搭載基板で、技適マークもあるので無線を使用できます。
RP2040搭載基板ではこちら。
ピン配置
DC, CS, RES はこのモジュール専用に割り当てます。
通常のGPIO配線を使用します。
SDA(MOSI), CLK(SCK)は、SPI配線でピンの割り当てができるGPIOを指定します。
この2本は他のSPIモジュールと共用で使用することができます。
BLKはVCCの電源(3V3)を使用してもいいですが、GPIOをPWMで制御することでバックライトの輝度調整やフェードイン/アウト効果を演出することもできます。
外観
前面
背面
使用感
同サイズ帯にST7735 もあります。
同じSPIを使用しますが、ピン配置が全く違うので気を付けてください。
表示のみで、SDカードやタッチパネルのないシンプルな設計です。
2.0インチでも解像度が320×240(QVGA)あるので、画素が細かくスマートフォンほどではないですがかなり詳細な画像を表示することができます。
IPS LCDパネルを使用しているので視野角が広く、カラーOLED並みに色彩変化がありません。
視野角については比較画像を載せました。
中型サイズLCD ILI9341 2.4inch はこちらで紹介しています。
こちらはタッチパネルが使用できます。記事を追記しました。[2023/2/10]
大型サイズLCD ILI9486 4.0inch ではJPG表示、タッチ操作を紹介しています。
準備
ライブラリ
LCDを制御するためのライブラリにはAdafruit製ライブラリを使用します。
ST7735と共通ライブラリです。
ライブラリ名 | 用途 | 検索 | 確認時バージョン |
---|---|---|---|
Adafruit GFX Library by Adafruit | グラフィック | GFX | 1.11.3 |
Adafruit ST7735 and ST7789 Library by Adafruit | グラフィック | ST7789 | 1.9.3 |
TJpg_Decoder by Bodmer | JPG表示 | JPG | 1.0.8 |
Adafruit ST7735 and ST7789 Library by Adafruitライブラリをインストールすると、依存ライブラリが不足している場合不足している依存関係のインストールの問い合わせがあります。
「すべてをインストール」を選択してください。
画像はILI9341ライブラリをインストールするときの依存関係のインストール画面を流用しています。
使い方
表示
説明
RP2040系(Raspberry Pi Pico BOOT)を使用して表示制御します。
H/W SPI0を使用する参考にしてください。
図形などほかの描画サンプルは
スケッチ例 > Adafruit ST7735 and ST7789Library > graphicstest_st7789
を参照してください。
配線(RP2040系 Raspberry Pi Picoの場合)
RP2040 pico | 配線 | ST7789 |
---|---|---|
GND | 黒 | GND |
3.3V | 赤 | VCC |
GPIO28 | 橙 | DC |
GPIO17 | 黄 | CS |
GPIO18 | 紫 | CLK |
GPIO19 | 緑 | SDA(MOSI) |
GPIO22 | 青 | RES |
3.3V | 赤 | BLK |
スケッチ
/**********************************************************************
【ライセンスについて】
Copyright(c) 2022 by tamanegi
Released under the MIT license
'http://tamanegi.digick.jp/about-licence/
【マイコン基板】
Raspberry Pi Pico
【スケッチの説明】
SPI0 を使用し、ST7789の表示を行います。
【ライブラリ】
Raspberry Pi Pico/RP2040 > Raspberry Pi Pico
Adafruit ST7735 and ST7789 Library
Adafruit GFX Library
【準備】
Raspberry Pi Pico <-> ST7789
3.3V <-> VCC
GND <-> GND
GPIO17(SPI0 CS) <-> TFT CS
GPIO22 <-> TFT Reset
GPIO28 <-> TFT AO(D/C)
GPIO19(SPI0 MOSI) <-> TFT SDA
GPIO18(SPI0 SCK) <-> TFT SCK
3.3V <-> LED
【バージョン情報】
2023/2/23 : 新規
2023/3/9 : コメント修正 ライブラリ"Raspberry Pi Pico/RP2040 > Raspberry Pi Pico"
**********************************************************************/
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>
#define TFT_CS 17
#define TFT_RST 22
#define TFT_DC 28
#define TFT_MOSI 19
#define TFT_SCK 18
Adafruit_ST7789 tft = Adafruit_ST7789(&SPI, TFT_CS, TFT_DC, TFT_RST);
//S/W SPIはこちら。遅いが任意のピンを使用できる。
//Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCK, TFT_RST);
void setup(void)
{
tft.init(240, 320);
tft.fillScreen(ST77XX_BLACK); //背景の塗りつぶし
//テキスト表示
tft.setRotation(3); //画面回転
tft.setTextSize(4); //サイズ
tft.setCursor(0, 10); //カーソル位置
tft.setTextColor(ST77XX_GREEN); //緑
tft.printf("TAMANEGI\n");
tft.setTextSize(3); //サイズ
tft.setTextColor(ST77XX_RED); //赤
tft.printf("\n2.0inch LCD\n");
tft.setTextColor(ST77XX_YELLOW); //黄
tft.printf("Res=240 x 320\n");
tft.setTextColor(ST77XX_BLUE); //青
tft.printf("ST7789\n");
}
void loop()
{
}
配線(ESP32系 BananaPi PicoWの場合)
BananaPi PicoW | 配線 | ST7789 |
---|---|---|
GND | 黒 | GND |
3.3V | 赤 | VCC |
GPIO10 | 橙 | DC |
GPIO2 | 黄 | CS |
GPIO3 | 紫 | CLK |
GPIO4 | 緑 | SDA(MOSI) |
GPIO7 | 青 | RES |
3.3V | 赤 | BLK |
スケッチ
/**********************************************************************
【ライセンスについて】
Copyright(c) 2022 by tamanegi
Released under the MIT license
'http://tamanegi.digick.jp/about-licence/
【マイコン基板】
BananaPi PicoW
【スケッチの説明】
SPI を使用し、ST7789の表示を行います。
【ライブラリ】
esp32 > ESP32S3 Dev Module
Adafruit ST7735 and ST7789 Library
Adafruit GFX Library
【準備】
BananaPi PicoW <-> ST7789
3.3V <-> VCC
GND <-> GND
GPIO2(SPI0 CS) <-> TFT CS
GPIO7 <-> TFT Reset
GPIO10 <-> TFT AO(D/C)
GPIO4(SPI0 MOSI) <-> TFT SDA
GPIO3(SPI0 SCK) <-> TFT SCK
3.3V <-> LED
【バージョン情報】
2023/3/9 : 新規
**********************************************************************/
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>
#define TFT_CS 2
#define TFT_RST 7
#define TFT_DC 10
#define TFT_MOSI 4
#define TFT_SCK 3
Adafruit_ST7789 tft = Adafruit_ST7789(&SPI, TFT_CS, TFT_DC, TFT_RST);
//S/W SPIはこちら。遅いが任意のピンを使用できる。
//Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCK, TFT_RST);
void setup(void)
{
SPI.begin(TFT_SCK, -1, TFT_MOSI, TFT_CS);
tft.init(240, 320);
tft.fillScreen(ST77XX_BLACK); //背景の塗りつぶし
//テキスト表示
tft.setRotation(3); //画面回転
tft.setTextSize(4); //サイズ
tft.setCursor(0, 10); //カーソル位置
tft.setTextColor(ST77XX_GREEN); //緑
tft.printf("TAMANEGI\n");
tft.setTextSize(3); //サイズ
tft.setTextColor(ST77XX_RED); //赤
tft.printf("\n2.0inch LCD\n");
tft.setTextColor(ST77XX_YELLOW); //黄
tft.printf("Res=240 x 320\n");
tft.setTextColor(ST77XX_BLUE); //青
tft.printf("ST7789\n");
}
void loop()
{
}
結果
表示ができました。
表示(SDカードからjpgファイルの表示)
説明
SDカードリーダよりjpgファイル”test.jpg”を読み取り、TFTに表示をします。
SDカードのルートフォルダには”test.jpg”ファイルを保存してください。
jpgファイルのサイズは320 x 240で作成します。
配線
RP2040系(Raspberry Pi Pico)を使用した配線を掲載します。
SPI0をTFTとSDカードリーダ共通で使用します。
RP2040 pico | 配線 | ST7789 | 配線 | TFカードリーダ |
---|---|---|---|---|
GND | 黒 | GND | 黒 | GND |
3.3V | 赤 | VCC | 赤 | VCC |
GPIO28 | 橙 | DC | ||
GPIO17 | 黄 | CS | ||
GPIO18 | 紫 | CLK | 紫 | CLK |
GPIO19 | 緑 | SDA(MOSI) | 緑 | MOSI |
GPIO22 | 青 | RES | ||
3.3V | 赤 | BLK | ||
GPIO21 | 黄 | 黄 | CS | |
GPIO19 | 茶 | 茶 | MISO |
スケッチ
/**********************************************************************
【ライセンスについて】
Copyright(c) 2022 by tamanegi
Released under the MIT license
'http://tamanegi.digick.jp/about-licence/
【マイコン基板】
Raspberry Pi Pico
【スケッチの説明】
SDカードモジュールからtest.jpgを読み出しST7735に表示します。
【ライブラリ】
Raspberry Pi Pico/RP2040 > Raspberry Pi Pico
Adafruit GFX Library
Adafruit ST7735 and ST7789 Library
TJpg_Decoder
【準備】
SDカードのルートフォルダに "test.jpg"を保存します。
jpgファイルのサイズは 160 x 128 サイズで保存します。
SPI0のMOSIとSCKは共通で使用します。
Raspberry Pi Pico <-> ST7789
<<TFT側>>
3.3V <-> VCC
GND <-> GND
GPIO17(SPI0 CS) <-> TFT CS
GPIO22 <-> TFT Reset
GPIO28 <-> TFT AO(D/C)
GPIO19(SPI0 MOSI) <-> TFT SDA
GPIO18(SPI0 SCK) <-> TFT SCK
3.3V <-> LED
<<SDカードリーダ側>>
GPIO21 <-> SD CS
GPIO19(SPI0 MOSI) <-> SD MOSI
GPIO16(SPI0 MISO) <-> SD MISO
GPIO18(SPI0 SCK) <-> SD SCK
【バージョン情報】
2023/2/23 : 新規
**********************************************************************/
#include <SPI.h>
#include <SD.h>
#include <TJpg_Decoder.h>
#include <Adafruit_ST7789.h>
#include <Adafruit_GFX.h>
//TFT SD共通ピン設定
#define COMMON_MOSI 19
#define COMMON_SCK 18
//TFTピン設定
#define TFT_CS 17
#define TFT_RST 22
#define TFT_DC 28
//SDピン設定
#define SD_CS 21
#define SD_MISO 16
#define FILENAME "/test.jpg"
// JPGの最大サイズ(バッファを静的に確保するようにしているため、決め打ち。取り扱う最大ファイルサイズで変えるようにする)
#define JPG_SIZE_MAX (20 * 1024) //MAX 20KByteを想定
Adafruit_ST7789 tft = Adafruit_ST7789(&SPI, TFT_CS, TFT_DC, TFT_RST);
struct jpg_file
{
size_t size;
uint8_t buf[JPG_SIZE_MAX];
};
jpg_file jpg;
//デコードを行うコールバック関数
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap)
{
if (y >= tft.height())
return 0;
tft.drawRGBBitmap(x, y, bitmap, w, h);
return 1;
}
void setup()
{
//SPIピン設定
SPI.setTX(COMMON_MOSI);
SPI.setRX(SD_MISO);
SPI.setSCK(COMMON_SCK);
//TFTの初期化と初期設定
tft.init(240, 320);
tft.fillScreen(ST77XX_BLACK); //背景の塗りつぶし
tft.setRotation(3);
Serial.begin(115200);
//while(!Serial);
delay(1000);
//SDカードリーダの初期化とファイルの読み取り
if (!SD.begin(SD_CS, SD_SCK_MHZ(16)))
{
Serial.println("SD initialization failed!");
while(1);
}
TJpgDec.setCallback(tft_output);
File jpgFile = SD.open(FILENAME, FILE_READ);
if (!jpgFile)
{
Serial.printf("Open file failed [%s]\r\n", FILENAME);
while(1);
}
jpg.size = jpgFile.size();
if(sizeof(jpg.buf) < jpg.size)
{
Serial.println("File size over");
return;
}
//ファイル情報の表示
uint16_t w = 0, h = 0;
Serial.printf("file size = %d bytes\r\n", jpgFile.readBytes((char *)jpg.buf, jpg.size));
TJpgDec.getJpgSize(&w, &h, jpg.buf, jpg.size);
Serial.printf("Width = %d, height = %d\r\n", w, h);
TJpgDec.setJpgScale(1);
TJpgDec.drawJpg(0, 0, jpg.buf, jpg.size); //画像の表示
jpgFile.close();
}
void loop()
{
}
結果
SDカード内のjpgファイルの表示をしました。
こちらではSDカードのファイルリストの作成 を紹介しています。
組み合わせて使用することでフォトフレームなどを作ることができます。
比較
ライブラリが同梱されているST7735 1.8inchと同画面を表示して比較しました。
正面
ST7735(上)1.8inch, 128×160
ST7789(下)2.0inch, 240×320
JPG画像は、それぞれの解像度で作成しているので、ST7735は画素の粗さがわかります。
視野角
上方、下方からの視野角は広く色彩の変化は見られません。
ST7789(青い方)で左右からみても色彩変化はほとんど見られません。
ST7735は上の画像では色彩の変化がはっきりと出ています。
下の画像はワイヤーが邪魔であまり角度をつけて撮影できていませんが、画像は黒く変化します。
コメント
少し教えて下さい。PICOとST7789液晶(Waveshare 1.47inch)を接続して実験しているのですが、なぜかうまくいきません。SPI0を使用しているのですが、GP17/GP18/GP19の代わりに
GP5/GP3/GP2を使用するとなぜか表示されません。ソフトSPIだとちゃんと描画されるので接続ミスとかではないと思われます。GP5/GP3/GP2もSPI0の割付なのになんでこちらだと描画されないのかお分かりでしたら教えてもらえますと助かります。
ソフトSPIではST7789オブジェクト宣言時(コンストラクタ)に使用するピンを指定しますが、
ハードSPIを任意のピンで使用する場合はSPIオブジェクトにピン設定する必要があります。
SPI0用のオブジェクト(SPI)でMOSIとSCKのピン設定をされていますか?
例:
SPI.setTX(3);
SPI.setSCK(2);
tft.init(240, 320);
一度試してみてください。