RaspberryPi Picoで感圧式タッチ付きLCDモジュールを使う(ST7735)

コンピュータ、組み込み

ST7735 1.8inchのタッチ付きLCDモジュールを入手しました。
Raspberry Pi Pico、ESP32系を使った表示、タッチ、SDカードの読み取りをしてみます。

今回紹介するもの

LCDモジュール (ST7735) 1.8inch

特徴

LCDディスプレイとタッチパネルとSDカードスロットがついています。
電源とGNDは共通ですが、それぞれ独立して制御します。

サイズ1.8inch
解像度(X, Y)128, 160
通信方式SPI
LCDドライバST7735
動作電圧3.2~5V
パネルTN方式
タッチドライバXPT2046 (HR2046互換)
感圧式
タッチ解像度4K x 4K
その他SDカードリーダ


LCDディスプレイとSDカードスロットのモデルはこちらで紹介しています。

ピン配置

左側が電源とLCDの制御線、右側の上部がSDカードモジュール、右側の下部がタッチパネルの制御線です。
ピン配置表では水平方向のピン位置が合っていますが、現物は半ピッチほどずれています。
(つまり2.54ピッチのユニバーサル基板にきれいに実装できません。)

外観

前面

背面

使用感

ST7735の1.8inchLCDにタッチパネルが搭載されたことで機能面が充実しました。
画面が小さくて解像度も低めなので詳細画像の表示には不向きですが、画像データが小さくて済むのでストレージの節約になると考えています。

当サイトでST7735をAdafruit製ライブラリを使用したサンプルを掲載しています。
以前紹介した記事では、標準で用意されている初期化オプションを使用することで簡単に表示制御をすることができましたが、今回のタッチ付きLCDでは難点が2つほどあります。

・表示エリアが少しオフセットしています。
この後の記事でオフセットの修正方法を記載するので参考にしてください。
当サイトでは修正したライブラリでサンプルを掲示します。

・ピンピッチが合わない。
ピン自体は2.54ピッチで並んでいますが、LCD側とSD、タッチ側のピンの水平方向の高さが合っていません。
サンプルの紹介ではブレッドボードを2つ使用しているので気になりませんが、ユニバーサル基板に実装する場合は、何らかの工夫が必要です。

その他の中、大型LCDの記事はこちら

大型サイズLCD ILI9486 4.0inch ではJPG表示、タッチ操作を紹介しています。

準備

ライブラリ

LCDとタッチパネルを制御するためのライブラリをインストールします。
SDカードリーダはArduinoIDEインストール時にインストールされています。

ライブラリ名用途検索確認時バージョン
Adafruit GFX Library by AdafruitグラフィックGFX1.11.3
Adafruit ST7735 and ST7789
Library by Adafruit
グラフィックST77351.9.3
XPT2046_Touchscreen by Paul StoffregenタッチパネルXPT20461.4
TJpg_Decoder by Bodmerjpg表示jpg1.0.8

不足している依存関係のインストールの問い合わせがあれば「すべてをインストール」を選択してください。

ライブラリの修正

概要

当サイトではタッチ付きST7735 LCDの表示にはAdafruit製ライブラリを使用しています。
基本的にタッチ無ST7735モニタと同じスケッチで動作をしますが、画面が少しオフセットされてしまいます。
以下の画像では、画面の左と下が砂嵐状態の表示が見えます。

こちらを解消するために、Adafruitライブラリを一部修正して使用します。
修正に失敗した場合(コンパイルができなくなったり、修正前と同じ表示ができなくなった)は、ライブラリを再インストールすることで復旧できます。

修正箇所と修正方法

ローカルPC内のAdafruit ST7735 & ST7789 ライブラリフォルダを開きます。

Adafruit_ST7735.cpp の268行目に以下のスケッチを挿入します。

  if (options == INITR_BLACKTAB2) {
    _colstart = 2;			//Macro definition added to set the offset.
    _rowstart = 1;

    uint8_t data = 0xC0;
    sendCommand(ST77XX_MADCTL, &data, 1);
    options = INITR_BLACKTAB;
  }

