M5Stack の液晶ディスプレイ ILI9341 をちょっと解明してみた

M5stack,ライブラリに頼らずに、TFT,LCD,ILI9341,をちょっと解明 M5Stack

スケッチの入力

では、先で説明した、M5Stack のレジスタ直叩き関数を使って、自分で再編した以下のスケッチを Arduino IDE に入力してみてください。

2019年7月以降生産のM5Stackは、LCDパネルがILI9342C というIPSタイプに変更されています。
その場合、色が反転しますので、Invert(色反転)0x21コマンドを送信必要があります。
スケッチも修正して、146行目の反転コマンドをコメントアウトしてあるので、コメントを解除してコンパイルしてみてください。
新型M5StackのIPSディスプレイや、色反転については以下の記事を参照してください。
M5Stack FIRE (PSRAM付き)およびIPSタイプのLCD ILI9342Cを使ってみた
(2020/01/09)

 

【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)

/*
 * This sample sketch is LCD ILI9341 display test of M5Stack.
 * 
 * The MIT License (MIT)
 * Copyright (c) 2018 Mgo-tec. All rights reserved.
 * 
 * Modify Display.cpp of M5Stack library.
 * M5Stack library - MIT License
 * Copyright (c) 2017 M5Stack
 * 
 * https://opensource.org/licenses/mit-license.php
 */
#include <SPI.h>
#include "soc/spi_reg.h"

#define SPI_NUM 0x3 //VSPI=0x3, HSPI=0x2

const int sck = 18; // SPI clock pin
const int miso = -1; // MISO(master input slave output) don't using
const int mosi = 23; // MOSI(master output slave input) pin
const int cs_pin = 14; // Chip Select pin
const int dc_pin = 27; // Data/Command pin
const int rst_pin = 33; // Reset pin
const uint8_t lcd_led_pin = 32;

