【Arduino】LCDモジュール(ILI9486)と静電容量タッチパネル(FT6236)を使う

it

3.5inch LCDと静電容量タッチパネル一体化モジュールを使います。
Arduino環境でRaspberry Pi PicoとESP32-WROOM32を使った表示制御をしました。
静電容量タッチパネルの多点入力を試してみました。

LCD ILI9486 + 静電容量タッチパネル FT6236

簡単紹介

3.5inch LCD と 静電容量タッチパネルが一体化したモジュールです。

◆関連記事

<LCD関連>

画像をクリックすると記事にジャンプします。

ST7735の記事です。
小型で安価、SPIで通信するLCDをRaspberry Pi Picoで表示、タッチパネル、SDカードリーダを使いました。
Nextion のHMI NX3224T024を使った記事です。
NextionEditorのセットアップと簡単な使い方、Raspberry Pi Picoと連動した画面制御について記事にしました。
ILI9341の記事です。
Arduino環境で使える中型サイズのLCDを使いました。
表示制御、タッチパネルとトラブル、SDカードからのJPG表示を記事にしました。
ILI9488の記事です。
表示制御以外にGT911静電容量式タッチパネルの多点タッチを使いました。
ESP32以外にRaspberry Pi Picoでも使用できるスケッチの修正を紹介しています。
ST7789の記事です。
IPS方式で発色のきれいなLCDです。
表示やタッチ制御以外にTNとIPS方式の視野角についても比べてみました。
SSD1331 カラーOLEDの記事です。
OLEDの鮮やかな発色と広い視野角のディスプレイです。
Raspberry Pi PicoとESP32-WROOM32での表示をしました。
ILI9486 3.5inch の記事です。
FT6236静電容量式タッチパネルをESP32-WROOMとRaspberryPi Pico/Pico2 で使った内容を記事にしました。

<使ったマイコン>

ピン配置

外観

使ってみた

◆開発環境

Arduinoを使った開発環境にESP32-WROOM32(Node MCU)とRaspberry Pi Pico / Raspberry Pi Pico2を使いました。

記事ではモジュール搭載のSDカードリーダが使えなかったため、別のSDカードリーダモジュールを使います。
コンパイル時「SDカードライブラリの重複エラー」が発生しエラーと対処について記載しました。

◆LCD部

マイコンからSPIで使えるLCDとしては中~大型の部類に入ると思います。
解像度は(w, h) = (320, 480) 、まずまずの解像度でJPGを表示してもきれいに表示します。
IPS方式で視野角が広いです。

下図は電源に3.3V(画像上)と5V(画像下)を使った時の差です。
画像ではわかりにくいですがはっきりとした輝度の違いがあります。
3.3Vでも十分画像の認識をできますが暗いと感じます。


◆タッチ部

電源はLCDの電源と共通で使えます。
LCDの供給電圧が3.3Vでも5Vでも使えました。

サンプルを動かすと2ポイントまでマルチタップできることを確認できました。
静電容量式なので軽やかなタッチ入力ができます。

1秒間に読み取れるポイント回数約60回程度で、十分な感度とサンプリングができます。
同時に読み取れるポイントは2点で、同時読み取りでもサンプリングが遅くなるようなことは見られませんでした。

参考程度に、同じ静電容量パネルのGT911との比較です。

FT6236GT911
サンプリング60Hz100Hz
同時タッチ25
分解能2K, 2K2K, 2K
サイズラインナップ3.5inch3.5inch, 4.0inch

サイズラインナップは当方の知るモデルです。
価格はLCDとセット価格になるので単体価格は不明です。
感覚としては変わらないくらいの価格設定に思います。

準備

◆開発環境

Arduino環境でESP32-WROOM(Node MCU)とRaspberryPi Pico/Raspberry Pi Pico2を使用します。
Arduino環境の準備はこちらの記事で紹介しています。

◆ボードライブラリ

<ESP32-WROOM>
ESP32-WROOM(Node MCU)ではArduino IDEのボードマネージャからESP32用のライブラリのインストールとボードの選択をします。

追加のボードマネージャのURLhttps://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
検索esp32
ボードライブラリesp32 by Espressif Systems
選択するボードesp32 > ESP32 Dev Module
※動作確認はバージョン 3.3.1です

<Raspberry Pi Pico / Raspberry Pi Pico2>
Raspberry Pi Pico / Raspberry Pi Pico2ではArduino IDEのボードマネージャからRP2040 / RP2350用のライブラリのインストールとボードの選択をします。
ボードライブラリには「Raspberry Pi Pico/RP2040/RP2350 by Earle F. Philhower, III」を使用します。