Adafruit_ST7735.h の17行目に以下のスケッチを挿入します。

#define INITR_BLACKTAB2 0x07

メインのスケッチの初期化には、今回追加した INITR_BLACKTAB2 を指定します。
この修正を適用したスケッチは次の「使い方」で紹介します。

使い方

LCD表示

説明

RP2040系(Raspberry Pi Pico)を使用して表示制御します。
H/W SPI0を使用する参考にしてください。

図形などほかの描画サンプルは
スケッチ例 > Adafruit ST7735 and ST7789Library > graphicstest_st7789
を参照してください。

配線(RP2040系 Raspberry Pi Pico)
Raspberry Pi pico配線ST7735
3.3VVCC
3.3VLED
GNDGND
GPIO1(SPI0 CS)CS
GPIO28Reset
GPIO27D/C
GPIO3(SPI0 TX)SDI(MOSI)
GPIO2(SPI0 SCK)SCK
スケッチ(RP2040系 Raspberry Pi Pico)
/**********************************************************************
【ライセンスについて】
Copyright(c) 2022 by tamanegi
Released under the MIT license
'http://tamanegi.digick.jp/about-licence/

【マイコン基板】
RaspberryPi Pico 

【スケッチの説明】
ST7735 LCDの制御をします。
SPIは SPI0とSPI1のどちらのサンプルも掲載しますが、
SPI1側はコメントアウトしますので、状況に応じてコメントを外してください。
※コメント検索 [SPI1の場合]

【ライブラリ】
Raspberry Pi Pico / RP2040 > Raspberry Pi Pico
Adafruit ST7735 and ST7789 Library (修正版)
Adafruit GFX Library

【準備】
マイコン基板 <-> ST7735
3V3               <-> VCC
GND               <-> GND
GPIO1(SPI0 CS)    <-> CS
GPIO28            <-> Reset
GPIO27            <-> AO
GPIO3(SPI0 MOSI)  <-> SDA
GPIO2(SPI0 SCK)   <-> SCK

【バージョン情報】
2023/6/1 : 新規
**********************************************************************/

#include <Adafruit_GFX.h> 
#include <Adafruit_ST7735.h>
#include <SPI.h>

//SPI0の場合
#define TFT_CS          1   // CS
#define TFT_RST         28  // Reset 
#define TFT_DC          27  // DC
#define TFT_MOSI        3   // MOSI
#define TFT_SCK         2   // SCK

//SPI1の場合
// #define TFT_CS          13  // CS
// #define TFT_RST         28  // Reset 
// #define TFT_DC          27  // DC
// #define TFT_MOSI        15  // MOSI
// #define TFT_SCK         14  // SCK

//SPI0の場合
Adafruit_ST7735 tft = Adafruit_ST7735(&SPI, TFT_CS, TFT_DC, TFT_RST);
//SPI1の場合
//Adafruit_ST7735 tft = Adafruit_ST7735(&SPI1, TFT_CS, TFT_DC, TFT_RST);

void setup(void) 
{
  //SPI0の場合
  SPI.setTX(TFT_MOSI);
  SPI.setSCK(TFT_SCK);

  //SPI1の場合
  // SPI1.setTX(TFT_MOSI);
  // SPI1.setSCK(TFT_SCK);
  

  tft.initR(INITR_BLACKTAB2);                  //Init ST7735S初期化 修正版ライブラリ使用
//  tft.initR(INITR_BLACKTAB);                  //Init ST7735S初期化 修正版ライブラリを使用しない場合は表示ずれがあるが、こちらで初期化

  tft.fillScreen(ST77XX_BLACK);               //背景の塗りつぶし

    //テキスト表示
  tft.setRotation(3);                         //画面回転
  tft.setTextSize(3);                         //サイズ

  tft.setCursor(0, 10);                       //カーソル位置                      
  tft.setTextColor(ST77XX_GREEN);             //緑
  tft.printf("TAMANEGI\n");

  tft.setCursor(0, 50);                       //カーソル位置                      
  tft.setTextSize(2);                         //サイズ
  tft.setTextColor(ST77XX_RED);               //赤
  tft.printf("1.8inch LCD\n");
  tft.setTextColor(ST77XX_YELLOW);            //黄
  tft.printf("Res=128 x 160\n");
  tft.setTextColor(ST77XX_BLUE);              //青
  tft.printf("ST7735\n");
}