//***********セットアップ****************************
void setup() {
  Serial.begin(115200);
  ILI9341_Init();
  Display_Clear(0, 0, 319, 239);
  Brightness(255); //LCD LED Full brightness
  delay(2000);
}
//***********メインループ****************************
void loop() {
  int i, j;
  //red (0-31), green (0-63), blue (0-31)
  uint8_t red_max = 31, green_max = 63, blue_max = 31;
  Draw_Pixel_65k_3Color(0, 0, red_max, green_max, blue_max);
  Draw_Pixel_65k_3Color(319, 0, red_max, green_max, blue_max);
  Draw_Pixel_65k_3Color(0, 239, red_max, green_max, blue_max);
  Draw_Pixel_65k_3Color(319, 239, red_max, green_max, blue_max);
  delay(2000);

  Draw_Horizontal_Line(0, 319, 0, red_max, green_max, blue_max);
  Draw_Horizontal_Line(0, 319, 239, red_max, green_max, blue_max);
  Draw_Vertical_Line(0, 0, 239, red_max, green_max, blue_max);
  Draw_Vertical_Line(319, 0, 239, red_max, green_max, blue_max);
  delay(2000);

  Draw_Line(0, 0, 319, 239, red_max, 0, 0);
  Draw_Line(319, 0, 0, 239, 0, green_max, 0);
  Draw_Line(160, 0, 160, 239, 0, 0, blue_max);
  Draw_Line(0, 120, 319, 120, red_max, green_max, 0);
  delay(2000);

  for(i = 0; i < 120; i = i + 5){
    Draw_Rectangle_Line(40+i, i, 279-i, 239-i, red_max, green_max, blue_max);
  }
  delay(2000);

  uint8_t Width = 50;
  Draw_Rectangle_Fill(0, 0, 319, 239, 0, 0, blue_max);
  Draw_Rectangle_Fill(10, 10, 10+Width, 10+Width, red_max, 0, 0);
  Draw_Rectangle_Fill(309-Width, 10, 309, 10+Width, 0, green_max, 0);
  Draw_Rectangle_Fill(10, 229-Width, 10+Width, 229, red_max, green_max, 0);
  Draw_Rectangle_Fill(309-Width, 229-Width, 309, 229, 0, green_max, blue_max);
  delay(2000);

  Display_Clear(0, 0, 319, 239);
  Draw_Rectangle_Line(40, 0, 279, 239, 0, 0, blue_max);
  Draw_Line(40, 0, 279, 239, 0, 0, blue_max);
  Draw_Line(40, 239, 279, 0, 0, 0, blue_max);
  Draw_Circle_Line(159, 119, 119, red_max, green_max, blue_max);
  Draw_Circle_Line(25, 25, 25, red_max, 0, 0);
  Draw_Circle_Line(294, 25, 25, 0, green_max, 0);
  Draw_Circle_Line(25, 214, 25, red_max, green_max, 0);
  Draw_Circle_Line(294, 214, 25, red_max, 0, blue_max);
  for(i = 0; i < 120; i = i + 5){
    Draw_Circle_Line(159, 119, 119 - i, red_max, green_max, blue_max);
  }
  delay(2000);

  Display_Clear(0, 0, 319, 239);
  Draw_Rectangle_Fill(0, 0, 319, 239, 0, 0, 20);
  Draw_Circle_Fill(159, 119, 119, red_max, 0, blue_max);
  Draw_Circle_Fill(25, 25, 25, red_max, 0, 0);
  Draw_Circle_Fill(294, 25, 25, 0, green_max, 0);
  Draw_Circle_Fill(25, 214, 25, red_max, green_max, 0);
  Draw_Circle_Fill(294, 214, 25, 0, green_max, blue_max);
  Draw_Circle_Fill(159, 119, 51, 0, 0, blue_max);
  delay(2000);

  Display_Clear(0, 0, 319, 239);
  for(i = 0; i < 240; i = i + 10){
    Draw_Line(0, i, i, 239, 10, green_max, 20);
    Draw_Line(80 + i, 0, 319, i, 0, green_max, 31);
  }
  delay(2000);

  Display_Clear(0, 0, 319, 239);
  j = 31;
  for(i = 0; i < 32; i++){
    Draw_Rectangle_Fill(i*10, 0, i*10+9, 59, i, 0, 0);
    Draw_Rectangle_Fill(i*10, 60, i*10+9, 119, 0, i*2, 0);
    Draw_Rectangle_Fill(i*10, 120, i*10+9, 179, 0, 0, i);
    Draw_Rectangle_Fill(i*10, 180, i*10+9, 239, j, j*2, j);
    j--;
  }
  delay(10000);
  Display_Clear(0, 0, 319, 239);
}
//****** LCD ILI9341 ディスプレイ初期化 ***********
void ILI9341_Init(){
  Brightness(0);

  pinMode(rst_pin, OUTPUT); //Set RESET pin
  pinMode(dc_pin, OUTPUT); //Set Data/Command pin

  SPI.begin(sck, miso, mosi, cs_pin); //VSPI setting

  SPI.setBitOrder(MSBFIRST);
  //ILI9341 のSPI Clock Cycle Time (Write) Minimun 100ns=10MHz
  //※Arduino core ESP32 v1.0.4では10MHz以上にすると正常に表示されないので注意
  SPI.setFrequency(10000000);
  SPI.setDataMode(SPI_MODE0);
  SPI.setHwCs(true); //Set Hardware CS pin

  //Hardware Reset------------
  digitalWrite(rst_pin, HIGH);
  delay(5);
  digitalWrite(rst_pin, LOW);
  delay(10);
  digitalWrite(rst_pin, HIGH);
  delay(121);

  digitalWrite(dc_pin, HIGH);

  CommandWrite(0x38); //Idle mode OFF
  CommandWrite(0x3A); //COLMOD: Pixel Format Set
    DataWrite(0b01010101); //RGB 16 bits / pixel, MCU 16 bits / pixel
  CommandWrite(0x36); //MADCTL: Memory Access Control
    DataWrite(0b00001000); //D3: BGR(RGB-BGR Order control bit )="1"
  CommandWrite(0x11); //Sleep OUT
  delay(10);
  //CommandWrite(0x21); //ILI9342C M5Stack LCD Inversion.
  CommandWrite(0x29); //Display ON

  Display_Clear(0, 0, 319, 239);
  Brightness(100);
}
//********* 4wire SPI Data / Command write************
void CommandWrite(uint8_t b){
  digitalWrite(dc_pin, LOW);
  SPI.write(b);
  digitalWrite(dc_pin, HIGH);
}

