(1). 準備

LCDを使ったアプリは、LCDが高い事とドライバーが書けない事から諦めていました。最近比較的大きなLCDが手頃な価格になって来ました。後はドライバーは無いかなと探していたらこのライブラリーを見つけました。

ESP32を使って ILI9341,2.8 “, 240×320 LCD で動かして見たのですがやりたかった事が殆ど出来ました。とても感動したので今回からライブラリーにあるデモプラグラムを実行しながら各関数の使い方を説明して行きたいと思います。

まずはハードの準備

ILI9341,2.8 “, 240×320 LCD と同じハードを使います。

  • LCD: ILI9341,2.8 “, 240×320
    • 解像度 240x320 
    • カラー 16ビット
    • タッチセンサー付き
    • SDカードのソケット付き
  • CPU: ESP32
    • 30ピンタイプの普通?のESP32です。
    • PSRAM無し

SDカードがあれば画像、日本語フォントの表示等が可能になるのでVSPIをLCDに、HSPIをSDに割り当ててSDカードを使用可能にしています。

ピン配置は以下の通り。

ピン番号LCDESP32
VCCVCC
GNDGND
CSGPIO22
RESETEN
DC GPIO21 
MOSIGPIO23
SCKGPIO18
LEDGPIO05
MISOGPIO19
10T_CLKGPIO18
11T_CSGPIO17
12T_DINGPIO23
13T_DOGPIO19
14T_IRQGPIO16
S1SD_CSGPIO04
S2SD_MOSIGPIO33
S3SD_MISOGPIO25
S4SD_SCKGPIO26

ソフトの準備

説明はArduino IDE 1.8.19で行います。先ずTFT_eSPIのライブラリーを追加して下さい。ILI9341,2.8 “, 240×320 LCDで説明していますが、ライブラリー追加後User_Setup.hの編集も忘れず行って下さい。最後に簡単な例(上記のリンクではKey-Pad)が動く事を確認して下さい。

説明の前に

LCDの表示関係の説明なのでLCDの画面コピーが出来ないかライブラリーを見ていると

void readRectRGB(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data);

という関数を見つけました。指定した画面のエリアを1ドット3バイト(RGB)のビットマップ形式でバッファー(縦x横x3バイト必要)に読み込む関数です。この関数を使って画面のコピーを取る void get_img(int s_mode, char* f_name) を書いて見ました。

get_img.ino

#include "FS.h"
#include <SD.h>

#define sd_sck    26
#define sd_mosi   33
#define sd_ss      4
#define sd_miso   25

SPIClass sd_spi(HSPI);

void get_img(int s_mode, char* f_name){
  File fp;
  int a, b, c, d, w, h, filesize;
  unsigned char *img, *i_buf;
  unsigned char bmpfileheader[14] = {'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0};
  unsigned char bmpinfoheader[40] = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0};

  // Initialise the SD
  sd_spi.begin(sd_sck, sd_miso, sd_mosi, sd_ss);
  if(!SD.begin(sd_ss, sd_spi)) Serial.println("Fail");

  w = 240;
  h = 320;
  if(s_mode & 1)
  {
    w = 320;
    h = 240;
  }

  filesize = 54 + 3 *w * h; 
  for(a = 0; a < 4; a ++){
    bmpfileheader[2 + a] = (unsigned char)(filesize >> (a * 8));
    bmpinfoheader[4 + a] = (unsigned char)(w >> (a * 8));
    bmpinfoheader[8 + a] = (unsigned char)(h >> (a * 8));
  }  

  img = (unsigned char *)malloc(3 * w);
  i_buf = (unsigned char *)malloc(3 * w);

  fp = SD.open(f_name,"wb");
  fp.write(bmpfileheader,14);
  fp.write(bmpinfoheader,40);

  for(a = 0; a < h; a ++){
    d = 0;
    if(s_mode > 1) tft.readRectRGB(0, a, w, 1, img);
    else tft.readRectRGB(0, (h - 1 - a), w, 1, img);
      
    for(b = 3 * w - 1; b > 0; b -= 3){
      for(c = 0; c < 3; c ++){ 
       if(s_mode < 2) i_buf[d + 2 - c] = img[d + c];
       else i_buf[d + c] = img[b - c];
      }    
      d += 3;
    }
    fp.write(i_buf, w * 3);
  }
  fp.close();
  
  free(img);
  free(i_buf);
  
  Serial.println("OK");
  while(1) ;
}
  • 引数:      int s_mode: 画面のモード char* f_name: 保存するファイルネーム
  • 4から7行:   使用するピンの定義
  • 9行:      使用するSPIをHSPIで宣言
  • 19行:     SDカードの初期化
  • 22から28行: 画面には4つモード(縦、横、縦逆、横逆)がありモードに合わせて縦横を調整
  • 30から35行: ビットマップファイルヘッダーの書き込み
  • 37,38行:  画面全てを保存するサイズのバッファーは確保出来ないので横方向1列分のバッファー
             を2つ確保。         
  • 44から57行: 横方向最上段から最下段まで1列単位で取り込みSDカードに保存しています。
             先ず対象の列をバッファーimgに読み込み、その後データ画面のモードに合わ
             せて並び替えi_bufに保存。i_bufをSDカードに書き込んでいます。
  • 63行:     終了合図

次回はスケッチの例に有る、”Free_Font_Demo”に付いての説明を予定しています。下記は”Free_Font_Demo”の一部を実際の写真と上記の関すを使って取った画面コピーを並べて表示したものです。

写真の方は光の加減か色合いが違いますが、現物での比較は両者殆ど同じに見えます。