Description
I have LVGL working on an ESP32C3 with ESP IDF 5.1.2. I have a basic hello world thing going. Im using an ST7735 SPI display 160x128pixels. What im trying to accomplish is to read a temperature sensor and display that on my TFT. I have a task that runs every 10 seconds and does read the temperature (I2C) and display it on the console. However when this task runs, it seems to wipe out the display. The lv_task_handler while loop is still working (verified with printf) but the screen goes blank and never comes back. If i disable the temperature gathering task, the display will stay on with the ‘hello world’ indefinitely. So something is happening when the temperature task is called. Any idea what might be causing this? Ive spent days, read everythign i could find (including here) but cant seem to figure out how to get lvgl and FREERTOS non-lvgl tasks to work together.
What MCU/Processor/Board and compiler are you using?
ESP32C3
What LVGL version are you using?
8.3
What do you want to achieve?
What have you tried so far?
Code to reproduce
Add a code snippet which can run in the simulator. It should contain only the relevant code that compiles without errors when separated from your main code base.
The code block(s) should be formatted like:
#include <stdio.h>
#include "string.h"
#include "freertos/FreeRTOS.h"
//#include "freertos/queue.h"
#include "freertos/task.h"
//#include "freertos/event_groups.h"
#include "freertos/semphr.h"
#include "nvs_flash.h"
#include "esp_flash.h"
#include "esp_chip_info.h"
#include "esp_err.h"
#include "esp_timer.h"
#include "esp_log.h"
#include "driver/i2c.h"
#include "sht3x.h"
#include "lvgl/lvgl.h"
//#include "lvgl/examples/lv_examples.h"
#include "lvgl_esp32_drivers/lvgl_helpers.h"
#define I2C_MASTER_NUM 0
#define I2C_MASTER_SCL_IO 10
#define I2C_MASTER_SDA_IO 9
#define I2C_MASTER_FREQ_HZ 100000
#define I2C_MASTER_TX_BUF_DISABLE 0
#define I2C_MASTER_RX_BUF_DISABLE 0
#define SHT3X_ADDRESS 0x44
#define DISP_HOR_RES 128
#define DISP_VER_RES 160
#define LVGL_TICK_PERIOD_MS 1
static sht3x_t sht3x_dev;
float temperature;
float humidity;
SemaphoreHandle_t xGuiSemaphore;
lv_disp_draw_buf_t draw_buf;
lv_disp_drv_t disp_drv;
static void measure_temphum(void *pvParameters)
{
TickType_t last_wakeup = xTaskGetTickCount();
uint8_t duration = sht3x_get_measurement_duration(SHT3X_HIGH);
while (1)
{
sht3x_start_measurement(&sht3x_dev, SHT3X_SINGLE_SHOT, SHT3X_HIGH);
printf("MARKER: measure temp\n");
// Wait until measurement is ready (constant time of at least 30 ms
// or the duration returned from *sht3x_get_measurement_duration*).
vTaskDelay(duration);
sht3x_get_results(&sht3x_dev, &temperature, &humidity);
printf("SHT3x Sensor: %.2f °C, %.2f %%\n", temperature, humidity);
// perform one measurement and do something with the results
vTaskDelayUntil(&last_wakeup, 10000/portTICK_PERIOD_MS);
printf( "Task Name\tStatus\tPrio\tHWM\tTask\tAffinity\n");
char stats_buffer[1024];
vTaskList(stats_buffer);
printf("%s\n", stats_buffer);
printf("MARKER: end of main\n");
}
}
static void gui_app(void)
{
lv_obj_t * scr1 = lv_obj_create(NULL);
lv_obj_set_style_bg_color(scr1, lv_color_make(0,0,63), LV_PART_MAIN);
lv_obj_t * label = lv_label_create(scr1);
lv_label_set_text(label, "Hello world!");
lv_obj_set_style_text_color(label, lv_color_make(0,63,0), LV_PART_MAIN);
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
lv_scr_load(scr1);
}
static void lvgl_tick_task(void *arg)
{
(void) arg;
lv_tick_inc(LVGL_TICK_PERIOD_MS);
}
static void lvgl_gui_init()
{
/*Setup LVGL*/
lv_init();
lvgl_driver_init();
/*Declare a buffer for 1/10 screen size*/
static lv_color_t buf1[DISP_HOR_RES * DISP_VER_RES / 10];
assert(buf1);
static lv_color_t buf2[DISP_HOR_RES * DISP_VER_RES / 10];
assert(buf2);
/*Initialize `disp_buf` with the buffer(s). With only one buffer use NULL instead buf_2 */
lv_disp_draw_buf_init(&draw_buf, buf1, buf2, DISP_HOR_RES * DISP_VER_RES / 10);
//static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
disp_drv.flush_cb = st7735s_flush; /*Set your driver function*/
disp_drv.draw_buf = &draw_buf; /*Assign the buffer to the display*/
disp_drv.hor_res = DISP_HOR_RES; /*Set the horizontal resolution of the display*/
disp_drv.ver_res = DISP_VER_RES; /*Set the vertical resolution of the display*/
disp_drv.rotated = 1;
lv_disp_drv_register(&disp_drv); /*Finally register the driver*/
/*Create timer to call lv_tick*/
static const esp_timer_create_args_t periodic_timer_args = {
.callback = &lvgl_tick_task,
.name = "periodic_gui"
};
static esp_timer_handle_t periodic_timer;
ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, LVGL_TICK_PERIOD_MS * 1000)); //time in microseconds
gui_app();
TickType_t last_wakeup;
xGuiSemaphore = xSemaphoreCreateMutex();
while (1) {
/* Delay 1 tick (assumes FreeRTOS tick is 10ms */
//vTaskDelay(1000 / portTICK_PERIOD_MS);
/* Try to take the semaphore, call lvgl related function on success */
if (pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY)) {
//printf("tick count before:%d\n",(int)xTaskGetTickCount());
lv_timer_handler();
//printf("tick count after:%d\n",(int)xTaskGetTickCount());
vTaskDelay(1000 / portTICK_PERIOD_MS);
xSemaphoreGive(xGuiSemaphore);
}
}
free(buf1);
free(buf2);
vTaskDelete(NULL);
}
void app_main(void)
{
//Initialize NVS
printf("MARKER: starting main\n");
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
//Check SOC Chip Specs
printf("MARKER: check chip\n");
check_chip();
//Initialize I2C
printf("MARKER: initialize I2C\n");
ESP_ERROR_CHECK(i2c_master_init());
printf("I2C:I2C Initialized SDA:%d SCL:%d CLK:%d\n",I2C_MASTER_SDA_IO,I2C_MASTER_SCL_IO,I2C_MASTER_FREQ_HZ);
//Scan for I2C devices
printf("MARKER: scan I2C\n");
scan_i2c();
i2c_driver_delete(I2C_NUM_0);
//Initialize task for temphum measurement
printf("MARKER: initialize I2C for temphum\n");
ESP_ERROR_CHECK(i2cdev_init());
memset(&sht3x_dev, 0, sizeof(sht3x_t));
ESP_ERROR_CHECK(sht3x_init_desc(&sht3x_dev, SHT3X_ADDRESS, 0, I2C_MASTER_SDA_IO, I2C_MASTER_SCL_IO));
ESP_ERROR_CHECK(sht3x_init(&sht3x_dev));
xTaskCreate(&lvgl_gui_init, "lvgl_gui_init", 8192*4, NULL, 3, NULL);
xTaskCreate(&measure_temphum, "measure_temphum", configMINIMAL_STACK_SIZE * 2, NULL, 0, NULL);
}
Screenshot and/or video
If possible, add screenshots and/or videos about the current state.