void DataWrite(uint8_t b){
  SPI.write(b);
}

void DataWrite16(uint16_t b){
  SPI.write16(b);
}

void DataWrite32(uint32_t b){
  SPI.write32(b);
}
//******** Set Column and Page Address ( X Y range setting )***********
void XY_Range(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1){
  uint32_t X = (uint32_t)x0<<16 | x1;
  uint32_t Y = (uint32_t)y0<<16 | y1;

  CommandWrite( 0x2A ); //Set Column Address
    DataWrite32(X);
  CommandWrite( 0x2B ); //Set Page Address
    DataWrite32(Y);
}
//********* Display All Black Clear ******************************
void Display_Clear(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1){
  uint16_t Width_x = x1 - x0 + 1;
  uint16_t Width_y = y1 - y0 + 1;
  uint32_t Total = Width_x * Width_y ;

  Block_SPI_Fast_Write(x0, y0, x1, y1, 0, 0, 0, Total);
}
//********* Display Color Pixel Block Fast Write *****************
void spiWriteBlock(uint16_t color, uint32_t repeat) {
  uint16_t color16 = (color >> 8) | (color << 8);
  uint32_t color32 = color16 | color16 << 16;

  if (repeat > 15) {
    SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_NUM), SPI_USR_MOSI_DBITLEN, 255,
                      SPI_USR_MOSI_DBITLEN_S);

    while (repeat > 15) {
      while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM)) & SPI_USR)
        ;
      for (uint32_t i = 0; i < 16; i++)
        WRITE_PERI_REG((SPI_W0_REG(SPI_NUM) + (i << 2)), color32);
      SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR);
      repeat -= 16;
    }
    while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM)) & SPI_USR)
      ;
  }

  if (repeat) {
    repeat = (repeat << 4) - 1;
    SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_NUM), SPI_USR_MOSI_DBITLEN, repeat,
                      SPI_USR_MOSI_DBITLEN_S);
    for (uint32_t i = 0; i < 16; i++)
      WRITE_PERI_REG((SPI_W0_REG(SPI_NUM) + (i << 2)), color32);
    SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR);
    while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM)) & SPI_USR)
      ;
  }
}
//*********** LCD ILE9341 Block Pixel SPI Fast Write *****************
void Block_SPI_Fast_Write(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint8_t red, uint8_t green, uint8_t blue, uint32_t repeat){
  uint16_t ColorDot = (red << 11) | (green << 5) | blue;
  XY_Range(x0, y0, x1, y1);
  CommandWrite( 0x2C ); //LCD RAM write
  spiWriteBlock(ColorDot, repeat);
}
//*********** 65k Color Pixel (Dot) Write ****************************
void Draw_Pixel_65k_DotColor(uint16_t x0, uint16_t y0, uint16_t DotColor){
  SPI.setFrequency(10000000);
  XY_Range(x0, y0, x0, y0);
  CommandWrite( 0x2C ); //RAM write
  DataWrite16( DotColor );
}
//*********** 65k Pixel RGB color Write ****************************
void Draw_Pixel_65k_3Color(uint16_t x0, uint16_t y0, uint8_t red, uint8_t green, uint8_t blue){
  SPI.setFrequency(10000000);
  XY_Range(x0, y0, x0, y0);

  uint16_t Dot = ((uint16_t)red << 11) | ((uint16_t)green << 5) | (uint16_t)blue;
  CommandWrite( 0x2C ); //RAM write
  DataWrite16( Dot );
}
//***************************************
void Draw_Rectangle_Line(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint8_t red, uint8_t green, uint8_t blue){
  Draw_Horizontal_Line(x0, x1, y0, red, green, blue);
  Draw_Horizontal_Line(x0, x1, y1, red, green, blue);
  Draw_Vertical_Line(x0, y0, y1, red, green, blue);
  Draw_Vertical_Line(x1, y0, y1, red, green, blue);
}
//***************************************
void Draw_Horizontal_Line(int16_t x0, int16_t x1, int16_t y0, uint8_t red, uint8_t green, uint8_t blue){
  if(x0 > 319) x0 = 319;
  if(x1 > 319) x1 = 319;
  if(y0 > 239) y0 = 239;
  if(x1 < x0){
    uint16_t dummy = x1;
    x1 = x0;
    x0 = dummy;
  }

  uint32_t Width_x = x1 - x0 + 1;
  Block_SPI_Fast_Write(x0, y0, x1, y0, red, green, blue, Width_x);
}
//***************************************
void Draw_Vertical_Line(int16_t x0, int16_t y0, int16_t y1, uint8_t red, uint8_t green, uint8_t blue){
  if(x0 > 319) x0 = 319;
  if(y0 > 239) y0 = 239;
  if(y1 > 239) y1 = 239;
  if(y1 < y0){
    uint16_t dummy = y1;
    y1 = y0;
    y0 = dummy;
  }

  uint16_t Width_y = y1 - y0 + 1;
  Block_SPI_Fast_Write(x0, y0, x0, y1, red, green, blue, Width_y);
}
//***************************************
void Draw_Line(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint8_t red, uint8_t green, uint8_t blue){
  if(x0 > 319) x0 = 319;
  if(x1 > 319) x1 = 319;
  if(y0 > 239) y0 = 239;
  if(y1 > 239) y1 = 239;
  if(x0 == x1 && y0 == y1) return;

  int i;

  int16_t Y = 0, X = 0;
  int16_t length_x = x1 - x0;
  int16_t length_y = y1 - y0;

  uint16_t Dot = (red << 11) | (green << 5) | blue;

  if(abs(length_x) > abs(length_y)){
    float degY = ((float)length_y) / ((float)length_x);
    if(x0 < x1){
      for(i = x0; i < (x1 + 1); i++){
        Y = y0 + round((i-x0) * degY);
        Draw_Pixel_65k_DotColor(i, Y, Dot);
      }
    }else{
      for(i = x0; i >= x1; i--){
        Y = y0 + round((i-x0) * degY);
        Draw_Pixel_65k_DotColor(i, Y, Dot);
      }
    }
  }else{
    float degX = ((float)length_x) / ((float)length_y);
  
    if(y0 < y1){
      for(i = y0; i < (y1 + 1); i++){
        X = x0 + round((i-y0) * degX);
        Draw_Pixel_65k_DotColor(X, i, Dot);
      }
    }else{
      for(i = y0; i >= y1; i--){
        X = x0 + round((i-y0) * degX);
        Draw_Pixel_65k_DotColor(X, i, Dot);
      }
    }
  }
}
//***************************************
void Draw_Rectangle_Fill(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint8_t red, uint8_t green, uint8_t blue){
  uint16_t Width_x = x1 - x0 + 1;
  uint16_t Width_y = y1 - y0 + 1;
  uint32_t Total = Width_x * Width_y ;
  Block_SPI_Fast_Write(x0, y0, x1, y1, red, green, blue, Total);
}
//***************************************
void Draw_Circle_Line(uint16_t x0, uint16_t y0, uint16_t r, uint8_t red, uint8_t green, uint8_t blue){
  uint16_t x1, y1;
  float i;
  float deg = 1.0;
  if( r > 50 ) deg = 0.5;
  if( r > 110) deg = 0.25;

  uint16_t Dot = ((uint16_t)red << 11) | ((uint16_t)green << 5) | (uint16_t)blue;

  for(i = 0; i < 360; i = i + deg){
    x1 = round( (float)(x0 + (r * cos(radians(i)))) );
    y1 = round( (float)(y0 + (r * sin(radians(i)))) );
    Draw_Pixel_65k_DotColor(x1, y1, Dot);
  }
}
//***************************************
void Draw_Circle_Fill(uint16_t x0, uint16_t y0, uint16_t r, uint8_t red, uint8_t green, uint8_t blue){
  //red (0-31), green (0-63), blue (0-31)
  uint16_t x1, y1;
  float i;
  float deg = 1.0;
  //半径が大きくなると、角度の刻み方を細かくしないと、完全に塗りつぶせないので注意。
  if( r > 50 ) deg = 0.5;
  if( r > 110) deg = 0.25;

  for( i = 0; i < 360; i = i + deg ){
    x1 = round( (float)(x0 + (r * cos(radians(i)))) );
    y1 = round( (float)(y0 + (r * sin(radians(i)))) );
    Draw_Vertical_Line(x1, y0, y1, red, green, blue);
  }
}
//********* LCD Display LED Brightness **************
void Brightness(uint8_t brightness){
  uint8_t ledc_ch = 0;
  uint32_t valueMax = 255;
  uint32_t duty = (8191 / valueMax) * brightness;
  ledcSetup(ledc_ch, 5000, 13);
  ledcAttachPin(lcd_led_pin, ledc_ch);
  ledcWrite(ledc_ch, duty);
}