void loop()
{
}
配線(ESP32系 Waveshare ESP32-S3-Pico)
ESP32-S3-Pico配線ST7735
3.3VVCC
3.3VLED
GNDGND
GPIO2CS
GPIO7Reset
GPIO10D/C
GPIO4SDI(MOSI)
GPIO3SCK
スケッチ(ESP32系 Waveshare ESP32-S3-Pico)
/**********************************************************************
【ライセンスについて】
Copyright(c) 2022 by tamanegi
Released under the MIT license
'http://tamanegi.digick.jp/about-licence/

【マイコン基板】
RaspberryPi Pico 

【スケッチの説明】
ST7735 LCDの制御をします。

【ライブラリ】
Raspberry Pi Pico / RP2040 > Raspberry Pi Pico
Adafruit ST7735 and ST7789 Library (修正版)
Adafruit GFX Library

【準備】
マイコン基板 <-> ST7735
3V3               <-> VCC
GND               <-> GND
GPIO12(SPI CS)    <-> CS
GPIO9             <-> Reset
GPIO8             <-> AO
GPIO14(SPI MOSI)  <-> SDA
GPIO13(SPI SCK)   <-> SCK
GPIO15(SPI MISO)  <-> non   ピン番号の変更だけ

【バージョン情報】
2023/6/1 : 新規
**********************************************************************/

#include <Adafruit_GFX.h> 
#include <Adafruit_ST7735.h>
#include <SPI.h>

//SPI0の場合
#define TFT_CS          12    // CS
#define TFT_RST         9     // Reset 
#define TFT_DC          8     // DC
#define TFT_MOSI        14    // MOSI
#define TFT_SCK         13    // SCK
#define TFT_MISO        15    //MISO      //表示では使用しませんが、デフォルトMISO位置に別のSPI機能を設定すると動作しなくなるためMISO位置を変更する


//VSPIの場合
Adafruit_ST7735 tft = Adafruit_ST7735(&SPI, TFT_CS, TFT_DC, TFT_RST);

void setup(void) 
{
  SPI.begin(TFT_SCK, TFT_MISO, TFT_MOSI, TFT_CS); 


  tft.initR(INITR_BLACKTAB2);                  //Init ST7735S初期化 修正版ライブラリ使用
//  tft.initR(INITR_BLACKTAB);                  //Init ST7735S初期化 修正版ライブラリを使用しない場合は表示ずれがあるが、こちらで初期化

  tft.fillScreen(ST77XX_BLACK);               //背景の塗りつぶし

    //テキスト表示
  tft.setRotation(3);                         //画面回転
  tft.setTextSize(3);                         //サイズ

  tft.setCursor(0, 10);                       //カーソル位置                      
  tft.setTextColor(ST77XX_GREEN);             //緑
  tft.printf("TAMANEGI\n");

  tft.setCursor(0, 50);                       //カーソル位置                      
  tft.setTextSize(2);                         //サイズ
  tft.setTextColor(ST77XX_RED);               //赤
  tft.printf("1.8inch LCD\n");
  tft.setTextColor(ST77XX_YELLOW);            //黄
  tft.printf("Res=128 x 160\n");
  tft.setTextColor(ST77XX_BLUE);              //青
  tft.printf("ST7735\n");
}

void loop()
{
}
結果

LCDの表示ができました。
結果はRP2040系 Raspberry Pi Pico を使用したものですが、ESP32-S3-Picoを使っても同じ画像が表示されます。

