ILI9341,2.8 “, 240×320 LCD

今回はタッチセンサー付きのLCDです。

裏面にはSDカードソケットが付いていました。

仕様はこんな感じです。

サイズ2.8”
LCDドライバILI9341
解像度(X, Y)240, 320
通信方式SPI
動作電圧3.3~5V
タッチセンサ有り
その他SDカードソケット

ESP32に繋いで動作を確認。

ハード

先ずはLCDへの表示とタッチセンサの確認を行います。使用した回路は以下の通りです。

  • 通信方式がSPIなので、ESP32のデフォルトピンを接続していますが、それ以外は配線しやすいように選んでいます。
  • タッチセンサを使用しなければ、10から14(頭が”T_”で始めるピン)は配線する必要は有りません。

SPIの信号線をLCDとタッチセンサで共有しています。ただ、MOSIとT_DIN 、 MISOとT_DO を繋いでいる点に注意が必要です。(感覚的に逆な感じがしました)

LCDESP32
VCCVCC
GNDGND
CSGPIO22
RESETEN
DCGPIO21
MOSIGPIO23
SCKGPIO18
LEDGPIO05
MISOGPIO19
10T_CLKGPIO18
11T_CSGPIO17
12T_DINGPIO23
13T_DOGPIO19
14T_IRQGPIO16

ソフト

Arduino IDEでESP32の開発が出来る環境を前提として話を進めます。今回はLCD表示用ライブラリーとして”TFT_eSPI”を使用しています。先ずはライブラリーのインストール。Arduino IDEで ツール ー> ライブラリー管理と進み ライブラリマネージャの検索欄に”tft_espi”と入力するとTFT_eSPIが表示されます。それをインストール。

インストール後、Arduino\libraries\TFT_eSPI-masterフォルダに”User_Setup.h”が出来ます。これを今回のハードに合わせて編集します。この設定ファイルですがLCDのドライバに合わせて行う必要が有ります。ドライバは”ILI9341”なのでそれに合わせて設定して行きます。

  • ドライバの選択
    • 46行位にドライバーの選択が有ります。
    • 今回は、ILI9341_2_DRIVER を選択しています。
  • 解像度の指定
    • 85行目あたりに解像度の設定が有ります。
    • 240x320を下記の様に設定しています。
  • バックライトのオンオフ設定
    • 大体130行目あたりに(今回は132,133行)LCDのバックライトのオンオフ設定が有ります。
    • LCDのピン8のLEDがこれに当たります。今回はGPIO05と繋いでいるので define TFT_BL  5。
    • その下でオン条件を設定しています。 これで HIGHでオンに成ります。
  • SPI設定
    • 212行あたりにSPI信号関係の設定が有ります。
    • 今回はリセットピンをESP32のリセットと共有しています。設定ファイル的にはこのピンを使用していない扱いとなります。この様な場合は”ー1”を指定します。(下記217行)
  • 今回は使用しませんが
    • 今回は上記のSPIをVSPIとして使用する為設定しませんが、HSPIとして使用したい場合下記の378行のコメントを外します。

上記設定後、Arduino IDEで ファイル ー> スケッチ例 ー>  TFT_eSPI ー>  320×240 ー> Keypad_240x320 を選択してデモ用スケッチを読み込みます。このスケッチはLCDにキーパッドを表示するプログラムです。コンパイル後、実行して下さい。最初の1回のみLCDのキャリブレーションが実行されます。

LCDの隅に上記の様な矢印が表示され矢印の先をタッチします。指でもOKですが、付属のタッチペンの方が感度が良いです。4箇所順に聞かれます。順にタッチして下さい。キャリブレーションが終わるとキーパッドが表示されます。

キーを押すと上の表示欄に数字が表示されます。Sendキーを押すと表示された文字がシリアルモニタに転送されます。(スケッチて転送レートを9600にしているのでシリアルモニタの転送レートを9600にセットして下さい)

割り込み処理は

LCDからの割り込みは下記の様にして確認する事が出来ます。

interrupt.ino

#include <SPI.h>
#include <TFT_eSPI.h>      // Hardware-specific library

TFT_eSPI tft = TFT_eSPI(); // Invoke custom library

int tm;
#define T_IRQ   21

//------------------------------------------------------------------------------------------

void IRAM_ATTR onTouch() {
  tm ++;
  Serial.println("touched " + String(tm));
}