【解説】

M5Stack ライブラリは使わず、SPI直叩き関数だけ流用します。
M5Stack ライブラリは MIT なので、改変、再配布OKですが、その部分のライセンス表記と著作者表記しました。
その他はほぼ自作です。

また、このスケッチは、micro SD カードと併用できるようにプログラミングされていませんので注意してください。

●14行目:
Arduino core for ESP32 に同梱されている SPI レジスタ群ライブラリをインクルードします。

●16行目:
SPI レジスタ関数で使用する、SPI番号を指定します。
ここでは、VSPI 接続なので、0x3 とします。

●18-24行:
M5Stack の ESP32 の GPIO アサインです。
MISO 端子は接続されていないので、-1 にしています。

●29行:
ここで、ILI9341 を初期化しています。
これについては後述します。

●30行:
ディスプレイを黒色、つまり全てのビットをゼロで埋めます。

●31行:
TFT LCD のLED バックライトをフル点灯させます。

●114-151行:
ILI9341 を初期化する関数です。
120行目で SPI 通信のピンを設定しますが、Arduino – ESP32 標準の SPI ライブラリを使う場合、クラス名を大文字の SPI. と指定すると、自動的に VSPI モードとなります。
125行目でSPIクロック周波数を27 MHz にしていますが、実は、ILI9341 のデータシートを見てみると、SPI クロック1周期の最少タイムが 100ns と書いてありました。
とすると、最大は 10 MHz 設定のはずです。
しかし、M5Stack の Display.cpp ライブラリでは、27 MHz で駆動していました
これ、自分で実験してみると分かるのですが、27 MHz でも問題無く動作して、しかも高速です
これはこれでヨシとします。
そして、重要なのが、127行目でVSPI ハードウェアCSピンを有効にしています。
これをやらないと、いちいち CS ピンを digitalWrite で HIGH-LOW を切り替えなければいけないので、速度が遅くなってしまいます。

