実現したいこと
ESP32モジュール基板にili9488というTFTモジュールを接続して、lvglライブラリを使用してタッチパネル用の画面プロジェクトを作成したいと思っています。
既に、hello worldのような簡単なプロジェクトが動作していることを確認済みで、ESP32とili9488間の配線は正常であることを確認しました。
次に、画面中央に大きめのボタンを1個配置して、正常にタッチ動作できるかをやっています。
発生している問題・分からないこと
画面中央に大きめのボタンを1個配置して、正常にタッチ動作できるかを、chat GPTに簡単なプログラムを作ってもらって、ボタンは表示できたのですが、タッチ動作の反応が全くない状態になります。
ボタンをタッチするとモニター出力されるはずの文字列
cpp
1// シンプルなボタンイベントハンドラ2static void simple_button_event_handler(lv_event_t *e) {3 lv_event_code_t code = lv_event_get_code(e);4 if(code == LV_EVENT_CLICKED) {5 Serial.println("Simple Button Pressed!");6 }7}
この文字列がボタンを押しても全く出力されません。
そうなると、simple_button_event_handlerという割り込み関数が全く動いていないような状態だと思いますし、なぜ動いていないのかが全然わかりません。
改善方法などありましたらご教示の程よろしくお願い致します。
該当のソースコード
main.cファイルの内容はこちらです。
cpp
1//main.cファイル内容2 3#include <Arduino.h>4#include <lvgl.h>5#include <TFT_eSPI.h> // ILI9488ドライバを含むライブラリ6 7void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p); // ILI9488用のflush関数8 9TFT_eSPI tft = TFT_eSPI(); // TFTインスタンスを作成10 11static lv_style_t style_pressed;12 13// ボタンイベントハンドラ14static void button_event_handler(lv_event_t *e) {15 lv_event_code_t code = lv_event_get_code(e);16 lv_obj_t *button = lv_event_get_target(e);17 if(code == LV_EVENT_CLICKED) {18 Serial.println("Button Pressed!"); // デバッグメッセージを追加19 20 // ボタンの背景色を変更するスタイルを作成21 22 lv_style_init(&style_pressed);23 lv_style_set_bg_color(&style_pressed, lv_color_make(0xFF, 0xA5, 0x00)); // オレンジ色に設定24 25 // スタイルをボタンに適用26 lv_obj_add_style(button, &style_pressed, 0);27 28 const char *btn_text = lv_label_get_text(lv_obj_get_child(button, 0));29 lv_obj_t *label = (lv_obj_t *)lv_event_get_user_data(e); // 修正:ユーザーデータを正しく取得30 lv_label_set_text(label, btn_text);31 }32}33 34// シンプルなボタンイベントハンドラ35static void simple_button_event_handler(lv_event_t *e) {36 lv_event_code_t code = lv_event_get_code(e);37 if(code == LV_EVENT_CLICKED) {38 Serial.println("Simple Button Pressed!");39 }40}41 42 43static lv_disp_draw_buf_t draw_buf;44static lv_color_t buf[320 * 10]; // 描画バッファを定義45 46 47static lv_disp_drv_t disp_drv;48 49void setup() {50 Serial.begin(115200); // シリアル通信を開始51 lv_init(); // LVGLを初期化52 tft.begin(); // TFTを初期化53 tft.setRotation(1); // 必要に応じて画面の向きを設定54 55 //uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };56 //tft.setTouch(calData);57 58 59 lv_disp_draw_buf_init(&draw_buf, buf, NULL, 320 * 10);60 61 // ディスプレイドライバを設定62 63 lv_disp_drv_init(&disp_drv);64 disp_drv.hor_res = 480;65 disp_drv.ver_res = 320;66 disp_drv.flush_cb = my_disp_flush; // ここでILI9488用のflush関数を設定67 disp_drv.draw_buf = &draw_buf;68 lv_disp_drv_register(&disp_drv);69 70 // シンプルなボタンを作成71 lv_obj_t *btn = lv_btn_create(lv_scr_act());72 lv_obj_set_size(btn, 200, 100);73 lv_obj_align(btn, LV_ALIGN_CENTER, 0, 0);74 lv_obj_add_event_cb(btn, simple_button_event_handler, LV_EVENT_ALL, NULL);75}76 77void loop() {78 lv_timer_handler(); // LVGLタイマーを処理79 delay(5);80}81 82// ILI9488用のflush関数(ディスプレイドライバの設定に必要)83void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {84 uint32_t w = (area->x2 - area->x1 + 1);85 uint32_t h = (area->y2 - area->y1 + 1);86 tft.startWrite();87 tft.setAddrWindow(area->x1, area->y1, w, h);88 tft.pushColors((uint16_t *)&color_p->full, w * h, true);89 tft.endWrite();90 lv_disp_flush_ready(disp);91}
また、TFT_eSPIライブラリのUser_Setup.hファイルの編集内容はこちらです。
cpp
1----(中略)----2 3//#define ILI9481_DRIVER4//#define ILI9486_DRIVER5#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)6//#define ST7789_DRIVER // Full configuration option, define additional parameters below for this display7//#define ST7789_2_DRIVER // Minima8 9----(中略)----10 11// The hardware SPI can be mapped to any pins12 13#define TFT_MISO 1914#define TFT_MOSI 2315#define TFT_SCLK 1816#define TFT_CS 4 // Chip select control pin17#define TFT_DC 2 // Data Command control pin18//#define TFT_RST 3 // Reset pin (could connect to RST pin)19//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST20 21// For ESP32 Dev board (only tested with GC9A01 display)22// The hardware SPI can be mapped to any pins23 24//#define TFT_MOSI 15 // In some display driver board, it might be written as "SDA" and so on.25//#define TFT_SCLK 1426//#define TFT_CS 5 // Chip select control pin27//#define TFT_DC 27 // Data Command control pin28//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)29//#define TFT_BL 22 // LED back-light30 31#define TOUCH_CS 27 // Chip select pin (T_CS) of touch screen32 33//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only34 35----(中略)----36 37//#define SPI_FREQUENCY 100000038// #define SPI_FREQUENCY 500000039// #define SPI_FREQUENCY 1000000040//#define SPI_FREQUENCY 2000000041#define SPI_FREQUENCY 2700000042// #define SPI_FREQUENCY 4000000043// #define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz)44// #define SPI_FREQUENCY 8000000045 46// Optional reduced SPI frequency for reading TFT47#define SPI_READ_FREQUENCY 2000000048 49// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:50#define SPI_TOUCH_FREQUENCY 250000051 52// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default.53
試したこと・調べたこと
上記の詳細・結果
念のため、main.cファイル内の
static void button_event_handler(lv_event_t *e)
static void simple_button_event_handler(lv_event_t *e)
2つのハンドラーがあるので、使っていないbutton_event_handlerは削除してみましたが、不具合は解消しません。
タッチ操作によるハンドラー呼び出しでは何か特別な設定などありますでしょうか?
補足
なお、TFT_eSPIライブラリのみで作成した下記の画面プログラムは、タッチ操作も正常にできていることを確認しています。
なので、ESP32基板とili9488との物理的な配線やTFT_eSPIライブラリの各種設定は問題ないのでは?と思うのですが・・・
他に確認すべきことなどありますでしょうか?
cpp
1#include <Arduino.h>2#include <WiFi.h>3#include <NTPClient.h>4#include <WiFiUdp.h>5#include <TFT_eSPI.h>6 7// Wi-Fiの設定8const char *ssid = "my_SSID"; // ここにSSIDを入力9const char *password = "my_password"; // ここにWi-Fiパスワードを入力10 11// NTPサーバの設定12WiFiUDP ntpUDP;13NTPClient timeClient(ntpUDP);14 15void drawButtons();16void drawButton(int buttonIndex, uint32_t color);17 18// TFTディスプレイの設定19TFT_eSPI tft = TFT_eSPI(); // TFT_eSPIオブジェクトの作成20 21void setup() {22 Serial.begin(115200);23 24 // Wi-Fi接続25 WiFi.begin(ssid, password);26 while (WiFi.status() != WL_CONNECTED) {27 delay(500);28 Serial.print(".");29 }30 Serial.println("WiFi Connected");31 32 // TFTディスプレイの初期化33 tft.init();34 tft.setRotation(1); // 画面の向きを調整35 36 uint16_t calData[5] = { 231, 3567, 344, 3355, 7 };37 tft.setTouch(calData);38 39 // NTPサーバに接続40 timeClient.begin();41 timeClient.setTimeOffset(3600 * 9); // 日本時間の場合、UTC+9時間42 43 // ボタンの表示(一度だけ実行)44 drawButtons();45 46}47 48void drawButtons() {49 for (int i = 0; i < 10; i++) {50 drawButton(i, TFT_BLACK); // デフォルトの色でボタンを描画51 }52}53 54 55void drawButton(int buttonIndex, uint32_t color) {56 int x = (buttonIndex % 5) * 80; // ボタンのX座標を更新57 int y = (buttonIndex / 5) * 60 + 100; // ボタンのY座標を更新58 tft.fillRect(x, y, 80, 60, color); // 新しいサイズでボタンの背景を描画59 tft.drawRect(x, y, 80, 60, TFT_WHITE); // 新しいサイズでボタンの枠を描画60 tft.setCursor(x + 30, y + 25); // テキストの位置を調整61 tft.print(buttonIndex + 1); // ボタンの番号を描画62}63 64 65// タッチされたボタンのインデックスと時間を記録する変数66int lastButtonIndex = -1;67unsigned long lastButtonTime = 0;68 69// グローバル変数として前回の時刻を記録するための変数を追加70String lastTime = "";71 72void loop() {73 timeClient.update();74 75 String currentTime = timeClient.getFormattedTime();76 if (currentTime != lastTime) {77 // 時計表示エリアのみを更新78 tft.fillRect(0, 0, 240, 80, TFT_BLACK); // 時計表示エリアをクリア79 tft.setTextColor(TFT_WHITE);80 tft.setTextSize(2);81 tft.setCursor(10, 10);82 tft.print("Time: ");83 tft.setTextSize(3);84 tft.setCursor(10, 40);85 tft.print(currentTime);86 87 lastTime = currentTime; // 現在の時刻を記録88 // シリアルモニターに時刻を出力89 Serial.println(timeClient.getFormattedTime());90 }91 92 // タッチ座標の変数を宣言93 uint16_t t_x, t_y;94 95 // タッチ入力の検出96 if (tft.getTouch(&t_x, &t_y)) {97 int buttonIndex = (t_x / 80) + (t_y - 100) / 60 * 5; // 幅80ピクセル、高さ60ピクセルに基づく計算98 if (buttonIndex >= 0 && buttonIndex < 10) {99 drawButton(buttonIndex, TFT_RED);100 lastButtonIndex = buttonIndex;101 }102 } else {103 // タッチが終了した場合、ボタンの色を戻す104 if (lastButtonIndex != -1) {105 drawButton(lastButtonIndex, TFT_BLACK);106 lastButtonIndex = -1;107 }108 }109 110 delay(10);111 112}113

0 コメント