Needle superimposed on the screen. Update screen?

Please help me. What can I do to prevent this from happening on my screen?

This needle overlap?

Is there a clear screen command?

My code is:

void v_Display(void *parameters){
     float tempReceived;
     char tempC_char[20];
            xQueueReceive(TempC_Queue, &tempReceived, pdMS_TO_TICKS(0));
            sprintf(tempC_char, "%.2fºC", tempReceived);
            if (xSemaphoreTake(xMutex, 100)) {
                lv_meter_set_indicator_end_value(MyGauge[0], indic1[0], tempReceived);
                lv_label_set_text(ui_lblTemp, tempC_char);
                lv_label_set_text(ui_lblDataHora, datahora_formatadaX);
            vTaskDelay(10 / portTICK_PERIOD_MS);


This code is started screen:

void My_Demo(int pos, void * panel){
        MyGauge[pos] = lv_meter_create(panel);
        lv_obj_set_size(MyGauge[pos], 220, 220);
        lv_obj_align(MyGauge[pos], LV_ALIGN_CENTER, 0, 0);

        scale[0] = lv_meter_add_scale(MyGauge[pos]);

        lv_meter_set_scale_ticks(MyGauge[pos], scale[0], gauge.Marcador_C, gauge.Marcador_Larg, gauge.Marcador_Alt, c_HexColor(gauge.Marcador_Color));
        lv_meter_set_scale_major_ticks(MyGauge[pos], scale[0], gauge.MarcadorP_K, gauge.MarcadorP_Larg, gauge.MarcadorP_Alt, c_HexColor(gauge.MarcadorP_Color), gauge.Dist);
        lv_meter_set_scale_range(MyGauge[pos], scale[0], gauge.R_Inicio, gauge.R_Fim, 180, 180);

        if (gauge.F1_Ativar){
            indic1[pos] = lv_meter_add_arc(MyGauge[pos], scale[0], gauge.F1_Larg, c_HexColor(gauge.F1_Color), gauge.F1_R);
            lv_meter_set_indicator_start_value(MyGauge[pos], indic1[pos], gauge.F1_Inicio);
            lv_meter_set_indicator_end_value(MyGauge[pos], indic1[pos], gauge.F1_Fim);

        if (gauge.F2_Ativar){
            indic2[pos] = lv_meter_add_arc(MyGauge[pos], scale[0], gauge.F2_Larg, c_HexColor(gauge.F2_Color), gauge.F2_R);
            lv_meter_set_indicator_start_value(MyGauge[pos], indic2[pos], gauge.F2_Inicio);
            lv_meter_set_indicator_end_value(MyGauge[pos], indic2[pos], gauge.F2_Fim);

        if (gauge.F3_Ativar){
            indic3[pos] = lv_meter_add_arc(MyGauge[pos], scale[0], gauge.F3_Larg, c_HexColor(gauge.F3_Color), gauge.F3_R);
            lv_meter_set_indicator_start_value(MyGauge[pos], indic3[pos], gauge.F3_Inicio);
            lv_meter_set_indicator_end_value(MyGauge[pos], indic3[pos], gauge.F3_Fim);

        indic1[pos] = lv_meter_add_needle_line(MyGauge[pos], scale[0], gauge.Agulha_Larg, c_HexColor(gauge.Agulha_Color), gauge.Agulha_Alt);

        lv_obj_set_style_bg_opa(MyGauge[pos], 0, LV_PART_MAIN|LV_STATE_DEFAULT);
        lv_obj_set_style_radius(MyGauge[pos], 0, LV_PART_MAIN|LV_STATE_DEFAULT);
        lv_obj_set_style_border_width(MyGauge[pos], 3, LV_PART_MAIN|LV_STATE_DEFAULT);
        lv_obj_set_style_border_opa(MyGauge[pos], 181, LV_PART_MAIN|LV_STATE_DEFAULT);
        lv_obj_set_style_border_color(MyGauge[pos], lv_color_hex(0xffffff), LV_PART_MAIN|LV_STATE_DEFAULT);
        lv_obj_set_style_border_side(MyGauge[pos], LV_BORDER_SIDE_NONE, LV_PART_MAIN|LV_STATE_DEFAULT);
        lv_obj_set_style_shadow_width(MyGauge[pos], 0, LV_PART_MAIN|LV_STATE_DEFAULT);
        lv_obj_set_style_text_color(MyGauge[pos], c_HexColor(gauge.Color), LV_PART_TICKS|LV_STATE_DEFAULT); //Branco
        lv_obj_set_style_text_font(MyGauge[pos], &ui_font_Verdana16, LV_PART_TICKS|LV_STATE_DEFAULT);

        //Write style for speed_MyGauge, Part: LV_PART_INDICATOR, State: LV_STATE_DEFAULT.
        lv_obj_set_style_bg_opa(MyGauge[pos], 255, LV_PART_INDICATOR|LV_STATE_DEFAULT);
        lv_obj_set_style_bg_color(MyGauge[pos], lv_color_hex(0x000000), LV_PART_INDICATOR|LV_STATE_DEFAULT);//Preto


@kdschlosser (Help me please)

what version of LVGL are you using? if you are using 8.x I don’t have as much exposure to that version so IDK if I would be able to help you. there have been lots of widget bug fixes in version 9 which is going to be released pretty soon now we are putting the final touches on it.

My LVGL version is 8.3.11

The idea of ​​this request for help is to develop changes to the plotted Gauge in my product without having to restart the MCU.

To make it more practical for the user

I am thinking you wanna use something like this.

your issue is you are using the wrong function to set the value of the meter. You should be using

void lv_meter_set_indicator_value(lv_obj_t *obj, lv_meter_indicator_t *indic, int32_t value)

instead of


the start value and end value is the range the indicator is going to be allowed to travel. the reason why you are getting 2 of them is more than likely being caused by the indicator being outside of the range you have set when you changed the end value.

I made the change and this problem continues to occur.

But it doesn’t always happen, it just happens sometimes.

Is there any other command I can give in LVGL that recreates the screen. Like a clear screen?

Any suggestions on how I can ensure this doesn’t happen?

I am not sure if lv_refr_now(disp) forces a refresh of the entire screen or not. You can try it.

I try …

Is don’t work.

Is my function:

Is my tentative…is not work:


And for debug purpose:


all code:

void setupDisplay(){

        lv_disp_draw_buf_init( &draw_buf, buf1, NULL, screenWidth * screenHeight / 13 );

        static lv_disp_drv_t disp_drv;
        lv_disp_drv_init( &disp_drv );
        //Display driver port of LVGL
        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 );

        static lv_indev_drv_t indev_drv;
        lv_indev_drv_init( &indev_drv );
        indev_drv.type = LV_INDEV_TYPE_POINTER;
        indev_drv.read_cb = my_touchpad_read;
        lv_indev_drv_register( &indev_drv );
        Serial.println("[INFO] - Config Display");

void v_DisplayTemp(void *parameters){
     float tempReceived;
     float tempReceivedAnt;
     char tempC_char[20];
            if (xQueueReceive(TempC_Queue, &tempReceived, portMAX_DELAY)){
                if (tempReceived !=tempReceivedAnt){
                    sprintf(tempC_char, "%.2fºC", tempReceived);
                    if (xSemaphoreTake(xMutex, portMAX_DELAY)) {
                        lv_meter_set_indicator_value(MyGauge[0], indic1[0], tempReceived);
                        lv_label_set_text(ui_lblTemp, tempC_char);


I cannot really comment on most of this code but lv_timer_handler() should be called in your main loop! See: Task Handler — LVGL documentation

This might be part of the problem… unless v_displayTemp() is your main loop, in which case it does not seem wise to have the timer handler enclosed in a mutex.

There is no main loop because I am using FreeRTOs with several simultaneous tasks, this is the task that performs the function of updating the screen all the time with the temperature.

There is a Semaphore because at some point other tasks also need to update items on the screen with LVGL and I don’t want them to do that at the same time, the behavior gets weird. Even after inserting the semaphoro, everything was correct.

Although I still have this problem with the needle overlapping the screen.