Arduino環境でLCDモジュールを使う(ILI9486)

コンピュータ、組み込み

Arduino環境で扱える最大クラスのILI9486 4.0inch を紹介します。
RP2040 Raspberry Pi picoとESP32-S3でのSPI接続とグラフィック表示、JPG画像表示、タッチパネルを使ってみます。

今回紹介するもの

LCDモジュール (ILI9486) 4.0inch

特徴

Arduino環境で使用できる液晶カラーモニタとしては大型の4.0inch サイズです。
画面描画命令をSPIを使って高速な表示をします。

感圧式タッチパネルとSDカードスロットがついていて、電源とGNDは共通です。
CS以外のSPI通信線は共通の配線で使用することができます。

製品情報
サイズ4.0inch
LCDドライバILI9486
解像度(X, Y)480, 320
通信方式SPI
動作電圧3.3~5V
タッチパネルドライバXPT2046 (HR2046と互換)
タッチパネル分解能4K x 4K
その他SDカードリーダ
外観

前面

背面

使用感

ILI9341 LCDと並べてみると倍以上のサイズです。
ピン配置も同じなので、ILIのLCDシリーズに慣れていれば作業はしやすいと思います。

画像左がILI9486 4.0inch,
右上がST7735 1.8inch,
右下がILI9341 2.4inch

感圧タッチパネルの分解能は縦横比が違いますが4K x 4Kです。
ILI9341と同じで±30程度のばらつきがあるので平均化処理などの工夫が必要です。

解像度も大きくなり、視野も広いのでゲーム画面にしても見やすいと思います。
タッチパネルを利用した操作盤として使用するときに複数のボタンを配置しても、窮屈さはだいぶん軽減されます。

小型サイズLCD ST7735はこちらで紹介しています。

中型サイズLCD ILI9341はこちらで紹介しています。

準備

ライブラリ

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

ライブラリ名用途検索確認時バージョン
Adafruit GFX Library by AdafruitグラフィックGFX1.11.3
ILI9486_SPI by Jean-Marc ZinggグラフィックILI94861.0.5
XPT2046_Touchscreen by Paul StoffregenタッチパネルXPT20461.4
TJpg_Decoder by Bodmerjpg表示jpg1.0.8

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

使い方(LCD表示)

RP2040系 Raspberry Pi Pico(SPI0)でLCD表示

説明

サンプルとして文字列を表示します。

サンプルはテキストの表示のみです。
各マイコンでのSPIの設定方法について記述します。
そのほかの描画サンプルについては
スケッチ例 > ILI9486 > graphictest を参照してください。

RP2040系のSPIの設定方法についての参考にしてください。

配線

LCDのMISOは配線なしで動作します。

Raspberry Pi pico配線ILI9486
3.3VVCC
3.3VLED
GNDGND
GPIO1(SPI0 CS)CS
GPIO22Reset
GPIO28D/C
GPIO3(SPI0 TX)SDI(MOSI)
GPIO2(SPI0 SCK)SCK
[2023/3/18] 誤記修正 ResetとD/Cのピン番号の修正
スケッチ
/**********************************************************************
【ライセンスについて】
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 GFX Library
Adafruit ILI9486

【準備】
Raspberry Pi Pico     <-> ILI9486
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/14 : 新規
**********************************************************************/
#include <SPI.h>
#include <ILI9486_SPI.h>
#include <Adafruit_GFX.h>