void setup() {
  // Use serial port
  Serial.begin(9600);

  // Initialise the TFT screen
  tft.init();

  // Set the rotation before we calibrate
  tft.setRotation(0);

  // Clear the screen
  tft.fillScreen(TFT_WHITE);

  tm = 0;
  pinMode(T_IRQ, INPUT_PULLUP);
  attachInterrupt(T_IRQ, onTouch, FALLING);

}

//------------------------------------------------------------------------------------------

void loop(void) {
  delay(1000);
}

LCDからの割り込み信号はLOWがアクティブなので割り込み条件を”立ち下がり”(FALLING)に設定します。(31行)

このプログラムを実行するとLCDの画面が白くなり、画面を触る度にシリアルモニタに触った回数が表示されます。割り込みも問題無く機能します。

SDカードはちょっと問題

次はSDカードの確認。このカードはLCDとタッチセンサでSPI信号線を共有しCS信号でお互いを区別しています。そこで同じコンセプトをSDカードに適応した下記の回路を試して見ました。CSを別にSPI信号線を共通とした回路です。

評価に使用したスケッチは以下。プログラムの内容は

test.ino

#include <SPI.h>
#include <SD.h>
#include <TFT_eSPI.h>      // Hardware-specific library

TFT_eSPI tft = TFT_eSPI(); // Invoke custom library

#define sd_sck          18
#define sd_mosi         23
#define sd_ss           4
#define sd_miso         19

//------------------------------------------------------------------------------------------

SPIClass sd_spi(VSPI);

void setup() {
  // Use serial port
  Serial.begin(115200);

  // Initialise the SD
  sd_spi.begin(sd_sck, sd_miso, sd_mosi, sd_ss);
  SD.begin(sd_ss, sd_spi);

  // Initialise the TFT screen
  tft.init();
}

//------------------------------------------------------------------------------------------

void loop(void) {
  File fp;
  String line;
  
  tft.setRotation(1);
  tft.fillScreen(TFT_BLACK);            // Clear screen
  tft.setTextDatum(MC_DATUM);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  tft.setTextSize(6);

  fp = SD.open("/test.txt", FILE_WRITE);
  fp.println("TEST 123");
  fp.close();
  
  fp = SD.open("/test.txt", FILE_READ);
  line = fp.readStringUntil(0x0d);
  fp.close();

  Serial.println("data: " + line);
  tft.drawString(line,160,120);

  while(1) ;
}
  • 7〜10行  SD用SPIピン定義。CSのみ変えて他はLCDのSPIと同じ
  • 14行    SD用SPI(VSPI)のインスタンスを作成
  • 21,22行 SDカードの初期設定
  • 25行    LCDの初期設定
  • 34〜38行 LCDを画面設定
  • 40〜42行 SDカードに”TEST 123”と書き込む
  • 44〜46行 SDカードから書き込んた値を読み取る
  • 48行    モニターに読み込んだ値を表示
  • 49行    LCDに読み込んだ値を表示

正常に動けばシリアルモニタとLCDに”TEST 123”と表示されるはずです。このスケッチは正常に動きました。ところが、SDカードとLCDの初期化の順番を逆にすると、SDカード、LCDともに動作しません。次にSDカード用SPIのインスタンスをVSPIからHSPIに変更して同じ事を実行した所下記の様に成りました。

VSPIHSPI
ABAB
SDLCDSDLCD
LCDSDLCDSD
SDLCDSDLCDSDLCDSDLCD
OKOKNGNGNGNGOKNG

上の表右がHSPIで宣言した場合の結果です。A:SD,LCDの順に初期化した場合。B:LCD,SDの順に初期化した場合です。HSPIで宣言するとSDを先に初期化するとSD、LCD共に動作せず、逆に初期化するとSDは動くのですがLCDが動かない結果と成りました。

訳の分からない結果となったので、LCDとSDのSPIの信号線を分けたらどうなるか確認して見ました。使った回路は以下

LCDとSDカードでSPIの信号線は完璧に別にしています。この回路で同じ評価をすると下記の様に成りました。

VSPIHSPI
ABAB
SDLCDSDLCD
LCDSDLCDSD
SDLCDSDLCDSDLCDSDLCD
NGNGOKOKOKOKOKOK

増々分からない結果と成りました。でも一つだけ確実なのは 

  • SDのインスタンスをHSPIで宣言し、SPIの信号線をLCDと別にすれば初期化の順番に関係無く動作する

です。評価したどのパターンでも動作するように思えるのですが動作しない理由がわかりません。

最後に

SDカードの使い方に若干の疑問は残りましたが、値段に対して反応は速く綺麗です。タッチセンサの感度は若干悪く指でも反応はしますが付属にタッチペンの方が感度が良いです。