130-135行では、データシートに沿ったハードウェアリセットをしています。
所々delay を置いていて、これより短いとリセットがキャンセルされてしまうので注意です。
また、ソフトウェアリセットもありましたが、ハードウェアリセットで賄えるので、ソフトウェアリセットは不要です。

137行目で DC ピンを HIGH にしておくことが重要です。
コマンド送信の時だけ LOW にするので、その他は常に HIGH にしておきます。

139-147行が、私が実験した中で、最小限の初期化コマンドです。
M5Stack ライブラリの Display.cpp より、遙かにシンプルになっています。
140-141行では、65kカラーモードのビット転送にしています。
142-143行では、赤色ビット先行で読み取っていきます。
これを設定しないと、赤色と青色がテレコになってしまいます。
2019年7月以降生産に新型M5StackのLCDパネルはILI9342CというIPSタイプになりました。
その場合、146行目のコメントを外して、Invert(色反転)コマンドを実行してください。

●153-169行:
コマンドやデータを送信する場合、CSピンはハードウェアCS送信を有効にしているので、CSピンの設定は不要です。
ただ、DCピンについては、コマンド送信だけ LOW にすればよく、後は殆どデータ送信なので、HIGH にしていればデータ送信できます。

●171-179行:
Pixel の描画範囲を決める関数です。
四角形範囲だけでなく、直線範囲も決定できます。

