Description
I’m trying to get a simple “hello world” up and running. To show one that can update the screen, I have it change words once every second eg “hello”…“world.” The task handler is not updating on its own - it’s like it draws once, maybe twice, then gives up. The values can be output via Serial prints but the screen will only update if I use lv_refr_now(NULL) which feels hacky, I want to understand and fix what’s broken.
What MCU/Processor/Board and compiler are you using?
ESP32, and I’m using VSCode’s Platformio extension, installing the LVGL library with Platformio’s UI.
What do you want to achieve?
For now, just a working hello world demo that shows text or visuals that change on the screen. Eventually, I’m trying to create a dashboard for a car that’s being remote controlled, so we can monitor what’s going on, and tweak values that control the gas, steering etc.
What have you tried so far?
I started with LVGL 8.3.7 (latest available for Platformio), but the device would immediately get stuck in a reboot loop if I tried to run lv_task_handler.
So I downgraded to 7.11.0, and I was glad to see that the initial “Hello world” static text was displayed. A simple chart with static values was also working. But I noticed that if I tried to update the values, the screen still showed the old data.
I’ve also tried adding delays before, and after updating the values. I’ve tried moving the lv_task_handler call to after the value updates, and sometimes it draws a second value but then stops (This really drove me crazy).
I’ve changed LV_DISP_DEF_REFR_PERIOD to 20,30,100, 1000
I’ve tried adding while(lv_task_handler()) {delay(5);}
I’ve tried adding lv_obj_invalidate(chart) and lv_chart_refresh(chart)
I’ve spent days trouble shooting this and giving in, I need some help
Code to reproduce
#include "lvgl_display.h"
#include "lvgl.h"
#include <TFT_eSPI.h> // Include the graphics library
TFT_eSPI tft = TFT_eSPI();
// Called by the LVGL library to write to the display // eSPI
void 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, w * h, true);
tft.endWrite();
lv_disp_flush_ready(disp);
}
// Buffer for LVGL to draw
static lv_disp_buf_t disp_buf;
static lv_color_t buf[LV_HOR_RES_MAX * 10]; // Declare a buffer for 10 lines
void lvgl_init() {
// Initialize LVGL
lv_init();
// Initialize your display buffer
lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);
// Initialize a display driver
lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
disp_drv.hor_res = 320;
disp_drv.ver_res = 240;
disp_drv.flush_cb = disp_flush; /*Set your driver function*/
disp_drv.buffer = &disp_buf; /*Assign the buffer to the display*/
lv_disp_drv_register(&disp_drv); /*Finally register the driver*/
// Initialize TFT
tft.begin();
tft.setRotation(3); // Use landscape orientation
}
lv_obj_t *label; // global
void create_hello_world_label() {
// Create and style a label with a larger blue box around it
lv_obj_t *label_bg = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_size(label_bg, 200, 50);
lv_obj_set_style_local_bg_color(label_bg, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLUE);
lv_obj_set_style_local_radius(label_bg, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, 10);
lv_obj_set_style_local_value_font(label_bg, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, &lv_font_montserrat_14);
label = lv_label_create(label_bg, NULL);
lv_label_set_text(label, "Hello, world!");
lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, 0);
// Align label to center
lv_obj_align(label_bg, NULL, LV_ALIGN_CENTER, 0, 0);
}
void setup() {
Serial.begin (115200); // Open serial port
// Initialize the display
lvgl_init();
create_hello_world_label();
}
// Add an array of words to cycle through
const char* words[] = {"Hello", "World", "ESP32", "Arduino", "LVGL"};
const int num_words = sizeof(words) / sizeof(words[0]); // Calculate the number of words
int word_index = 0; // Start with the first word
void update_hello_world_label(const char* word) {
lv_label_set_text(label, word); // Update the label text
lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, 0); // Re-center the label on the screen
}
void loop() {
// Update the disp
lv_task_handler();
delay(5); // Allow some delay for system tasks
// Update the hello world text every second
word_index = (word_index + 1) % num_words; // Cycle through the words
update_hello_world_label(words[word_index]); // Update the label with the new word
// lv_refr_now(NULL); // force redraw
delay(1000); // delay so that you don't flood your Serial monitor with messages
}