追加のボードマネージャのURLhttps://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
検索RP2040
ボードライブラリRaspberry Pi Pico/RP2040/RP2350 by Earle F. Philhower, III※
選択するボードRaspberry Pi Pico/RP2040/RP2350 > Raspberry Pi Pico
Raspberry Pi Pico/RP2040/RP2350 > Raspberry Pi Pico2
※動作確認はバージョン 4.1.1です

◆モジュールライブラリ

ライブラリ名用途検索確認時バージョン
ILI9486_SPI by Jean-Marc ZinggLCDILI94861.0.5
Adafruit GFX Library by AdafruitLCDILI94861.12.3
Adafruit BusIO by AdafruitLCDILI94861.17.4
bb_captouch by Larry BankタッチパネルGT9111.2.0※
TJpg_Decoder by BodmerJPGtjpg1.1.0

JPGに使用するライブラリ「TJpg_Decoder by Bodmer」はJPG画像をデコードするために使います。
JPG画像を使用しない場合はインストール不要です。

サンプルにはSDカードリーダモジュールを使用しますが、新しくライブラリはインストール不要です。
SDカードリーダライブラリはインストールの過去のライブラリインストールの過程で重複するトラブルが発生することがあります。
本記事でのサンプル対応方法については「SDカードライブラリの重複エラー」で紹介しています。

※記事中ではバージョン1.2.0を対象として「Raspberry Pi Pico / Raspberry Pi Pico2」でも動作するように修正します。

dafruit GFX Library By Adafruit と Adafruit BusIO by Adafruitは ILI9486_SPI by Jean-Marc Zingg の依存関係です。
インストール時に同時にインストールします。

トラブル

SDカードリーダモジュールが不動

◆現象

SDカード(Raspberry Pi Pico / Raspberry Pi Pico2)にて、実行時にSDカードリーダモジュールを認識できない。
SDカードリーダモジュール初期化失敗時のメッセージ「SD initialization failed!」がシリアル出力される。

◆配線

現象発生時の配線。

◆処置

別のSDカードリーダモジュールを使用する。

一体型のモジュールを使用できないことは残念ですがスケッチが使用できることを確認できた。
スケッチと別モジュールを使った時の配線サンプルはSDカード(Raspberry Pi Pico / Raspberry Pi Pico2)に記載する。

SDカードライブラリの重複エラー

◆現象

コンパイルするとSDライブラリ重複コンパイルエラーメッセージが表示される。

「SD.h」に対して複数のライブラリが見つかりました
使用済:C:\Users\xxxx\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\5.4.2\libraries\SD
未使用:C:\Users\xxxx\AppData\Local\Arduino15\libraries\SD
※xxxxはWindowsアカウント

◆処置

コンパイラの選択したライブラリを残し、未使用のライブラリを削除
今回削除したライブラリは「未使用:C:\Users\xxxx\AppData\Local\Arduino15\libraries\SD」

今回の処置では、未使用側のライブラリをフォルダごと削除しています。
ほかのスケッチで使用する場合は、別のフォルダに移動して後から戻せるようにするなどの対応をします。

使い方

LCDの表示(ESP32-WROOM)

説明

LCD上に色とサイズを変えながら文字列を表示します。

配線

スケッチ

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

#define TFT_CS            (5)
#define TFT_RST           (27)
#define TFT_DC            (26)
#define TFT_MOSI          (23)
#define TFT_SCK           (18)

#define ILI9486_BLACK     (0x0000)
#define ILI9486_WHITE     (0xFFFF)
#define ILI9486_RED       (0xF800)
#define ILI9486_GREEN     (0x07E0)
#define ILI9486_BLUE      (0x001F)
#define ILI9486_CYAN      (0x07FF)
#define ILI9486_MAGENTA   (0xF81F)
#define ILI9486_YELLOW    (0xFFE0)
#define ILI9486_ORANGE    (0xFC00)

ILI9486_SPI tft(TFT_CS, TFT_DC, TFT_RST);

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

  tft.setSpiKludge(false);
  tft.init();

  tft.fillScreen(ILI9486_BLACK);
  
  tft.setRotation(1);
  tft.setTextSize(7);
  
  tft.setCursor(0, 10);
  tft.setTextColor(ILI9486_GREEN);
  tft.printf("TAMANEGI\n\n");

  tft.setTextSize(4);
  tft.setTextColor(ILI9486_RED);
  tft.printf("3.5inch LCD\n");
  tft.setTextColor(ILI9486_YELLOW);
  tft.printf("Res=480 x 320\n");
  tft.setTextColor(ILI9486_BLUE);
  tft.printf("ILI9486\n");
}