●181-187行:
画面を消去する関数ですが、画面一杯の四角形範囲をゼロ値のビットで埋めています。

●189-219行:
先ほど説明した、M5Stack ライブラリ中のDisplay.cpp にある、SPIレジスタ直叩き関数をそのまま流用しました。
これは、高速で四角形範囲を単色で塗りつぶします。

●221-226行:
四角形範囲を単色で高速描画する関数です。
224行のコマンド 0x2C がデータ送信用コマンドです。
多量のデータでもこのコマンドを最初に1回置くだけで、その後は全てデータと判断してくれます。
ですから、広い範囲を単色で埋め尽くすのは単純で速いです。

●228-242行:
1 pixel を描画するための関数です。
これを使って斜線や円を描きます。

●251-277行:
垂直線や水平線を描くための関数です。
これもごく細い四角形としてSPIレジスタ直叩き高速描画しています。
これで、枠だけの四角形や、円の中を塗りつぶしているのがミソです。

●279-322行:
斜線を描く関数です。
これは高速描画できないので、1 pixel づつ描画しています。

●331-345行:
円の枠線を描く関数です。
これも高速描画できないので、1 pixel づつ描画しています。

●347-361行:
円を塗りつぶす関数です。
これは高速描画可能なので、垂直線を利用して描画しています。

●363-370行:
TFT LCD ディスプレイのバックライト LED を制御する関数です。
PWM で制御して、明るさを調整している感じです。
これは、Arduino – ESP32 のサンプルスケッチをちょっと改変して流用しています。

コンパイル書き込み実行

では、M5Stack とパソコンを USB で接続して、Arduino IDE でコンパイル書き込み実行してみてください。
ツールメニューのボードマネージャでは、ESP32 Dev Module でOKです。

因みに、これをコンパイル書き込みすると、初期動作プログラムは消去されます。

最初に紹介している動画のように表示されればOKです。

ただ、液晶ディスプレイの欠点として、斜めから見ると色相がガラッと変わってしまいますね。
斜めから見たい場合は OLED の方が圧倒的に鮮やかですね。

まとめ

どうでしょうか?

M5Stack の標準ライブラリを使った方が遙かにいろいろなことができますが、今回の実験は、私自身が M5Stack のディスプレイをライブラリに頼らずに自由に描画させたいことが目的だったのです。
近いうちに日本語フォントを表示させてみたいと思っているので、そのためには自分自身でライブラリを作成しなければ達成できないというわけでやってみました。

長い間遠ざけていましたが、今実際にILI9341 を動かしてみると、その高性能さに驚かされました。
こんな安価なデバイスがこれほど高機能であれば、やっぱり多くの電子工作家が使うだろうなと思いました。
動画表示機能もあり、これは使わない手がありません。

