Unable to update label text on the screen (lv_label_set_text_fmt)

What do you want to achieve?

Updating label text (using lv_label_set_text_fmt()) periodically.

What have you tried so far?

Project link so far, iotProjects/esp32s3/m5dial_base at main · ra7narajm/iotProjects · GitHub
As a newbie I am trying to create a basic clock, I have created two label (clock-label and date label) objects with default text.
Text for these labels should be updated periodically.

The issue here is, label text appears to be getting updated, I am confirming text update with following after every lv_label_set_text_fmt(),
Serial.printf("updating clockLabel %s\n", lv_label_get_text(objects.clockLabel));

The console prints show label getting updated, but on screen label text is not updated.

Code to reproduce

static void __ui_create_screens(void) {
    //main screen, clock face
    objects.main = lv_obj_create(lv_scr_act());
    lv_obj_set_pos(objects.main, 0, 0);
    //lv_obj_align(objects.main, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_size(objects.main, 240, 240);
    lv_obj_set_style_bg_color(objects.main, lv_color_hex(0xfff8f8f8), LV_PART_MAIN | LV_STATE_DEFAULT);
    //lv_obj_set_style_bg_color(objects.main, lv_color_white(), LV_PART_MAIN);

    //clock
    {
        objects.clockLabel = lv_label_create(objects.main);
        lv_obj_set_size(objects.clockLabel, 180, 70);
        lv_obj_set_pos(objects.clockLabel, 20, 55);
        //lv_obj_align(objects.clockLabel, LV_ALIGN_CENTER, 30, 53);
        lv_obj_set_style_bg_color(objects.clockLabel, lv_color_hex(0xfff8f8f8), LV_PART_MAIN | LV_STATE_DEFAULT);
        lv_obj_set_style_text_align(objects.clockLabel, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT);
        lv_obj_set_style_text_font(objects.clockLabel, &orbitron_24_4bpp, LV_PART_MAIN | LV_STATE_DEFAULT);
        lv_obj_set_style_text_color(objects.clockLabel, lv_color_black(), LV_PART_MAIN);
        lv_label_set_text(objects.clockLabel, "HH:MM:SS");
    }
    //date
    {
        objects.dateLabel = lv_label_create(objects.main);
        lv_obj_set_size(objects.dateLabel, 180, 35);
        lv_obj_set_pos(objects.dateLabel, 20, 135);
        //lv_obj_align(objects.dateLabel, LV_ALIGN_CENTER, 30, 53);
        lv_obj_set_style_bg_color(objects.dateLabel, lv_color_hex(0xfff8f8f8), LV_PART_MAIN | LV_STATE_DEFAULT);
        lv_obj_set_style_text_align(objects.dateLabel, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT);
        lv_obj_set_style_text_font(objects.dateLabel, &orbitron_14_4bpp, LV_PART_MAIN | LV_STATE_DEFAULT);
        lv_obj_set_style_text_color(objects.dateLabel, lv_color_black(), LV_PART_MAIN);
        lv_label_set_text(objects.dateLabel, "Day, Dt Mon, YYYY");
    }
}

static constexpr const char* const wday[7] = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
static constexpr const char* const month[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
void update_time_task(lv_timer_t * timer) {
    struct tm dtInfo;
    char labelBuf[24];
    peripheral_rtc_get_date_time(&dtInfo);
    Serial.println(&dtInfo, "%A, %B %d %Y %H:%M:%S");
    {
        //sprintf(labelBuf, "%02d:%02d:%02d", dtInfo.tm_hour, dtInfo.tm_min, dtInfo.tm_sec);
        lv_label_set_text_fmt(objects.clockLabel, "%02d:%02d:%02d", dtInfo.tm_hour, dtInfo.tm_min, dtInfo.tm_sec);
        Serial.printf("updating clockLabel %s\n", lv_label_get_text(objects.clockLabel));
    }
    {
        //TODO need not update every tick
        //sprintf(labelBuf, "%s, %02d %s, %04d", wday[dtInfo.tm_wday], dtInfo.tm_mday, month[dtInfo.tm_mon], dtInfo.tm_year + 1900);
        lv_label_set_text_fmt(objects.dateLabel, "%s, %02d %s, %04d", wday[dtInfo.tm_wday], dtInfo.tm_mday, month[dtInfo.tm_mon], dtInfo.tm_year + 1900);
        Serial.printf("updating dateLabel %s\n", lv_label_get_text(objects.dateLabel));
    }
}

Screenshot and/or video

Environment

  • MCU/MPU/Board: M5Dial (platformio board: m5stack-stamps3)
  • LVGL version: 9.4.0

I may be understanding the code wrong, but i see some issues:

  • You don’t have a function to inc the lvgl timer, you need to call “lv_tick_inc(x)” periodically, so LVGL knows how much time has passed.
  • In your loop, you have a vTaskDelay(1000); this would make things quite slow, since you are updating the GUI (calling LVGL) in this loop.

Try replace you loop with:

void loop() {
  // put your main code here, to run repeatedly:
  lv_timer_handler();   //older version lv_task_handler() ref: https://docs.lvgl.io/8/porting/timer-handler.html
  ui_tick();
  vTaskDelay(1);
  lv_tick_inc(1);
}

Not a correct way, but enough to see if anything changes on screen.

1 Like

Your suggestion worked. and that helped me move label update to 1 Sec timer lv_timer_create(update_time_task, 1000, NULL);

Thank you.