void loop(void)
{
}

結果

表示結果は下の「LCDの表示(RP2040)」の結果で一緒に掲載します。

LCDの表示(Raspberry Pi Pico / Raspberry Pi Pico2)

説明

LCD上に色とサイズを変えながら文字列を表示します。

配線

スケッチ

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

//for ESP32-WROOM
// #define TFT_CS            (5)
// #define TFT_RST           (27)
// #define TFT_DC            (26)
// #define TFT_MOSI          (23)
// #define TFT_SCK           (18)

//for RP2040/RP2350
#define TFT_CS            (17)
#define TFT_RST           (22)
#define TFT_DC            (28)
#define TFT_MOSI          (19)
#define TFT_SCK           (18)

#define ILI9486_BLACK     (0x0000)
#define ILI9486_WHITE     (0xFFFF)
#define ILI9486_RED       (0xF800)
#define ILI9486_GREEN     (0x07E0)
#define ILI9486_BLUE      (0x001F)
#define ILI9486_CYAN      (0x07FF)
#define ILI9486_MAGENTA   (0xF81F)
#define ILI9486_YELLOW    (0xFFE0)
#define ILI9486_ORANGE    (0xFC00)

ILI9486_SPI tft(TFT_CS, TFT_DC, TFT_RST);

void setup(void)
{
//  for ESP32-WROOM 
//  SPI.begin(TFT_SCK, -1, TFT_MOSI, TFT_CS); 

// for RP2040/RP2350
  // SPI.setMOSI(TFT_MOSI);
  // SPI.setSCK(TFT_SCK);

  tft.setSpiKludge(false);
  tft.init();

  tft.fillScreen(ILI9486_BLACK);
  
  tft.setRotation(1);
  tft.setTextSize(7);
  
  tft.setCursor(0, 10);
  tft.setTextColor(ILI9486_GREEN);
  tft.printf("TAMANEGI\n\n");

  tft.setTextSize(4);
  tft.setTextColor(ILI9486_RED);
  tft.printf("3.5inch LCD\n");
  tft.setTextColor(ILI9486_YELLOW);
  tft.printf("Res=480 x 320\n");
  tft.setTextColor(ILI9486_BLUE);
  tft.printf("ILI9486\n");
}

void loop(void)
{
}

結果

画像左上が、ESP32-WROOM(Node MCU)を使った表示、右下がRaspberry Pi Picoを使ったです。
LCDライブラリはどちらのMCUにも対応しているため同じ表示ができました。

SDカードリーダ(Raspberry Pi Pico / Raspberry Pi Pico2)

説明

SDカードに保存されているJPG画像を読み出しLCDに表示する。
LCDとSDカードのSPI通信は共通の信号を使い、CSでセレクトします。

一体型のSDカードリーダを使ってJPG画像を表示する予定でしたが動作しませんでした。
不動の原因は不明です。
別のモジュールからJPG画像を読み出す配線サンプルに変更しました。

配線

代わりのSDカードリーダモジュールを使った配線

スケッチ

#include <SPI.h>
#include <ILI9486_SPI.h>
#include <Adafruit_GFX.h>
#include <SD.h>
#include <TJpg_Decoder.h>

#define TFT_CS        (17)
#define TFT_RST       (22)
#define TFT_DC        (28)
#define TFT_MOSI      (19)
#define TFT_SCK       (18)

#define SD_CS         (21)  
#define SD_MISO       (16)
#define SD_MOSI       (TFT_MOSI)
#define SD_SCK        (TFT_SCK)

#define FILENAME      "/tamanegi.jpg"

#define ILI9486_BLACK     (0x0000)
#define ILI9486_WHITE     (0xFFFF)

#define JPG_SIZE_MAX  (100 * 1024)

