東京メトロ02系の運転席の横にあるモニタ装置液晶ディスプレイを作ってみましょう。
使用した液晶ディスプレイは3.5インチの解像度320x480、SPI接続のものを選択しました。
タッチパネル機能がありますが、今回は使用していません。
画面イメージ
最初に画面イメージを作成します。
ポンチ絵でも構いませんが作る事をお勧めします。
(扉の開閉の文字は、本来開いたら 開 が正しいと思いますが閉としています)
構成
今回は、メインマイコンとしてESP32を使用します。
液晶ディスプレイを動かすライブラリには TFT_eSPI を使用します。
配線
3.5インチTFT液晶ディスプレイの仕様は以下のようです。
今回使用する3.5インチ液晶ディスプレイに搭載しているディスプレイドライバILI948xはタッチパネルを使用する際にMISOを接続しないようにしてください。
映像が映らなくなります。
ピンは以下につなげています。
- MOSI23
- MISO 19
- SCLK 18
- CS 5
- DC 17
- RST なし
ライブラリの導入
Arduinoに TFT_eSPI のライブラリを追加します。
スケッチ⇒ライブラリをインクルード⇒ライブラリを管理⇒TFT_eSPI をインストールします。
User_Setup.h のピン設定を変更します。
//#define ILI9486_DRIVER
//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high)
//#define TFT_MISO 19
//#define TFT_MOSI 23
//#define TFT_SCLK 18
//#define TFT_CS 15 // Chip select control pin
//#define TFT_DC 2 // Data Command control pin
//#define TFT_RST 4 // Reset pin (could connect to RST pin)
//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
を以下に変更しました。
ピン設定は各自の環境に合わせてください。
リセットピンは使用しないので -1 とします。
#define ILI9486_DRIVER
//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high)
#define TFT_MISO 19
#define TFT_MOSI 23
#define TFT_SCLK 18
#define TFT_CS 5 // Chip select control pin
#define TFT_DC 17 // Data Command control pin
//#define TFT_RST 4 // Reset pin (could connect to RST pin)
#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
動作確認
最初に、キチンと動くか確認をするためにサンプルプログラムを動かしてみましょう。
プログラム
サンプルプログラムが動いたら画面イメージを元に画面を作って行きましょう。
線や丸、四角を開始位置、終了位置、色を設定します。
線:tft.drawLine(x, y, width, hight, Color);
四角(塗りつぶし無し):tft.drawRect(x, y, width, hight, Color);
四角(塗りつぶしあり): tft.fillRect(x, y, width, hight, Color);
日本語フォントファイルの準備
この段階で、例えば以下を画面出力すると日本語の文字が文字化けします。
tft.loadFont("使用フォント名");
tft.setTextColor(Color);
tft.drawString("表示内容", x, y);
ここからは Watako さんの M5Stackで好きなフォントを使う を参考にフォントファイルを作ります。
最初に Processing をダウンロードします。
ファイル⇒スケッチ例⇒TFT_eSPI⇒Tools⇒Create_Smooth_Font⇒Create_font を開き
プログラムを丸ごと Processing に貼り付け実行します。
実行後パソコンに搭載しているフォントが表示されます。
Unicodeの準備
今回のプログラムではUnicodeの番号を指定する必要があります。
使用する日本語を羅列し、変換します。
static final int[] specificUnicodes = {
以下へ貼り付けます。
この際に
\u4eca\u65e5
となっているものは
0x4eca
0x65e5
と書き換えます。
int fontNumber = 258; // << Use [Number] in brackets from the fonts listed.
int fontSize = 28;
static final int[] specificUnicodes = {
以上を必要なフォントごとに実行すると下記のようなフォントファイルが出来上がっていると思います。
フォントファイルのアップロード
上記で作成したフォントファイルを Arduinoプログラムフォルダ 内に dataフォルダ を作成しにコピーします。
次に Arduino ESP32 filesystem uploader をダウンロードします。
ダウンロードした ESP32FS.java を Userフォルダ⇒Arduino⇒Toolsフォルダ にコピーします。
ESP32 Sketch Data Upload が表示されていると思います。
ESP32 Sketch Data Upload をクリックしファイルをアップロードします。
以上でフォントファイルがアップロードされました。
なお、フォントの色を以下で指定しています。
tft.setTextColor(文字色,背景色);
最後に、プログラムをコンパイルして実行し、動作確認をしましょう。
/*
Sketch to demonstrate using the print class with smooth fonts
Sketch is writtent for a 240 x 320 display
Load the font file into SPIFFS first by using the Arduino IDE
Sketch Data Upload menu option. Font files must be stored in the
sketch data folder (Ctrl+k to view).
https://github.com/esp8266/arduino-esp8266fs-plugin
https://github.com/me-no-dev/arduino-esp32fs-plugin
New font files in the .vlw format can be created using the Processing
sketch in the library Tools folder. The Processing sketch can convert
TrueType fonts in *.ttf or *.otf files.
Note: SPIFFS does not accept an underscore _ in filenames!
The library supports 16 bit unicode characters:
https://en.wikipedia.org/wiki/Unicode_font
The characters supported are in the in the Basic Multilingal Plane:
https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane
Make sure all the display driver and pin connenctions are correct by
editing the User_Setup.h file in the TFT_eSPI library folder.
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
#########################################################################
*/
// Font file is stored in SPIFFS
#define FS_NO_GLOBALS
#include <FS.h>
// Graphics and font library
#include <TFT_eSPI.h>
#include <SPI.h>
TFT_eSPI tft = TFT_eSPI(); // Invoke library
// -------------------------------------------------------------------------
// Setup
// -------------------------------------------------------------------------
void setup(void) {
Serial.begin(115200); // Used for messages
tft.init();
tft.setRotation(1);
if (!SPIFFS.begin()) {
Serial.println("SPIFFS initialisation failed!");
while (1) yield(); // Stay here twiddling thumbs waiting
}
Serial.println("\r\nInitialisation done.");
listFiles(); // Lists the files so you can see what is in the SPIFFS
}
// -------------------------------------------------------------------------
// Main loop
// -------------------------------------------------------------------------
void loop() {
int xpos = 0;
int ypos = 50;
// Wrap test at right and bottom of screen
tft.setTextWrap(true, true);
// Name of font file (library adds leading / and .vlw)
String fileName = "msgothic-28";
// Font and background colour, background colour is used for anti-alias blending
tft.setTextColor(TFT_WHITE, TFT_BLACK);
// Load the font
tft.loadFont(fileName);
// Display all characters of the font
tft.showFont(2000);
// Set "cursor" at top left corner of display (0,0)
// (cursor will move to next line automatically during printing with 'tft.println'
// or stay on the line is there is room for the text with tft.print)
tft.setCursor(0, 0);
tft.drawRect(0, 0, 375, 95, TFT_WHITE);
tft.drawLine(0, 35, 375, 35, TFT_WHITE);
tft.drawLine(0, 65, 375, 65, TFT_WHITE);
tft.drawRect(0, 95, 480, 280, TFT_WHITE);
tft.loadFont("msgothic-36");
tft.fillRect(375, 0, 480, 95, TFT_YELLOW);
tft.setTextColor(TFT_BLACK, TFT_YELLOW);
tft.drawString("状態", 390, 30);
tft.fillRect(20, 195, 95, 70, TFT_DARKGREEN);
tft.fillRect(115, 195, 350, 70, TFT_WHITE);
tft.fillRect(0, 275, 480, 45, TFT_WHITE);
tft.fillRect(0, 280, 105, 35, TFT_CYAN);
tft.fillRect(125, 280, 105, 35, TFT_CYAN);
tft.fillRect(250, 280, 105, 35, TFT_CYAN);
tft.fillRect(375, 280, 105, 35, TFT_CYAN);
tft.loadFont("msgothic-28");
// Set the font colour to be white with a black background, set text size multiplier to 1
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.drawString("運行 : 21 行先 : 荻窪", 10, 7);
tft.drawString("地点 : 池袋", 10, 37);
tft.drawString("終端戸締 : 1 側", 10, 67);
tft.drawString("車内 : ", 10, 100);
tft.drawString(" 1 2 3 4 5 6", 135, 165);
tft.drawString(" 1側扉 ", 25, 200);
tft.drawString(" 2側扉 ", 25, 235);
tft.setTextColor(TFT_WHITE, TFT_RED);
tft.drawString(" 閉 閉 閉 閉 閉 閉 ", 120, 200);
tft.setTextColor(TFT_BLACK, TFT_WHITE);
tft.drawString(" 閉 閉 閉 閉 閉 閉 ", 120, 235);
delay(10000);
}
// -------------------------------------------------------------------------
// List files in ESP8266 or ESP32 SPIFFS memory
// -------------------------------------------------------------------------
void listFiles(void) {
Serial.println();
Serial.println("SPIFFS files found:");
#ifdef ESP32
listDir(SPIFFS, "/", true);
#else
fs::Dir dir = SPIFFS.openDir("/"); // Root directory
String line = "=====================================";
Serial.println(line);
Serial.println(" File name Size");
Serial.println(line);
while (dir.next()) {
String fileName = dir.fileName();
Serial.print(fileName);
int spaces = 25 - fileName.length(); // Tabulate nicely
if (spaces < 0) spaces = 1;
while (spaces--) Serial.print(" ");
fs::File f = dir.openFile("r");
Serial.print(f.size()); Serial.println(" bytes");
yield();
}
Serial.println(line);
#endif
Serial.println();
delay(1000);
}
#ifdef ESP32
void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
Serial.printf("Listing directory: %s\n", dirname);
fs::File root = fs.open(dirname);
if (!root) {
Serial.println("Failed to open directory");
return;
}
if (!root.isDirectory()) {
Serial.println("Not a directory");
return;
}
fs::File file = root.openNextFile();
while (file) {
if (file.isDirectory()) {
Serial.print("DIR : ");
String fileName = file.name();
Serial.print(fileName);
if (levels) {
listDir(fs, file.name(), levels - 1);
}
} else {
String fileName = file.name();
Serial.print(" " + fileName);
int spaces = 32 - fileName.length(); // Tabulate nicely
if (spaces < 1) spaces = 1;
while (spaces--) Serial.print(" ");
String fileSize = (String) file.size();
spaces = 8 - fileSize.length(); // Tabulate nicely
if (spaces < 1) spaces = 1;
while (spaces--) Serial.print(" ");
Serial.println(fileSize + " bytes");
}
file = root.openNextFile();
}
}
#endif
// -------------------------------------------------------------------------
画面が表示されない・再起動する
フォントファイルをキチンとアップロードできていないと液晶が表示されないだけでなくESP32がリブートを繰り返します。
調整
文字や線などの配置を確認しながら進めていきます。
特に文字が抜けていて文字化けすることなどあるので注意しましょう。
BVE連携する
以上で、液晶画面にモニタ装置の情報が表示できたと思います。
それでは最後に、BVEと連携させてみましょう。