Updating values on a screen

Description

What is a good practice to call a cyclic refresh for values on a sreen/page?

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

STM32F407VE, 3.2" TFT

What do you want to achieve?

cyclic refresh for values that are changing by other threads.

I want to assign an update function to a screen. This function checks if a value has changed and calls the update for the object.
For a generic approach, a function call back could be stored in the page ext structure and this function could be called from the lv_handler_task. When switching pages, only the assigned update handler is called.
This would require a cb function pointer in the lv_page_ext_t structure, a set function and the call in the lv_handler_task.

What have you tried so far?

brainstorming.
Would this be a usefull modification or is possible already with using lv_tasks? With tasks I see the disadvantage that the task must know the screens to decide which handler must be called.

I see, the lv_obj_user_data_t could be also used to store an update handler and this could be called in a lv_task. This would be possible without modifying core structures. But how about this idea as a new feature for 6.1?

I must apologize for not knowing exactly what a “cyclic refresh” means here. Could you explain that?

yes, some measurement like a temperature that is updated in another thread. I don’t want to call (and implement mutex stuff) the lv_ functions to update the temperature value in another thread. Instead, the update handler checks the values that are displayed on the screen and if changed, calls the lv function for updating a label, status or something else.

I’ve tried to solve it with the user_data and it works.

  • the page user_data is set to the update handler
  • a generic task is created. This tasks checks for an existing update_handler in user_data of actual screen and calls it
typedef void (*lv_update_cb_t)(bool);

static void lv_screen_update_task(lv_task_t* task)
{
    static lv_obj_t* lastScreen = 0;
    bool firstStart;

    lv_obj_t* actScreen = lv_disp_get_scr_act(NULL);
    firstStart = (actScreen != lastScreen);
    lastScreen = actScreen;

    if (actScreen && actScreen->user_data) {
        ((lv_update_cb_t)actScreen->user_data)(firstStart);
    }
}

int main(int argc, char** argv)
{
    /*Initialize LittlevGL*/
    lv_init();

    /*Initialize the HAL for LittlevGL*/
    hal_init();

    // register update handler
    lv_task_t* task = lv_task_create(lv_screen_update_task, 100, LV_TASK_PRIO_MID, 0);

    vParameterScreen();

    while (1) {
        /* Periodically call the lv_task handler.
        * It could be done in a timer interrupt or an OS task too.*/
        lv_task_handler();
        Sleep(10);       /*Just to let the system breathe */
    }

    return 0;
}

in my sreen:

static void lvParameterScreen_update_task(bool firstStart)
{
    static int motorPosOld = 0;
    char buffer[32];

    if (firstStart || (motorPos != motorPosOld)) {			// update only if value has changed
        snprintf(buffer, sizeof(buffer), "Pos: %4d", motorPos);
        lv_label_set_text(labelPos, buffer);
        motorPosOld = motorPos;
    }
}

void lvParameterScreen(void)
{

    /********************
     * CREATE A SCREEN
     *******************/
    /* Create a new screen and load it
     * Screen can be created from any type object type
     * Now a Page is used which is an objects with scrollable content*/
    lv_obj_t * scr = lv_page_create(NULL, NULL);
    scr->user_data = (lv_obj_user_data_t)lvParameterScreen_update_task;  // set update callback
    lv_disp_load_scr(scr);

   // adding screen objects
   // ...
}

This works with the user_data, but maybe this can be implemented in the core because the update function is usefull in many cases.

From reading the code I can see what you’re doing, but I think it’s not worth the extra complication. I don’t really see why you can’t either use a mutex or do everything on one OS thread (including checking the motor position). If you need to find out if the motor position changed, create a LittlevGL task that runs every 200ms (or whatever refresh rate you need) and checks for a change in the motor position. LittlevGL tasks don’t require a mutex because they are run by lv_task_handler.

1 Like

ok, in my example I used only one screen. When I have multiple screens with many elements, then my code does not check the inactive items. I have not checked yet how much it costs to update the objects when they are not displayed.
And with my code I can keep the create and update functions in one source and I don’t have to make display elements global. Not even the update function because this can be kept local in the create function.
thanks for your comments.