ということで、今後もこのデバイスを使い倒してみようと思います。

ではまた・・・。

コメント

  1. マッキー より:

    お久しぶりです。
    私も昨年末M5を入手しテストしてます。
    2月のコメントでILI9341をと書いたのはこのためでした。
    情報が少なく困ってました。
    wifi接続、SSL通信非常に参考のなりました。
    M5はアリエクスプレスで入手しましたが、アマゾンあたりは欠品してるみたいです。
    余談ですが、ESP32の試作ケースは3Dプリンターで作ってます。
    FreeCADっていうソフトですがなかなか良いです。無料ですし、オープンソースでパイソンで動いてます。
    画像が添付できればお見せしたいところです。

    今後ともご活躍ください。

    • mgo-tec mgo-tec より:

      マッキーさん

      ご無沙汰しております。
      再度ブログにお越しいただき、そしてコメントいただき、ありがとうございます。

      そうだったんですね。
      M5stackを既に試されていたんですね。
      今はネットではESP32開発ボードよりも情報が多いくらいになっていて、M5stckを動かすには苦労しなくなっていますね。
      しばらくこのブームは続きそうです。

      3Dプリンターでケース作っているとはスゴイですね。
      私はしばらく使っておらず、使い方を忘れてしまいました。
      いつか挑戦してみようとは思っています。
      今後、M5stack用のライブラリを作ったりしていこうと思っています。

      マッキーさんも今後いろいろオモシロイ物を作って、ご活躍なさってください。

  2. マッキー より:

    ありがとうございます。
    ILI9341で通常の動作はさせましたが、前回お願いしたのは、漢字表示をさせたいためSSD1331のような漢字表示ライブラリーが欲しかったのです。
    中華製の漢字ROM、GT20L16J1Yを使って表示しましたがいまいちでした。
    余談ですが、M5stackでオシロスコープもすんなり動きました。
    無理ばっかり言ってすみません。(._.)

    • mgo-tec mgo-tec より:

      私自身も漢字表示ライブラリーが欲しいと思っています。
      今、取組中作業があるので、それが終わってから作成しようと思っています。
      もうちょっと時間がかかりますので、しばらくお待ちください。

  3. あいむ より:

    こんにちは。

    私も前々から気になっていたM5Stackをようやく購入できたので、色々なサンプルを動かしてどんなものか確認しています。今日は、このページのスケッチを動かしてみました。問題なく動作していましたが、まだ、ソースコードは全く見ていませんので、後でじっくり読んでみようと思っています。

    私はiPhoneのプログラマーなので、iPhoneとESP32をBLEで通信させた物を作っています。M5Stackがあると開発がスムーズに進められるようなので、うまくいったらESP32のプリント基板を自作してみようと思っています。

    私もM5Stackで、日本語表示してみたいです。

    では、では。

    • mgo-tec mgo-tec より:

      あいむさん

      記事をご覧いただき、サンプルスケッチを試していただき、ありがとうございます。

      iPhone と BLE通信はイイですね!
      私はまだ BLE は試していません。
      Wi-Fiすら把握し切れていない状態です。

      確かに、M5stack を使うと開発がスムースになりそうですよね。
      何かオモシロイものができるとイイですね。

  4. あいむ より:

    アマゾンで購入しておいた1,186円のILI9341のLCDディスプレーモジュール基板が今日到着したので、このページのTFT LCD ILI9341 と ESP32の配線を参考に配線して、このスケッチを動作を確認したので報告します。

    M5Stackと同じように表示しました。が、XとYが逆になっていて、一部が表示されませんでした。たぶん日本語のスケッチも動くと思います。

    これから作る予定のESP32のプリント基板は、このILI9341のLCDが使えることが分かったので、表示装置はこれを使おうと思います。まだ、ライブラリーのソースコード見ていませんが、あとで修正できるか検討してみようと思います。

    • mgo-tec mgo-tec より:

      あいむさん

      ご報告ありがとうございます。
      私も、2~3日前、Amazon で購入した サインスマート販売の 2.2 インチ ILI9341 は動作確認しました。
      ライブラリの
      ESP32_LCD_ILI9341_SPI.cpp
      91行目をコメントアウトして、92行目のコメントを解除すると XY 正しく表示されました。

      ただ、Hiletgo の 2.4インチのものはピン配列が謎で断念しました。

  5. あいむ より:

    もう修正してあったのですね。

    教えていただいたESP32_LCD_ILI9341_SPI.cppを修正したらXYが正しく表示されました。ただ、Yahooニュースをスクロールするスケッチを動かして見たのですが、今度はスクロールする文字列が横に長くて2文字くらいしか表示しなかったです。

    同じILI9341のLCDでも色々とありそうですね。
    今度は、1,490円のILI9341の2.8インチのタッチパネル付きを購入したので、届いたらこちらも動作確認してみます。

    • mgo-tec mgo-tec より:

      あ、そうなんですね。
      サインスマートの ILI9341 は問題無く表示されましたけどね。

      ILI9341_Init関数は最小限の初期化コマンドしか使っていないので、やっぱり M5stack 標準ライブラリにあるように、ズラーッと初期化コマンドを使った方が正常に動作されるかも知れません。
      まだ使いこなせていないコマンドが多いです。

      今後、気付いたところは改良していきたいと思っています。

  6. kazu より:

    こんばんは
    Atom Liteに書き込みをしてみました。ILI9341の接続をどうしたらいいのかわかりません。
    といっても元々無理なことをしているのかもしれません。

    • mgo-tec mgo-tec より:

      kazuさん

      記事をご覧いただきありがとうございます。
      残念ながら、私はAtom Liteを持ち合わせていませんので、動くかどうか私には分かりません。

      ところで、M5StackやESP32でディスプレイを高速表示させるライブラリを作っているらびやんさんという方がおられます。私が尊敬するお方です。
      その方は超プロフェッショナルなので、恐らく、Atom LiteとILI9341に関しては熟知していると思います。
      TwitterかGitHubで質問してみるという手もあるかもです。

      というわけで、お役に立てず、すみません。

  7. haiga より:

    mgo-tecさま

    いつも有用な記事を拝見させて頂き、当方のCMに関連するツールに様々に使用させて頂いております。ありがとうございます。

    さて、最近、Amazon等でILI9341ドライバー仕様で320×480解像度の3.5インチLCDが売られておりますが、240×320のLCDをこれに変更できれば、エリアが2倍に広がります。

    mgo-tecさまのLCDドライバーの何処を変更すれば、このLCDに対応できるか((319,239)と記述している部分?)が知りたいと思い書込みした次第です。

    /haiga

    • mgo-tec mgo-tec より:

      haigaさん

      記事をご覧いただき、ありがとうございます。

      ILI9341の倍画面ですか~…。
      実機で確かめてみないと何とも言えませんが、今の私には実験する時間がまったく無く、最近はしばらくESP32もM5Stackも触っていないので、あまりお役に立てないかも知れません。
      この記事のソースコードならば、319, 239 のところを書き換えれば、もしかしたら動くかもしれませんが、何とも言えません。

      また、この記事は古く、未熟なプログラムで、他の私の自作ライブラリのドライバーも素人コードで動作が遅いです。

      お勧めなのは、「らびやん」さんのESP32, M5Stack用LCDドライバーが遙かに高速で、様々なLCDに対応していて、今やM5Stackの標準ライブラリになっています。
      LovyanGFXというものです。
      Arduino IDEからでもライブラリマネージャでインストールできると思います。
      使い方は私には解りませんが、ネットでもかなり情報が出ているので、是非試してみて下さい。
      おそらく、倍角のILI9341ドライバーにも対応していると思います。

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