//TFT SPIピン設定
#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)
{
  //SPIピン設定
  SPI.setTX(TFT_MOSI);
  SPI.setSCK(TFT_SCK);

  //TFTの初期化と初期設定
  tft.setSpiKludge(false);              // false to disable rpi_spi16_mode
  tft.init();                           //Init ILI9486初期化  
  tft.fillScreen(ILI9486_BLACK);        //背景の塗りつぶし

  //テキスト表示
  tft.setRotation(3);                         //画面回転
  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("4.0inch 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の表示ができました。

ESP32系 BananaPi picoW(VSPI)でLCD表示

説明

サンプルとして文字列を表示します。

サンプルはテキストの表示のみです。
各マイコンでのSPIの設定方法について記述します。
そのほかの描画サンプルについては
スケッチ例 > ILI9486 > graphictest を参照してください。

ESP32系のSPIの設定方法についての参考にしてください。
マイコン基板にはBananaPi picoW ESP32-S3を使用しています。

配線

LCDのMISOは配線なしで動作します。

Banana Pi picoW配線ILI9486
3.3VVCC
3.3VLED
GNDGND
GPIO2CS
GPIO7Reset
GPIO10D/C
GPIO4SDI(MOSI)
GPIO3SCK

Banana Pi picoWはRaspberry Pi picoと同サイズ基板で、電源、GNDは同じ位置にあります。
Raspberry Pi picoと同じピン位置になるよう配置しています。

スケッチ
/**********************************************************************
【ライセンスについて】
Copyright(c) 2022 by tamanegi
Released under the MIT license
'http://tamanegi.digick.jp/about-licence/

【マイコン基板】
Banana Pi PicoW

【スケッチの説明】
LCDのテスト表示を行います。

【ライブラリ】
esp32 > ESP32S3 Dev Module

Adafruit GFX Library
Adafruit ILI9486

【準備】
Raspberry Pi Pico     <-> ILI9486
3.3V                  <-> VCC
GND                   <-> GND
GPIO2                 <-> TFT CS
GPIO7                 <-> TFT Reset
GPIO10                <-> TFT AO(D/C)
GPIO4                 <-> TFT SDA
GPIO3                 <-> TFT SCK
3.3V                  <-> LED

【バージョン情報】
2023/2/27 : 新規
**********************************************************************/
#include <SPI.h>
#include <ILI9486_SPI.h>
#include <Adafruit_GFX.h>

#define TFT_CS    2
#define TFT_RST   7
#define TFT_DC    10
#define TFT_MOSI  4
#define TFT_SCK   3

#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ピン設定
  SPI.begin(TFT_SCK, -1, TFT_MOSI, TFT_CS); 

  //TFTの初期化と初期設定
  tft.setSpiKludge(false);              // false to disable rpi_spi16_mode
  tft.init();

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

  //テキスト表示
  tft.setRotation(3);                         //画面回転
  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("4.0inch 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の表示ができました。

タッチパネル

説明

タッチパネルのタッチ状態と、タッチ座標を読み出して表示します。

使用したILI9486のタッチドライバはXPT2046が実装されていました。
ILI9341ではHR2046が実装されていて互換があります。

配線

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

Raspberry Pi pico配線ILI9486
3.3VVCC
3.3VLED
GNDGND
GPIO1(SPI0 CS)CS
GPIO28Reset
GPIO27D/C
GPIO3(SPI0 TX)SDI(MOSI)
GPIO2(SPI0 SCK)SCK
GPIO9T_CS
GPIO0(SPI0 MISO)T_OUT(MISO)
GPIO2(SPI0 SCK)T_CLK
GPIO3(SPI0 MOSI)T_DIN(MOSI)

配線図ではTFT MISO 接続していますがなくても動作します。
[2023/6/2] MISO配線必要です。

スケッチ
/**********************************************************************
【ライセンスについて】
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 GFX Library
Adafruit ILI9486
XPT2046_Touchscreen

【準備】
<<LCD側>>
Raspberry Pi Pico     <-> ILI9486
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

<<Touch側>>
GPIO20                <-> T_CS
GPIO16(SPI0 MISO)     <-> T_OUT(MISO)
GPIO18(SPI0 SCK)      <-> T_CLK
GPIO19(SPI0 MOSI)     <-> T_DIN(MOSI)

【バージョン情報】
2023/2/14 : 新規
**********************************************************************/

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

//TFT SPIピン設定
#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

#define COMMON_SCK  18
#define COMMON_MOSI 19
#define COMMON_MISO 16

#define TOUCH_CS 20

XPT2046_Touchscreen ts(TOUCH_CS);
ILI9486_SPI tft(TFT_CS, TFT_DC, TFT_RST);

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

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

  //TFTの初期化と初期設定
  tft.setSpiKludge(false);              // false to disable rpi_spi16_mode
  tft.init();                           //Init ILI9486初期化  
  tft.fillScreen(ILI9486_BLACK);        //背景の塗りつぶし
  tft.setRotation(3);
  tft.setTextSize(2);
  tft.fillScreen(ILI9486_BLACK);

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

}

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

  //タッチがあればタッチされている座標の表示
  if (bTouch == true)
  {
   TS_Point tPoint = ts.getPoint();
    tft.setTextColor(ILI9486_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(ILI9486_RED);
    tft.setCursor(0, 0);
    tft.print("No Touch");
    
  }
  delay(200);
}
結果

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

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

説明

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

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

配線

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

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

Raspberry Pi pico配線ILI9486配線TFカードリーダ
3.3VVCCVCC
GNDGNDGND
GPIO17(SPI0 CS)TFT CS
GPIO22TFT Reset
GPIO28TFT AO(D/C)
GPIO19(SPI0 MOSI)TFT SDAMOSI
GPIO18(SPI0 SCK)TFT SCKSCK
3.3VLED
GPIO21SD CS
GPIO16(SPI0 MISO)MISO
GPIO20CS

スケッチ

/**********************************************************************
【ライセンスについて】
Copyright(c) 2022 by tamanegi
Released under the MIT license
'http://tamanegi.digick.jp/about-licence/

【マイコン基板】
Raspberry Pi Pico

【スケッチの説明】
SDカードモジュールからtest.jpgを読み出しILI9486に表示します。

【ライブラリ】
Raspberry Pi Pico/RP2040 > Raspberry Pi Pico

Adafruit GFX Library
Adafruit ILI9486
TJpg_Decoder

【準備】
SDカードのルートフォルダに "test.jpg"を保存します。
jpgファイルのサイズは 480 x 320 サイズで保存します。

SPI0のMOSIとSCKは共通で使用します。
ILI9486に実装されているSDカードリーダ以外のモジュールを使用する場合、電源とGNDを配線します。

<<TFT側>>
Raspberry Pi Pico     <-> ILI9486
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カードリーダ側>>
Raspberry Pi Pico     <-> TFカードリーダ
3.3V                  <-> VCC
GND                   <-> GND
GPIO21                <-> SD CS
GPIO19(SPI0 MOSI)     <-> SD MOSI
GPIO16(SPI0 MISO)     <-> SD MISO
GPIO18(SPI0 SCK)      <-> SD SCK

【バージョン情報】
2023/2/14 : 新規
**********************************************************************/

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

#include <TJpg_Decoder.h>
#include <ILI9486_SPI.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"

#define BLACK   0x0000      //パレット 黒
#define WHITE   0xFFFF      //パレット 白

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

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ピン設定
  SPI.setTX(COMMON_MOSI);
  SPI.setRX(SD_MISO);
  SPI.setSCK(COMMON_SCK);

  //TFTの初期化と初期設定
  tft.setSpiKludge(false);      // false to disable rpi_spi16_mode
  tft.init();                   //Init ILI9486初期化  
  tft.fillScreen(BLACK);        //背景の塗りつぶし
  tft.setRotation(3);

  Serial.begin(115200);
  //while(!Serial);
  delay(1000);
  
  //SDカードリーダの初期化とファイルの読み取り
  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ファイルの表示をしました。
こちらではSDカードのファイルリストの作成 を紹介しています。
組み合わせて使用することでフォトフレームなどを作ることができます。

Raspberry Pi Pico関連リンク

コメント

  1. たまねぎさん 初めまして、
    aruduino環境でLCDモジュールを使う(ILI9486)を拝見してコメント欄を拝借してメールしいます。

    さて、今弊社ではILI9486を表示ツールにしてESP32を使った制御盤を開発しようと思い表示テストを試みています。たまねぎさんのこのブログを参考にESP32系LCD制御スケッチを動かしてみましたがコンパイルはうまく行きますが何も表示されないような状態です。ピンアサインは変更しています。

    ご多忙とは思いますが、もしよろしかったら何かアドバイス又はご指導を頂けないでしょうか?
    有償でも結構ですのでよろしくお願いします。

    #define TFT_CS 2 → 5
    #define TFT_RST 7 → 4
    #define TFT_DC 10 → 17
    #define TFT_MOSI 4 → 23
    #define TFT_SCK 3 → 18

    • tamanegi より:

      こんにちは。
      指定されたピン設定を使用し、当方では動作しましたのでピンの選択に間違いはありません。
      使用した基板はESP32-WROOM NODE-MCUで試しています。
      過去の経験を列挙します。
      ・LCD自体の個別不良で表示されなかったことがある。>他のLCDモジュールで試してみる。
      ・ESP32の起動電圧不足。>電源供給がUSBハブの場合ACアダプタ付きのものを使う。
      ・ピンの差し間違い、または端子の接触不良。>よく確認する。
      他にもESP32のボードライブラリバージョンによっては動作しないことがあるので、バージョンの変更をしてみてはいかがでしょうか?
      今回使用したバージョン情報は以下です。
      ・ILI9486_SPI by Jean-Marc Zingg : 1.0.5
      ・Adafruit GFX Library by Adafruit : 1.11.9
      ・esp32 by Espressif Systems : 2.0.17

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