先に「迷路作成」を投稿しましたが、その後 800x480 ディスプレイ パラレル接続での作品を教えていただきました。ありがとうございます。
今回は、ILI9488 480x320 ディスプレイモジュールのタッチ機能を利用したお絵かきソフトを作ってみたので投稿します。
点や線、三角形、楕円(塗りつぶしも)、四角形(塗りつぶしも)までの描画機能を盛り込みました。工夫したポイントは
1.タッチ感度や精度を手懐けられるか
2.3点めまでのタッチ入力を可能にするために loop() を上手に中断させられるか
3.タッチパネルとしての座標と描画の座標が合わず変換が必要
なのですが、うまくできたりできなかったり。次のように loop() を中断させています。
pressed = false;
while (!pressed) {
t_x = 0;
t_y = 0;
pressed = tft.getTouch(&t_x, &t_y);
delay(1);
}
付属のペンでタッチしますがパネルサイズも小さいですし、タクトスイッチでのチャタリングみたいなのが発生し、loop()が意図しない形で進んでしまうようです。タッチが強すぎるとLoopが進みますし、弱すぎると認識しないし。軽やかなステップを踏むように(笑)タッチ!
第3点めについては、
tft.setRotation(1)
のとき最も簡単になります。
TFT_eSPIの設定は先に投稿した「迷路作成」を見て頂くことにして、ここでは新たなタッチ機能部の結線について示します。
ESP32(V_SPI) | ILI9488(display) | ILI9488(touch panel) |
---|---|---|
MOSI 23 | SDI(MOSI) | T_DIN |
MISO 19 | T_DO | |
SCK 18 | SCK | T_CLK |
CS 5 | CS | |
4 | T_CS | |
27 | DC/RS | |
32 | RESET | |
3V3 | LED | |
3V3 | VCC | |
GND | GND |
以下に Arduino IDE 2.1.0 で確認したコードを示します。
#include <TFT_eSPI.h> // Hardware-specific library
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
char KindLabel[8][12] = { "Clear.Scr", "Free Dot",
"Draw Line", "D.Triangl",
"D.Ellipse", "F.Ellipse",
"D.Rectang", "F_Rectang" };
uint8_t Shape[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
uint16_t Color[8] = { TFT_BLACK, TFT_MAGENTA, TFT_RED, TFT_YELLOW,
TFT_GREEN, TFT_BLUE, TFT_CYAN, TFT_WHITE };
void setup() {
Serial.begin(115200);
tft.init(); // DisplayとTouchは同じVSPIを使用
// T_DOのみMISOと接続。SDIはMISOと接続しない。
tft.setRotation(1);
InitScreen();
}
void InitScreen() {
// Clear the screen
tft.fillScreen(TFT_WHITE);
for (int x = 0; x < 8; x++) {
if (x % 2 == 1) {
tft.fillRect(60 * x, 0, 60, 25, TFT_DARKGREY);
tft.setTextColor(TFT_WHITE);
} else {
tft.fillRect(60 * x, 0, 60, 25, 0xF777); // Light Grey
tft.setTextColor(TFT_BLACK);
}
tft.drawRect(60 * x, 0, 60, 25, TFT_WHITE);
tft.drawString(KindLabel[x], 60 * x + 2, 4, 2);
tft.fillRect(60 * x, 25, 60, 25, Color[x]);
}
tft.setTextColor(TFT_WHITE);
tft.drawString("Black", 12, 29, 2);
tft.drawRect(420, 25, 60, 25, TFT_BLACK);
tft.setTextColor(TFT_BLACK);
tft.drawString("White", 432, 29, 2);
}
int pCol;
int shapeK;
uint16_t t_x; // To store the touch coordinates
uint16_t t_y;
bool pressed;
uint16_t x2;
uint16_t y2;
bool pressed2;
uint16_t x3;
uint16_t y3;
bool pressed3;
void loop(void) {
// Pressed will be set true as there is a valid touch on the screen
pressed = false;
while (!pressed) {
t_x = 0;
t_y = 0; // 後から y1 に変更しようとしたらエラーになったのでこのまま
pressed = tft.getTouch(&t_x, &t_y);
delay(1);
}
delay(10);
Serial.printf("First Point\r\n");
if (t_y >= 319 - 25) { // shape choose & clear screen
shapeK = t_x / 60; // shape kind
if (shapeK == 0) InitScreen();
}
if (t_y < 319 - 25 && t_y >= 319 - 25 * 2) { // color choose
pCol = Color[t_x / 60];
}
if (t_y < 319 - 25 * 2 - 5) {
if (shapeK == 1) {
tft.fillEllipse(t_x, 319 - t_y, 3, 3, pCol);
} else {
tft.fillEllipse(t_x, 319 - t_y, 2, 2, pCol);
x2 = 0;
y2 = 319;
pressed2 = false;
while (!pressed2 && y2 > 319 - 25 * 2 - 5) {
pressed2 = tft.getTouch(&x2, &y2);
delay(1);
}
delay(10);
Serial.printf(" Second Point\r\n");
if (y2 < 319 - 25 * 2 - 5) {
switch (shapeK) {
case 2:
tft.drawLine(t_x, 319 - t_y, x2, 319 - y2, pCol);
break;
case 3:
x3 = 0;
y3 = 319;
pressed3 = false;
while (!pressed3 && y3 > 319 - 25 * 2 - 5) {
pressed3 = tft.getTouch(&x3, &y3);
delay(1);
}
delay(10);
Serial.printf(" Third Point\r\n");
tft.drawTriangle(t_x, 319 - t_y, x2, 319 - y2, x3, 319 - y3, pCol);
break;
case 4:
tft.drawEllipse(t_x, 319 - t_y, abs(x2 - t_x), abs(y2 - t_y), pCol);
break;
case 5:
tft.fillEllipse(t_x, 319 - t_y, abs(x2 - t_x), abs(y2 - t_y), pCol);
break;
case 6:
tft.drawRect(min(t_x, x2), min(319 - t_y, 319 - y2), abs(x2 - t_x), abs(y2 - t_y), pCol);
break;
case 7:
tft.fillRect(min(t_x, x2), min(319 - t_y, 319 - y2), abs(x2 - t_x), abs(y2 - t_y), pCol);
break;
default:
break;
}
}
}
}
}
何かお気づきの点がございましたらお教えください。