タッチパネル

説明

タッチパネルのタッチ状態と、タッチ座標を読み出してLCDに表示します。
使用したLCDのタッチドライバはXPT2046が実装されていました。

配線

画面の表示とタッチの読み取りはSPI0を共通で使用します。
タッチに使用するCSピンは画面とは別のCSピンを指定してください。

Raspberry Pi pico配線ST7735
3.3VVCC
3.3VLED
GNDGND
GPIO1(SPI0 CS)CS
GPIO28Reset
GPIO27D/C
GPIO3(SPI0 TX)SDI(MOSI)
GPIO2(SPI0 SCK)SCK
GPIO5破線黄T_CS
GPIO0(SPI0 MISO)T_OUT(MISO)
GPIO2(SPI0 SCK)T_CLK
GPIO3(SPI0 MOSI)T_DIN(MOSI)
スケッチ
/**********************************************************************
【ライセンスについて】
Copyright(c) 2022 by tamanegi
Released under the MIT license
'http://tamanegi.digick.jp/about-licence/

【マイコン基板】
Raspberry Pi Pico

【スケッチの説明】
タッチパネルを使用し、タッチ位置をLCD画面に表示します。

【ライブラリ】
Raspberry Pi Pico / RP2040 > Raspberry Pi Pico
Adafruit ST7735 and ST7789 Library (修正版)
Adafruit GFX Library
XPT2046_Touchscreen

【準備】
<<LCD側>>
Raspberry Pi Pico     <-> ST7735
3.3V                  <-> VCC
GND                   <-> GND
GPIO1(SPI0 CS)        <-> TFT CS
GPIO28                <-> TFT Reset
GPIO27                <-> TFT AO(D/C)
GPIO3(SPI0 MOSI)      <-> TFT SDA
GPIO2(SPI0 SCK)       <-> TFT SCK
3.3V                  <-> LED

<<Touch側>>
GPIO5                 <-> T_CS
GPIO0(SPI0 MISO)      <-> T_DO(MISO)
GPIO2(SPI0 SCK)       <-> T_CLK
GPIO3(SPI0 MOSI)      <-> T_DIN(MOSI)

【バージョン情報】
2023/6/1 : 新規
**********************************************************************/

#include <SPI.h>
#include <Adafruit_ST7735.h>
#include <Adafruit_GFX.h>
#include <XPT2046_Touchscreen.h>

//TFT SPIピン設定
#define TFT_CS          1   // CS
#define TFT_RST         28  // Reset 
#define TFT_DC          27  // DC
#define TFT_MOSI        3   // MOSI
#define TFT_SCK         2   // SCK

#define COMMON_SCK  2
#define COMMON_MOSI 3
#define COMMON_MISO 0

#define TOUCH_CS 5

XPT2046_Touchscreen ts(TOUCH_CS);
Adafruit_ST7735 tft = Adafruit_ST7735(&SPI, TFT_CS, TFT_DC, TFT_RST);

void setup()
{
  Serial.begin(115200);

  //SPI ピン設定
  SPI.setTX(COMMON_MOSI);
  SPI.setRX(COMMON_MISO);
  SPI.setSCK(COMMON_SCK);

  //TFTの初期化と初期設定
  tft.initR(INITR_BLACKTAB2);          //Init ST7735S初期化 修正版ライブラリ使用

  tft.fillScreen(ST77XX_BLACK);        //背景の塗りつぶし
  tft.setRotation(3);
  tft.setTextSize(1);
  tft.fillScreen(ST77XX_BLACK);

  //タッチ入力開始
  ts.begin();
  ts.setRotation(1);

}

