背景
M5StackとはLCDや電池を搭載し、プログラムを書き込める、電子工作に便利な装置です。LCDが付いているのため試作機を素早く作るのに便利なので利用する機会が多いのですが、仕様が固まってくるとM5Stackに載っている機能(電池やスピーカー)を除いて最低限の装置が欲しくなります。
ピクセル数が同じ3.2インチのLCDがあるので、それをESP32の開発キットに接続してM5Stackと同様の構成にしてみました。
しかしながら、M5Stackで利用したのと同じプログラムでは、期待しない形で情報が表示されると分かりました。(タイトル画像のように、画面の縦横比が異なり、鏡文字が表示されました。)
調査と試行錯誤を重ねてESP32 + LCDモジュールでM5Stackと同じように情報を表示するプログラムの書き方を把握したので、備忘録を兼ねて記事として共有します。
使ったもの
- M5StackやESP32にプログラムを書き込めるPC
Arduino IDEかPlatformIOをインストールしておきます。
Arduino IDEの場合はarduino-esp32をインストールしてください。 - M5Stack
比較用です。 - ESP32 devkitC
ESP32にプログラムを書き込める回路が載った開発ボードです。 - 3.2インチ 320x240 LCD
M5Stackに使われているLCDと同じILI9341というドライバが使わてているものです。
開発元のページはこちらです。
3.2inch SPI Module ILI9341 SKU:MSP3218 - ブレッドボード
ESP32開発ボードとLCDから信号線を引き出し、ジャンパワイヤで接続しやすい状態にします。 - ジャンパワイヤ
ブレッドボードに引き出さされた信号線を接続します。 - USB microBケーブル
ESP32開発ボードをPCに接続します。
配線
ESP32とLCDをこのように接続します。M5Stackの回路図ではLEDはMSFETを通して制御する回路になっていますが、LCDモジュールはその回路が組み込まれているのでLEDをGPIO32か3V3に接続します。
LCD | ESP32 |
---|---|
VCC | 3V3 |
GND | GND |
CS | GPIO14 |
RESET | GPIO33 |
DC | GPIO27 |
MOSI | GPIO23 |
SCK | GPIO18 |
LED | GPIO32 もしくは 3V3 |
MISO | 未接続 |
ブレッドボードとジャンパワイヤを利用して接続するとこうなりました。
M5Stackで動かしているコード
このコードを動かすM5Stackと同じ情報をLCDモジュールに表示するのが今回の目的です。#include <Arduino.h>
#include <M5Stack.h>
void setup() {
M5.begin();
M5.Lcd.begin();
M5.Lcd.setTextSize(4);
}
void loop() {
M5.Lcd.setCursor(0, 0);
M5.Lcd.println("Hello world");
M5.Lcd.setCursor(0, 200);
M5.Lcd.println("at " + String(millis()));
delay(100);
}
M5Stackで動かすとこうなります。
ESP32とLCDモジュールで動かすとこうなります。
画面の縦横比の不一致と鏡文字表示になる不具合が発生します。
文字だけの描画なら: TFT_eSPIで代替
今回扱うプログラムはLCDに文字だけを表示しているので、M5.Lcdを作っているM5Displayの継承元となっているTFT_eSPIを利用して、縦横比を渡しつつ初期化することで期待する動作をさせれます。#include <Arduino.h>
#include <M5Stack.h>
#define LCD_WIDTH 320
#define LCD_HEIGHT 240
TFT_eSPI lcd(LCD_WIDTH, LCD_HEIGHT);
void setup() {
M5.begin(); // Activate gpio32 for background led
lcd.begin();
lcd.fillScreen(0);
lcd.setRotation(4);
lcd.setTextSize(4);
}
void loop() {
lcd.setCursor(0, 0);
lcd.println("Hello world");
lcd.setCursor(0, 200);
lcd.println("at " + String(millis()));
delay(100);
}
期待通りに動きました。
TFT_eSPIはM5Stack内部にコードを保持して使われていますが、元のコードはライブラリとして独立しています。
https://github.com/Bodmer/TFT_eSPI
M5Stackに関係無いプロジェクトでは上記のライブラリを利用するのも良さそうです。
M5Stackで使える関数を使い続けたいなら: 互換性のあるLovyanGFXを利用
TFT_eSPIの利用で文字だけの描画は解決したのですが、M5DisplayにはJpegを描画したり(drawJpg)、webから画像を取ってきたり(drawPngUrl)、独自の機能があるため、それを利用したい場面があると思います。その場合は、M5Displayと互換性を持たせつつ開発が続いているLovyanGFXを利用するのが1つの解決案です。(drawJpgやdrawPngUrlもあります。)
https://github.com/lovyan03/LovyanGFX
LovyanGFXを利用して期待する情報を表示するコードはこちらです。
サンプルコード HowToUse/2_spi_setting を参考にしました。
今回利用するLCDのドライバであるILI9341用の設定クラスを宣言し、通信に必要なGPIOピンを割り当ててlcdを初期化することで動きました。
#include <Arduino.h>
#include <FS.h>
#include <SD.h>
#include <SPIFFS.h>
#include <HTTPClient.h>
#include <LovyanGFX.hpp>
lgfx::LGFX_SPI<lgfx::LGFX_Config> lcd;
lgfx::Panel_ILI9341 panel;
void setup() {
panel.spi_cs = 14;
panel.spi_dc = 27;
panel.gpio_rst = 33;
panel.gpio_bl = 32;
panel.pwm_ch_bl = 7;
lcd.setPanel(&panel);
lcd.init();
lcd.begin();
lcd.fillScreen(0);
lcd.setRotation(1);
lcd.setTextSize(4);
}
void loop() {
lcd.setCursor(0, 0);
lcd.println("Hello world");
lcd.setCursor(0, 200);
lcd.println("at " + String(millis()));
delay(100);
}
LovyanGFXはM5Stackに依存せず定義できるので、M5Stackに関係しないプロジェクトでM5Displayと同様の操作をしたい場合に重宝しそうです。
LovyanGFXの存在は、M5Displayの分割要求が却下されたgithubのissueへのコメントや、それに関するつぶやきへの返信で、開発者から教えていただきました。
非推奨: M5.Lcdを使い続けたいなら: ライブラリの幅と高さ情報を書き換える
どうしてもM5.Lcdの呼び出しを通してESP32とLCDモジュールの組み合わせで期待する表示をさせたい場合は、M5Stackのライブラリのコードを書き換えることで実現可能ではあります。しかしながら、Arduino IDEの場合は他のプロジェクトにも影響し、PlatormIOの場合でもプロジェクトの管理外のコードを変更することになって保守が困難になるため、推奨はしません。
LIL9341_Defines.hのTFT_WIDTHとTFT_HEIGHTを書き換えます。
Arduino IDEの場合は [Arduinoのスケッチ置き場]/libraries/M5Stack/src/utility/ILI9341_Defines.h にあります。
PlatfomIOの場合は [プロジェクトのフォルダ]/.pio/libdeps/[esp32devなどのボード名]/M5Stack/src/utility/ILI9341_Defines.h にあります。
// #define TFT_WIDTH 240
// #define TFT_HEIGHT 320
#define TFT_WIDTH 320
#define TFT_HEIGHT 240
Lcd.begin()の後にsetRotationで4を設定することで、画面の回転と鏡文字表示の修正を行なえます。
M5.Lcd.begin();
M5.Lcd.setRotation(4);
上記の変更でM5.Lcdで ESP32 + LCDモジュールに期待通りの情報を表示できる状態になります。
しかしながら、ライブラリのコードを書き換えるのは開発時以外はしないのが良いと思います。
このような変更が必要な場合はM5Stackのコードをフォークして、自身のリポジトリのコードを書き換え、それを必要なライブラリとして使うのが良いと思います。
余談: M5StackのLCDは、ライブラリはILI9341のコードがあるけれど、ハードウェアはILI9342
LovyanGFXを作成した方から情報をいただきました。ご利用ありがとうございます!
— らびやん (@lovyan03) February 14, 2021
M5Stackに搭載されてるLCDはILI9342なのにTFT_eSPIのILI9341を書き換える形で実装されてしまってるので、ILI9341と併用しようとすると妙な感じになるですよね…。
調べてみるとM5Stack Basicの説明ページにILI9342を利用していると記述がありました。
ライブラリはILI9341とILI9342の記述があり、前者の方がファイル数が多いのでてっきり9341かと思っていました。
まとめ
M5Stackで表示していた情報をESP32とLCDモジュールの組み合わせで表示するには、M5Stackのライブラリをそのまま利用するのでは不十分でしたが、下記の方法があると把握しました。- M5Stackのコードに含まれるTFT_eSPIを利用する(ライブラリとして独立しているTFT_eSPIを利用するのも良さそうです。)
- LovyanGFXを利用する
- 非推奨: M5Stackのコード(LIL9341_Defines.h)で定義されるLCDの高さと幅を書き換える
いずれかの方法を採用することで、M5Stackと同じようにLCDに情報を表示するESP32とLCDモジュールを利用した装置が作れます。
変更履歴
2021.02.15LovyyanGFXを知るきっかけとなったgithubのコメントやtwitterの返信へのリンクを追加しました。
M5StackのLCDのドライバはILI9341かと思っていましたが、ILI9342だと情報をいただいたので、その情報を追加しました。
0 件のコメント :
コメントを投稿