Hi Everyone,
I’m trying to use an external button using LVGL and ESP32. There is no specific project I only would like to test this feature for learning purposes.
I’m using Arduino IDE 2.0 and LVGL library v8. For display, I’m using 240x240 GMT130-V1 and TFT_eSPI to drive it.
So far, I’m able to create and display a simple screen containing one LED, one Button and one label. The display works just fine.
The next step is to use an external push button - the “BOOT” button on the ESP32 Doit-Dev Kit - as an external button to simulate the press of the on-screen button.
I’ve followed the steps in LVGL academy - which was for LVGL v7 - as well as the code present in “lv_port_indev.c” and the steps mentioned in LVGL documentation. However, the external button state doesn’t change. I’m suspecting that the call-back function is not being called periodically.
I tried reading the state of the push button from the “loop” function and try to change the LED state based on that. And this worked just fine. However, when using the callback function and the procedure mentioned in the documentation\examples, it never worked.
Your suggestions\Input is highly appreciated.
My Arduino code:
//Included libraries
#include <TFT_eSPI.h>
#include <lvgl.h>
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int button_pin = 0; // The button used as an external button - "BOOT" button on ESP32 dev kit
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//For LVGL
static const uint16_t screenWidth = 240;
static const uint16_t screenHeight = 240;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[ screenWidth * 10 ];
TFT_eSPI tft = TFT_eSPI(screenWidth, screenHeight); // Invoke custom library
/* Display flushing */ //Not sure if required, need testing
void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p )
{
uint32_t w = ( area->x2 - area->x1 + 1 );
uint32_t h = ( area->y2 - area->y1 + 1 );
tft.startWrite();
tft.setAddrWindow( area->x1, area->y1, w, h );
tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );
tft.endWrite();
lv_disp_flush_ready( disp );
}
//++++++++++++++++++++++++++++++++++++++++++++++//
// LVGL global variables for testing
//++++++++++++++++++++++++++++++++++++++++++++++//
lv_obj_t * btn1;
lv_obj_t * led1;
lv_indev_t * indev_button_1;
/*Initialize your buttons*/
static void button_init_1(void)
{
pinMode(button_pin, INPUT);
}
/*Will be called by the library to read the button*/
static void button_read_1(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
//Test Code:-
int8_t btn_act = button_get_pressed_id_1();
if(btn_act >= 0) // If any button is pressed
{
data->state = LV_INDEV_STATE_PR;
lv_led_on(led1);
lv_label_set_text(labelCounter, "Something Pressed !!!"); //For debugging
}
else
{
data->state = LV_INDEV_STATE_REL;
lv_led_off(led1);
lv_label_set_text(labelCounter, "Nothing Pressed");//For debugging
}
//Original Code Commented for easier testing:-
/*
static uint8_t last_btn = 0;
//Get the pressed button's ID
int8_t btn_act = button_get_pressed_id_1();
if(btn_act >= 0) {
data->state = LV_INDEV_STATE_PR;
last_btn = btn_act;
}
else {
data->state = LV_INDEV_STATE_REL;
}
//Save the last pressed button's ID
data->btn_id = last_btn;
*/
}
/*Get ID (0, 1, 2 ..) of the pressed button*/
static int8_t button_get_pressed_id_1(void)
{
uint8_t i;
/*Check the buttons see which is being pressed (i = number of buttons)*/
for(i = 0; i < 1; i++) {
/*Return the pressed button's ID*/
if(button_is_pressed_1(i)) {
return i;
}
}
/*No button pressed*/
return -1;
}
/*Test if `id` button is pressed or not*/
static bool button_is_pressed_1(uint8_t id)
{
if(id >= 0)
{
lv_led_on(led1);
//char * pressedID;
//pressedID = char(id) + " is Pressed";
lv_label_set_text(labelCounter, "Something Pressed !!!"); //For debugging
}
else if(id == -1)
{
lv_led_off(led1);
lv_label_set_text(labelCounter, "Nothing Pressed");//For debugging
}
return false;
}
//----------------------------------------------------------------------------------------//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
void setup(void) {
//LVGL code:-
lv_init();
tft.begin(); /* TFT init */
tft.setRotation( 3 ); /* Landscape orientation, flipped */
lv_disp_draw_buf_init( &draw_buf, buf, NULL, screenWidth * 10 );
/*Initialize the display*/
static lv_disp_drv_t disp_drv;
lv_disp_drv_init( &disp_drv );
/*Change the following line to your display resolution*/
disp_drv.hor_res = screenWidth;
disp_drv.ver_res = screenHeight;
disp_drv.flush_cb = my_disp_flush;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register( &disp_drv );
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
btn1 = lv_btn_create(lv_scr_act());
led1 = lv_led_create(lv_scr_act());
labelCounter = lv_label_create(lv_scr_act());
lv_obj_align(labelCounter, LV_ALIGN_CENTER, 0, 90);
lv_label_set_text(labelCounter, counterChar);
lv_obj_add_event_cb(btn1, btn_event_handler, LV_EVENT_ALL, NULL);
lv_obj_align(btn1, LV_ALIGN_CENTER, 0, -30);
lv_obj_set_size(btn1, 180, 60);
lv_obj_t * label;
label = lv_label_create(btn1);
lv_label_set_text(label, "Button");
lv_obj_center(label);
//Create one LED to test the external button input
lv_obj_align(led1, LV_ALIGN_CENTER, 0, -90);
lv_led_set_color(led1, lv_color_hex(0xff0000));
lv_led_off(led1); // Make it Off by default
/*------------------
* Button
* -----------------*/
static lv_indev_drv_t indev_drv_1;
/*Initialize your button if you have*/
button_init_1();
/*Register a button input device*/
lv_indev_drv_init(&indev_drv_1);
indev_drv_1.type = LV_INDEV_TYPE_BUTTON;
indev_drv_1.read_cb = button_read_1;
indev_button_1 = lv_indev_drv_register(&indev_drv_1);
/*Assign buttons to points on the screen*/
static const lv_point_t btn_points[1] = {
{120, 90} //Button -> x:120; y:90
};
lv_indev_set_button_points(indev_button_1, btn_points);
}//End of Setup Function
void loop()
{
lv_timer_handler(); /* let the GUI do its work */
}//End of loop Function