ILI9486_SPI tft(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.setTX(TFT_MOSI);
  SPI.setRX(SD_MISO);
  SPI.setSCK(TFT_SCK);

  tft.setSpiKludge(false);
  tft.init();

  tft.fillScreen(ILI9486_BLACK);
  tft.setRotation(1);

  Serial.begin(115200);
  delay(1000);
  
  if (!SD.begin(SD_CS, SD_SCK_MHZ(8)))
  {
    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表示できる(と思います)

タッチパネル

説明

タップした位置にドット表示し簡単なペイントソフトにします。
最大2点同時タップまでのドットを表示することができます。

配線

スケッチ

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

#include <bb_captouch.h>
#include <Wire.h>

#define TOUCH_SDA         (21)
#define TOUCH_SCL         (22)
#define TOUCH_INT         (16)
#define TOUCH_RST         (17)
#define TOUCH_WIDTH       (640)
#define TOUCH_HEIGHT      (480)

#define TFT_CS            (5)    // CS
#define TFT_RST           (27)   // Reset 
#define TFT_DC            (26)   // DC
#define TFT_MOSI          (23)   // MOSI
#define TFT_SCK           (18)   // Clock

#define ILI9486_BLACK     (0x0000)
#define ILI9486_WHITE     (0xFFFF)
#define ILI9486_RED       (0xF800)
#define ILI9486_GREEN     (0x07E0)
#define ILI9486_BLUE      (0x001F)
#define ILI9486_CYAN      (0x07FF)
#define ILI9486_MAGENTA   (0xF81F)
#define ILI9486_YELLOW    (0xFFE0)
#define ILI9486_ORANGE    (0xFC00)

ILI9486_SPI tft(TFT_CS, TFT_DC, TFT_RST);

BBCapTouch bbct;

void setup() {

  Serial.begin(115200);
  while (!Serial);

  pinMode(TOUCH_RST, OUTPUT);
  pinMode(TOUCH_INT, OUTPUT);

  digitalWrite(TOUCH_RST, LOW);
  digitalWrite(TOUCH_INT, LOW);
  
  delay(10);  
  digitalWrite(TOUCH_INT, HIGH);
  delayMicroseconds(100);
  digitalWrite(TOUCH_RST, HIGH);
  delay(5);
  digitalWrite(TOUCH_INT, LOW);
  delay(50);

  //タッチパネルの原点位置
  // bbct.setOrientation(0, 0, 0);           //右上
  // bbct.setOrientation(90, 320, 0);        //右下
  // bbct.setOrientation(180, 320, 480);     //左下
  bbct.setOrientation(270, 0, 480);       //左上
  bbct.init(TOUCH_SDA, TOUCH_SCL, TOUCH_RST, TOUCH_INT);

  SPI.begin(TFT_SCK, -1, TFT_MOSI, TFT_CS); 

  tft.setSpiKludge(false);
  tft.init();
  tft.fillScreen(ILI9486_BLACK);
  tft.setRotation(3);
}

void loop()
{
 TOUCHINFO ti;

  while(1)
  {
    if (bbct.getSamples(&ti))
    {
      for (int i = 0; i < ti.count; i ++)
      {
        tft.fillCircle(ti.x[i], ti.y[i], 2, ILI9486_WHITE);
        Serial.printf("Touch[%d] : (x, y) = (%3d, %3d) : size = %3d\r\n", (i + 1), ti.x[i], ti.y[i], ti.area[i]);
      }
      Serial.println();
    } 
  }
}

結果

静電容量式タッチパネルなので軽く触れるだけでタッチ判定されます。
感圧式に比べて軽快な入力操作ができます。
FT6236では2ポイントまでの同時サンプリングができました。

RP2040 / RP2350で使用できるようにライブラリを修正する

説明

静電容量タッチパネルドライバ(FT6236)の制御ライブラリ 「bb_captouch by Larry Bank」を修正し、RP2040搭載基板 RaspberryPi Pico / RP2350搭載基板 RaspberryPi Pico2でも使用できるようにします。

ライブラリの修正箇所を記載します。
ライブラリのバージョンは「1.2.0」をターゲットにしています。
動作確認サンプルは、当記事「タッチパネル」のサンプルソースをRP2040 / RP2350でも動作するように修正します。

サンプルプログラムは背景を青、タッチした個所を白ドットで描画するペイントアプリにしました。

修正(ライブラリ)

ライブラリは
C:\Users\xxxx\Documents\Arduino\libraries\bb_captouch\src
(xxxxはPCのログインアカウントです)
bb_captouch.cppをメモ帳などテキストエディタで編集します。

int BBCapTouch::init(…)関数(90行目)を検索します。
ESPボードのI2Cピン設定箇所にRP2040ボード用の#ifdef 文を追記します。

94行目を以下のコードに置き換えます。

<修正前>

int BBCapTouch::init(int iSDA, int iSCL, int iRST, int iINT, uint32_t u32Speed)
{
uint8_t ucTemp[4];

    Wire.begin(iSDA, iSCL); // this is specific to ESP32 MCUs
    Wire.setClock(u32Speed);
    Wire.setTimeout(100);
    _iType = CT_TYPE_UNKNOWN;

<修正後>

int BBCapTouch::init(int iSDA, int iSCL, int iRST, int iINT, uint32_t u32Speed)
{
uint8_t ucTemp[4];

#if defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_RP2350)  //Added for RP2040 or RP2350 MCUs
    Wire.setSDA(iSDA);
    Wire.setSCL(iSCL);
    Wire.begin();
#else
    Wire.begin(iSDA, iSCL); // this is specific to ESP32 MCUs
#endif

    Wire.setClock(u32Speed);
    Wire.setTimeout(100);
    _iType = CT_TYPE_UNKNOWN;

スケッチをコンパイルすると出力ウインドウに以下メッセージが表示されますが無視します。

「警告:ライブラリbb_captouchはアーキテクチャesp32に対応したものであり、アーキテクチャrp2040で動作するこのボードとは互換性がないかもしれません。」

配線

配線サンプルにRaspberry Pi Picoを使っていますが、Raspberry Pi Pico2も同じ配線です。

修正(サンプルソース)

「タッチパネル」のサンプルソースに#ifdef分を追記してESP32-WROOM (Node MCU)、またはRP2040(RaspberryPi Pico) / RP2350(RaspberryPi Pico2)のどちらでもコンパイルできる変更をしています。

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

#include <bb_captouch.h>
#include <Wire.h>

#if defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_RP2350)  //Added for RP2040 or RP2350 MCUs
  #define TOUCH_SDA       (0)
  #define TOUCH_SCL       (1)
  #define TOUCH_INT       (2)
  #define TOUCH_RST       (3)

  #define TFT_CS          (17)
  #define TFT_RST         (22)
  #define TFT_DC          (28)
  #define TFT_MOSI        (19)
  #define TFT_SCK         (18)
  
#else
  #define TOUCH_SDA       (21)
  #define TOUCH_SCL       (22)
  #define TOUCH_INT       (16)
  #define TOUCH_RST       (17)

  #define TFT_CS          (5)
  #define TFT_RST         (27)
  #define TFT_DC          (26)
  #define TFT_MOSI        (23)
  #define TFT_SCK         (18)
#endif

#define TOUCH_WIDTH       (640)
#define TOUCH_HEIGHT      (480)

#define ILI9486_BLACK     (0x0000)
#define ILI9486_WHITE     (0xFFFF)
#define ILI9486_RED       (0xF800)
#define ILI9486_GREEN     (0x07E0)
#define ILI9486_BLUE      (0x001F)
#define ILI9486_CYAN      (0x07FF)
#define ILI9486_MAGENTA   (0xF81F)
#define ILI9486_YELLOW    (0xFFE0)
#define ILI9486_ORANGE    (0xFC00)

ILI9486_SPI tft(TFT_CS, TFT_DC, TFT_RST);

BBCapTouch bbct;

void setup() {

  Serial.begin(115200);
  while (!Serial);

  pinMode(TOUCH_RST, OUTPUT);
  pinMode(TOUCH_INT, OUTPUT);

  digitalWrite(TOUCH_RST, LOW);
  digitalWrite(TOUCH_INT, LOW);
  
  delay(10);  
  digitalWrite(TOUCH_INT, HIGH);
  delayMicroseconds(100);
  digitalWrite(TOUCH_RST, HIGH);
  delay(5);
  digitalWrite(TOUCH_INT, LOW);
  delay(50);

  //タッチパネルの原点位置
  // bbct.setOrientation(0, 0, 0);           //右上
  // bbct.setOrientation(90, 320, 0);        //右下
  // bbct.setOrientation(180, 320, 480);     //左下
  bbct.setOrientation(270, 0, 480);       //左上
  bbct.init(TOUCH_SDA, TOUCH_SCL, TOUCH_RST, TOUCH_INT);

#if defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_RP2350)  //Added for RP2040 or RP2350 MCUs
  SPI.setMOSI(TFT_MOSI);
  SPI.setSCK(TFT_SCK);
  SPI.begin();
#else
  SPI.begin(TFT_SCK, -1, TFT_MOSI, TFT_CS); 
#endif

  tft.setSpiKludge(false);
  tft.init();
  tft.fillScreen(ILI9486_BLUE);
  tft.setRotation(3);
}

void loop()
{
 TOUCHINFO ti;

 while (1) {
   if (bbct.getSamples(&ti)) {
     for (int i = 0; i < ti.count; i ++){
       tft.fillCircle(ti.x[i], ti.y[i], 3, ILI9486_WHITE);
       Serial.printf("Touch[%d] : (x, y) = (%3d, %3d) : size = %3d\r\n", (i + 1), ti.x[i], ti.y[i], ti.area[i]);
     }
    Serial.println();
    } 
  }
}

結果

Raspberry Pi Pico、Raspberry Pi Pico2どもにタッチ動作ができました。


コメント

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