void loop()
{
  //タッチ状態読み取り
  boolean bTouch = ts.touched();
  //画面クリア
  tft.fillRect(0, 0, 128, 64, ST77XX_BLACK);

  //タッチがあればタッチされている座標の表示
  if (bTouch == true)
  {
   TS_Point tPoint = ts.getPoint();
    tft.setTextColor(ST77XX_WHITE);
    tft.setCursor(0, 0);
    tft.printf("(x,y) = (%d, %d)\r\n", tPoint.x, tPoint.y);
    Serial.printf("(x,y) = (%d, %d)\r\n", tPoint.x, tPoint.y);
  }
  else 
  {
    //タッチがなければタッチ無表示
    tft.setTextColor(ST77XX_RED);
    tft.setCursor(0, 0);
    tft.print("No Touch");
    
  }
  delay(10);
}
結果

タッチの座標を読み出しました。

表示(SDカードからjpgファイルの表示)

説明

SDカードリーダよりjpgファイル”test.jpg”を読み取り、LCDに表示をします。

SDカードのルートフォルダには”test160x128.jpg”ファイルを保存してください。
jpgファイルのサイズは160 x 128で作成します。

配線

RP2040系(Raspberry Pi Pico)を使用した配線を掲載します。
SPI0をLCDとSDカードリーダ共通で使用します。

LCDのSDカードリーダも使用することができます。
電源とGND以外をシルク記載のピンに接続します。

Raspberry Pi pico配線ST7735
3.3VVCC
GNDGND
GPIO1(SPI0 CS)TFT CS
GPIO28TFT Reset
GPIO27TFT AO(D/C)
GPIO3(SPI0 MOSI)TFT SDA
GPIO2(SPI0 SCK)TFT SCK
GPIO6破線黄SD CS
GPIO3(SPI0 MOSI)SD MOSI
GPIO0(SPI0 MISO)SD MISO
GPIO2(SPI0 SCK)SD SCK

スケッチ

/**********************************************************************
【ライセンスについて】
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     <-> ST7735
<<TFT側>>
3.3V                  <-> VCC
GND                   <-> GND
GPIO1(SPI0 CS)        <-> TFT CS
GPIO28                <-> TFT Reset
GPIO27                <-> TFT AO(D/C)
GPIO3(SPI0 MOSI)      <-> TFT SDA
GPIO2(SPI0 SCK)       <-> TFT SCK
3.3V                  <-> LED

<<SDカードリーダ側>>
GPIO6                 <-> SD CS
GPIO3(SPI0 MOSI)      <-> SD MOSI
GPIO0(SPI0 MISO)      <-> SD MISO
GPIO2(SPI0 SCK)       <-> SD SCK

【バージョン情報】
2023/6/1 : 新規
**********************************************************************/

#include <SPI.h>
#include <SD.h>

#include <TJpg_Decoder.h>
#include <Adafruit_ST7735.h>
#include <Adafruit_GFX.h>

#define TFT_CS          1   // CS
#define TFT_RST         28  // Reset 
#define TFT_DC          27  // DC
#define TFT_MOSI        3   // MOSI
#define TFT_SCK         2   // SCK

#define COMMON_SCK  2
#define COMMON_MOSI 3
#define COMMON_MISO 0

#define SD_CS 6

#define FILENAME      "/test160x128.jpg"

// JPGの最大サイズ(バッファを静的に確保するようにしているため、決め打ち。取り扱う最大ファイルサイズで変えるようにする)
#define JPG_SIZE_MAX (20 * 1024) //MAX 20KByteを想定

Adafruit_ST7735 tft = Adafruit_ST7735(&SPI, TFT_CS, TFT_DC, TFT_RST);     //SPI0を使用

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(COMMON_MISO);
  SPI.setSCK(COMMON_SCK);

  //TFTの初期化と初期設定
  tft.initR(INITR_BLACKTAB2);                  //Init ST7735S初期化  (修正ライブラリ)
  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カードのファイルリストの作成 を紹介しています。
組み合わせて使用することでフォトフレームなどを作ることができます。

ライセンスについて

MIT License および ST7735/ST7789

Raspberry Pi Pico関連リンク

コメント

タイトルとURLをコピーしました