Label Function to set Text Not Updating the Display Always

Description

Label Set Functions like lv_label_set_text and lv_label_set_text_fmt is not working properly always.

What MCU/Processor/Board and compiler are you using?

ESP32 Based Custom Board

What LVGL version are you using?

8.3.11

What do you want to achieve?

I am reading temperature and humidity data from a sensor, which I want to update on the display

What have you tried so far?

I tried to understand if this is the problem with the variables holding temperature and humidity values or something else. My variables contain correct data, the lvgl functions are not able to update the data.

Code to reproduce

void app_main(void)
{
  dht11_init(DHT11_PIN);
  display_init();  
  ui_init();
  current_language = LANGUAGE_ENGLISH;
  update_labels(current_language);
  while (true)
  {
    vTaskDelay(MAIN_TASK_PERIOD / portTICK_PERIOD_MS);
    // Get DHT11 Temperature and Humidity Values
    if( dht11_read().status == DHT11_OK )
    {
      temperature = (uint8_t)dht11_read().temperature;
      humidity = (uint8_t)dht11_read().humidity;
      ESP_LOGI(TAG, "Temperature: %d", temperature);
      ESP_LOGI(TAG, "Humidity: %d", humidity);
      update_temperature_humidity();
    }
    else
    {
      ESP_LOGI(TAG, "Unable to Read DHT11 Status");
    }
  }
}

I can’t share the whole code it will be too big, but sharing some snippets to get some idea.
update_temperature_humidity function is called, and temperature and humidity are global variables.

The following is the update_temperature_humidity function.

static void update_temperature_humidity( void )
{
  char buffer[10] = { 0 };
  snprintf(buffer, 10, "%u °C", temperature);
  lv_label_set_text(ui_lblTemperatureValue, buffer);
  snprintf(buffer, 10, "%u °C", humidity);
  lv_label_set_text(ui_lblHumidityValue, buffer);

  // lv_label_set_text_fmt(ui_lblTemperatureValue, "%u °C", temperature);
  // lv_label_set_text_fmt(ui_lblHumidityValue, "%u %%", humidity);
  ESP_LOGI(TAG, "Temperature = %u and Humidity = %u Updated on Display", temperature, humidity);
}

I tried with both functions 'lv_label_set_textandlv_label_set_text_fmt`, I only see that sometimes the values are updated and not always.

Screenshot and/or video

I don’t have the screenshot, but can share the logs which show that values are not corrupted.

I (399) spi_flash: flash io: dio
I (404) app_start: Starting scheduler on CPU0
I (408) app_start: Starting scheduler on CPU1
I (408) main_task: Started on CPU0
I (418) main_task: Calling app_main()
I (1418) gpio: GPIO[0]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
Flushing Time: 50 ms
Flushing Time: 82 ms
I (7188) gpio: GPIO[12]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (7218) APP: Temperature: 22
I (7218) APP: Humidity: 69
I (7218) APP: Temperature = 22 and Humidity = 69 Updated on Display
I (12228) gpio: GPIO[12]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (12258) APP: Temperature: 22
I (12258) APP: Humidity: 67
I (12268) APP: Temperature = 22 and Humidity = 67 Updated on Display
I (17268) gpio: GPIO[12]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (17298) APP: Temperature: 22
I (17298) APP: Humidity: 67
I (17308) APP: Temperature = 22 and Humidity = 67 Updated on Display
I (22318) gpio: GPIO[12]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (22348) APP: Temperature: 22
I (22348) APP: Humidity: 67
I (22358) APP: Temperature = 22 and Humidity = 67 Updated on Display

As you see on logs value is correct but on display, there is no update (98% no update, sometimes in between the values are updated).
There is no crash the other widgets on the display just work fine.
Please suggest.

Maybe you misunderstand how lvgl work , or only forget line of code. Try add before vtaskdelay

lv_timer_handler();

I didn’t share the complete code, the lv_timer_handler is already called in other tasks, as shown below.

static int max_flushing_time = 0;
static void display_mng(void *pvParameter)
{
  int64_t start_time = 0;
  while(1)
  {
    vTaskDelay(pdMS_TO_TICKS(20));
    if( pdTRUE == xSemaphoreTake(lvgl_semaphore, portMAX_DELAY) )
    {
      start_time = esp_timer_get_time();
      lv_timer_handler();
      // Semaphore is released when flushing is completed, this is checked using
      // tft_flush_status function, and then we release the semaphore
      // xSemaphoreGive(lvgl_semaphore);
    }

    // check flushing status
    if( tft_flush_status() == true )
    {
      // printf("Flushing Time: %d" PRId64 ", %" PRId64 "\n", esp_timer_get_time(), start_time);
      int time_taken = (int32_t)((esp_timer_get_time() - start_time)/1000);
      if( time_taken > max_flushing_time )
      {
        max_flushing_time = time_taken;
        printf("Flushing Time: %d ms\n", max_flushing_time );
      }
      xSemaphoreGive(lvgl_semaphore);
    }
  }
}

Do I have to call this function still again?
For me the behavior is strange, I am not saying it is not working, it is updating the values but not always.

1 Like

??

Read and apply Operating system and interrupts — LVGL documentation

1 Like

Thank You for the link. I learned something new about LVGL today, some of the key points, that I think fixed the issue are as below.

  • LVGL is not thread-safe.
  • So we need mutex, which should be invoked before the call of lv_timer_handler and released after it
  • And we have to use the same mutex around every LVGL function call.
    • This point is very important for me because my lv_timer_handler was already protected by mutex, and then I created another mutex to protect my lvgl function calling, which is just a stupid idea, we have to use the same mutex, and then I did that and it fixes the problem.

@Marian_M Thank You very much.

Updated function is as below

static void update_temperature_humidity( void )
{
  if( true == display_update_lock() )
  {
    lv_label_set_text_fmt(ui_lblTemperatureValue, "%d °C", temperature);
    lv_label_set_text_fmt(ui_lblHumidityValue, "%d %%", humidity);
    ESP_LOGI(TAG, "Variable Temperature = %d, Humidity = %d Updated on Display", temperature, humidity);
    ESP_LOGI(TAG, "Label => Temperature = %s, Humidity = %s", lv_label_get_text(ui_lblTemperatureValue), lv_label_get_text(ui_lblHumidityValue));
    display_update_unlock();
  }
}

Yes , but normal simple way is use lvgl and update it in same thread, then you dont require any mutexxx. On other thread you handle special tasks and for example receive data store it , but don call lv show. Instead set some flag to true and in lvgl loop if true show new stored data…

1 Like

Thank You for the suggestion.
I will update accordingly, many thanks.