LVGL 9.0 using animation does not compile on ESP32 /Arduino plattform 2.3.2

Hi LVGL community,

I am new to LVGL and playing around with Version 9.0 and have it running on ESP32 using Arduino 2.3.2 plattform.

Demos and widget examples provided in the example folder coming with the lib installed via Arduino lib manager are compiling and running fine (using tft_eSPI configuration or manual display configuration).
So far so good.

Now, I wanted to test the Temperature Meter example from the LVGL example web page by coping 1:1 the two funktions lv_example_bar_3 and set_temp into my arduino code (see below).
Unfortunately it does not compile using LVGL 9.0 when registering the set_temp function with lv_anim_set_exec_cb(&a, set_temp); throughing the following error:

O:\Arduino_myProjects\LVGL_9.0_demo\LVGL_9.0_demo.ino: In function ‘void set_temp(void*, int32_t)’:
O:\Arduino_myProjects\LVGL_9.0_demo\LVGL_9.0_demo.ino:303:22: error: invalid conversion from ‘void*’ to ‘lv_obj_t*’ {aka ‘_lv_obj_t*’} [-fpermissive]
lv_bar_set_value(bar, temp, LV_ANIM_ON);
^~~
In file included from c:\users\eiker\documents\arduino\libraries\lvgl\lvgl.h:53,
from c:\Users\eiker\Documents\Arduino\libraries\lvgl\src/lvgl.h:16,
from O:\Arduino_myProjects\LVGL_9.0_demo\LVGL_9.0_demo.ino:6:
c:\users\eiker\documents\arduino\libraries\lvgl\src/widgets/bar/lv_bar.h:86:34: note: initializing argument 1 of ‘void lv_bar_set_value(lv_obj_t*, int32_t, lv_anim_enable_t)’
void lv_bar_set_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim);

exit status 1

Can someone please tell me what needs to be changed in order to get the animation running? or if possible can you please provide a correct code to register the set_temp function for this example compiling under Arduino 2.3.2 plattform using ESP32/LVGL 9.0

Thank you all for your support.
Majestix

please find my code below:

Blockquote
/*Using LVGL with Arduino requires some extra steps:
*Be sure to read the docs here: https://docs.lvgl.io/master/get-started/platforms/arduino.html */
#define USE_GT911_TOUCH
#define USE_DFR0669

#include <lvgl.h>
#include <TFT_eSPI.h>

#ifdef USE_GT911_TOUCH
#include <TAMC_GT911.h>
#endif

/*To use the built-in examples and demos of LVGL uncomment the includes below respectively.
*You also need to copy lvgl/examples to lvgl/src/examples. Similarly for the demos lvgl/demos to lvgl/src/demos.
*Note that the lv_examples library is for LVGL v7 and you shouldn’t install it for this version (since LVGL v8)
*as the examples and demos are now part of the main LVGL library. */

#include <examples/lv_examples.h>
#include <demos/lv_demos.h>

typedef struct {
lv_obj_t *label;
lv_obj_t *button;
int16_t x=0;
int16_t y=0;
int16_t width=0;
int16_t height=0;
lv_palette_t mainColor;
lv_palette_t pressedColor;
lv_style_t style;
lv_style_t style_pressed;
lv_style_transition_dsc_t trans;
lv_style_prop_t props[3] = {LV_STYLE_OUTLINE_WIDTH, LV_STYLE_OUTLINE_OPA, 0};
}myButton_t;

myButton_t upButton;
myButton_t downButton;

/Set to your screen resolution/
#define TFT_HOR_RES 480
#define TFT_VER_RES 320

/LVGL draw into this buffer, 1/10 screen size usually works well. The size is in bytes/
#define DRAW_BUF_SIZE (TFT_HOR_RES * TFT_VER_RES / 20 * (LV_COLOR_DEPTH / 8))
void *draw_buf = heap_caps_malloc(DRAW_BUF_SIZE, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
static lv_display_t *disp;

unsigned long lastTickMillis = 0;

#ifdef LV_USE_TFT_ESPI
TFT_eSPI tft = TFT_eSPI(); /* TFT instance */
#endif

#ifdef USE_GT911_TOUCH
// ** Touchscreen **
#define TOUCH_SDA 21
#define TOUCH_SCL 22
#define TOUCH_INT 25
#define TOUCH_RST 26
#define TOUCH_WIDTH TFT_HOR_RES
#define TOUCH_HEIGHT TFT_VER_RES
TAMC_GT911 touch = TAMC_GT911(TOUCH_SDA, TOUCH_SCL, TOUCH_INT, TOUCH_RST, TOUCH_WIDTH, TOUCH_HEIGHT);
TP_Point oldPoint;
#endif

#if LV_USE_LOG != 0
void my_print( lv_log_level_t level, const char * buf )
{
LV_UNUSED(level);
Serial.println(buf);
Serial.flush();
}
#endif

#if !LV_USE_TFT_ESPI
/* LVGL calls it when a rendered image needs to copied to the display*/
void disp_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
{
uint32_t w = ( area->x2 - area->x1 + 1 );
uint32_t h = ( area->y2 - area->y1 + 1 );

tft.startWrite();
tft.setAddrWindow( area->x1, area->y1, w, h );
tft.pushColors(( uint16_t *) px_map, w * h, true );
tft.endWrite();

/Call it to tell LVGL you are ready/
lv_disp_flush_ready(disp);
}
#endif

/Read the touchpad/
void touchpad_cb( lv_indev_t * indev, lv_indev_data_t * data )
{
#ifdef USE_GT911_TOUCH
// Read touch data from GT911
touch.read();
if (touch.isTouched) {
data->point.x = touch.points[0].x;
data->point.y = touch.points[0].y;
Serial.printf(“x:%d, y:%d\n”, data->point.x, data->point.y);
data->state = LV_INDEV_STATE_PRESSED;
}
else
{
data->state = LV_INDEV_STATE_RELEASED;
}
#endif
}

void setup()
{
Serial.begin( 115200 );

String LVGL_Arduino = "Hello Arduino! ";
LVGL_Arduino = String('V') + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch() + "running with Arduino on ESP32";

Serial.println( LVGL_Arduino );

#if !LV_USE_TFT_ESPI
  tft.begin();        // TFT init
  tft.setRotation(1); // Landscape orientation
  tft.fillScreen(TFT_GREEN);
  Serial.println( "TFT_eSPI setup done" );
#endif

#ifdef USE_GT911_TOUCH
  touch.begin();
  touch.setRotation(ROTATION_RIGHT); //ROTATION_LEFT = Landscape, ROTATION_INVERTED,  ROTATION_RIGHT = Landscape , ROTATION_NORMAL
  Serial.println( "GT911 setup done" );
#endif

lv_init();
Serial.println( "LVGL init done" );

/* register print function for debugging */

#if LV_USE_LOG != 0
lv_log_register_print_cb( my_print );
Serial.println( “LVGL log print registered” );
#endif

#if LV_USE_TFT_ESPI
/TFT_eSPI can be enabled lv_conf.h to initialize the display in a simple way/
disp = lv_tft_espi_create(TFT_HOR_RES, TFT_VER_RES, draw_buf, DRAW_BUF_SIZE);
Serial.println( “LVGL using TFT_SPI init done” );
#else
/Else create a display yourself/
disp = lv_display_create(TFT_HOR_RES, TFT_VER_RES);
lv_display_set_flush_cb(disp, disp_flush_cb);
lv_display_set_buffers(disp, draw_buf, NULL, DRAW_BUF_SIZE, LV_DISPLAY_RENDER_MODE_PARTIAL); //LV_DISPLAY_RENDER_MODE_DIRECT); //LV_DISPLAY_RENDER_MODE_PARTIAL);
Serial.println( “LVGL disp driver created” );
#endif

/*Initialize the (dummy) input device driver*/
lv_indev_t *indev = lv_indev_create();
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); /*Touchpad should have POINTER type*/
lv_indev_set_read_cb(indev, touchpad_cb);
Serial.println( "LVGL touch driver created" );

/* Create a simple label
 * ---------------------
 lv_obj_t *label = lv_label_create( lv_scr_act() );
 lv_label_set_text( label, "Hello Arduino, I'm LVGL!" );
 lv_obj_align( label, LV_ALIGN_CENTER, 0, 0 );

 * Try an example. See all the examples
 *  - Online: https://docs.lvgl.io/master/examples.html
 *  - Source codes: https://github.com/lvgl/lvgl/tree/master/examples
 * ----------------------------------------------------------------

 lv_example_btn_1();

 * Or try out a demo. Don't forget to enable the demos in lv_conf.h. E.g. LV_USE_DEMOS_WIDGETS
 * -------------------------------------------------------------------------------------------

 lv_demo_widgets();
 */

lv_obj_t *label = lv_label_create( lv_scr_act() );
lv_label_set_text( label, "Hello Arduino, LVGL 9.0 is running!" );
lv_obj_align( label, LV_ALIGN_CENTER, 0, 0 );

//lv_example_button_1();
//lv_example_button_2();
//lv_example_button_3();


//lv_example_buttonmatrix_1();
//lv_example_buttonmatrix_2();
//lv_example_buttonmatrix_3();

//lv_obj_t * 
//upButton.button = lv_button_create(lv_screen_active());
upButton=setButtonStyle(70,190,"UP",150,50,LV_PALETTE_BLUE, LV_PALETTE_BLUE_GREY,true);

//lv_obj_t * 
//downButton.button = lv_button_create(lv_screen_active());
downButton=setButtonStyle(270,190,"DOWN",150,50,LV_PALETTE_BLUE, LV_PALETTE_BLUE_GREY,true);

//tempBar(10,10,20,200,-20,40,LV_PALETTE_BLUE,LV_PALETTE_RED);

drawSpinner(240,60,70,70);

//lv_demo_benchmark();
//lv_demo_widgets();
//lv_demo_render();
//lv_demo_scroll();
//lv_demo_flex_layout();

Serial.println( "Setup done" );

}

void loop()
{
// LVGL Tick Interface
unsigned int tickPeriod = millis() - lastTickMillis;
lv_tick_inc(tickPeriod);
lastTickMillis = millis();

lv_timer_handler(); /* let the UI do its work */

}

/**

  • Style a button from scratch
    */
    myButton_t setButtonStyle(int16_t x, int16_t y, const char * text, int16_t width, int16_t height, lv_palette_t mainColor, lv_palette_t pressedColor,bool animation)
    {
    int16_t shadow_size = 4;

myButton_t button;
button.x=x;
button.y=y;
button.width=width;
button.height=height;
button.mainColor=mainColor;

/Init the style for the default state/
static lv_style_t style;
lv_style_init(&style);

lv_style_set_radius(&style, 6);

lv_style_set_bg_opa(&style, LV_OPA_100);
lv_style_set_bg_color(&style, lv_palette_main(mainColor));
lv_style_set_bg_grad_color(&style, lv_palette_darken(mainColor, 6));
lv_style_set_bg_grad_dir(&style, LV_GRAD_DIR_VER);

lv_style_set_border_opa(&style, LV_OPA_40);
lv_style_set_border_width(&style, 4);
lv_style_set_border_color(&style, lv_palette_main(LV_PALETTE_GREY));

lv_style_set_shadow_width(&style, shadow_size);
lv_style_set_shadow_color(&style, lv_palette_main(LV_PALETTE_GREY));
lv_style_set_shadow_offset_x(&style, shadow_size);
lv_style_set_shadow_offset_y(&style, shadow_size);

lv_style_set_outline_opa(&style, LV_OPA_COVER);
lv_style_set_outline_color(&style, lv_palette_main(pressedColor));

lv_style_set_text_color(&style, lv_color_white());
lv_style_set_pad_all(&style, 10);

/Init the pressed style/
static lv_style_t style_pressed;
lv_style_init(&style_pressed);

/Add a large outline when pressed/
if(animation)
{
lv_style_set_outline_width(&style_pressed, 30);
lv_style_set_outline_opa(&style_pressed, LV_OPA_TRANSP);
}

lv_style_set_translate_y(&style_pressed, 5);
lv_style_set_shadow_offset_x(&style_pressed, 3);
lv_style_set_shadow_offset_y(&style_pressed, 3);
lv_style_set_bg_color(&style_pressed, lv_palette_darken(pressedColor, 2));
lv_style_set_bg_grad_color(&style_pressed, lv_palette_darken(pressedColor, 8));

/Add a transition to the outline/
static lv_style_transition_dsc_t trans;
static lv_style_prop_t props[] = {LV_STYLE_OUTLINE_WIDTH, LV_STYLE_OUTLINE_OPA, 0};
lv_style_transition_dsc_init(&trans, props, lv_anim_path_linear, 300, 0, NULL);
lv_style_set_transition(&style_pressed, &trans);

lv_obj_t * btn1 = lv_button_create(lv_screen_active());
lv_obj_remove_style_all(btn1); /Remove the style coming from the theme/
lv_obj_add_style(btn1, &style, 0);
lv_obj_add_style(btn1, &style_pressed, LV_STATE_PRESSED);
lv_obj_set_pos(btn1,x,y);
lv_obj_set_size(btn1, width, height); //LV_SIZE_CONTENT, LV_SIZE_CONTENT);
//lv_obj_center(btn1);

lv_obj_t * label = lv_label_create(btn1);
lv_label_set_text(label, text);
lv_obj_center(label);

return button;
}

static void set_temp(void * bar, int32_t temp)
{
lv_bar_set_value(bar, temp, LV_ANIM_ON);
}

/**

  • A temperature meter example
    */
    void lv_example_bar_3(void)
    {
    static lv_style_t style_indic;

    lv_style_init(&style_indic);
    lv_style_set_bg_opa(&style_indic, LV_OPA_COVER);
    lv_style_set_bg_color(&style_indic, lv_palette_main(LV_PALETTE_RED));
    lv_style_set_bg_grad_color(&style_indic, lv_palette_main(LV_PALETTE_BLUE));
    lv_style_set_bg_grad_dir(&style_indic, LV_GRAD_DIR_VER);

    lv_obj_t * bar = lv_bar_create(lv_screen_active());
    lv_obj_add_style(bar, &style_indic, LV_PART_INDICATOR);
    lv_obj_set_size(bar, 20, 200);
    lv_obj_center(bar);
    lv_bar_set_range(bar, -20, 40);

    lv_anim_t a;
    lv_anim_init(&a);
    lv_anim_set_exec_cb(&a, set_temp);
    lv_anim_set_duration(&a, 3000);
    lv_anim_set_playback_duration(&a, 3000);
    lv_anim_set_var(&a, bar);
    lv_anim_set_values(&a, -20, 40);
    lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
    lv_anim_start(&a);
    }

void tempBar(int16_t x, int16_t y, int16_t width, int16_t height, int16_t minVal, int16_t maxVal, lv_palette_t startColor, lv_palette_t endColor)
{
static lv_style_t style_indic;

lv_style_init(&style_indic);
lv_style_set_bg_opa(&style_indic, LV_OPA_COVER);
lv_style_set_bg_color(&style_indic, lv_palette_main(endColor));
lv_style_set_bg_grad_color(&style_indic, lv_palette_main(startColor));
lv_style_set_bg_grad_dir(&style_indic, LV_GRAD_DIR_VER);

lv_obj_t * bar = lv_bar_create(lv_screen_active());
lv_obj_add_style(bar, &style_indic, LV_PART_INDICATOR);
lv_obj_set_size(bar, width, height);
lv_obj_set_pos(bar,x,y);
//lv_obj_center(bar);
lv_bar_set_range(bar, minVal, maxVal);

lv_anim_t anim;
lv_anim_init(&anim);
//lv_anim_set_exec_cb(&anim, set_temp);
//lv_anim_set_custom_exec_cb(&anim, set_temp);
lv_anim_set_duration(&anim, 3000);
lv_anim_set_playback_duration(&anim, 3000);
lv_anim_set_var(&anim, bar);
lv_anim_set_values(&anim, minVal, maxVal);
lv_anim_set_repeat_count(&anim, LV_ANIM_REPEAT_INFINITE);
lv_anim_start(&anim);

}

void drawSpinner(int16_t x, int16_t y, int16_t width, int16_t height)
{
static lv_style_t style;
lv_style_init(&style);
lv_style_set_bg_opa(&style, LV_OPA_COVER);
lv_style_set_bg_color(&style, lv_palette_main(LV_PALETTE_RED));
lv_style_set_bg_grad_color(&style, lv_palette_main(LV_PALETTE_GREEN));
lv_style_set_bg_grad_dir(&style, LV_GRAD_DIR_VER);

/*Create a spinner*/
lv_obj_t * spinner = lv_spinner_create(lv_screen_active());
lv_obj_add_style(spinner, &style, LV_PART_INDICATOR);
lv_obj_set_size(spinner, width, height);
lv_obj_set_pos(spinner, x-(width/2), y);
//lv_obj_center(spinner);
lv_spinner_set_anim_params(spinner, 800, 250);

}

Blockquote

Hi, found the issue…
GCC C++ logic used by Arduino plattform

Solution:
add direct cast (lv_obj_t*)

static void set_temp(void * bar, int32_t temp)
{
lv_bar_set_value((lv_obj_t)* bar, temp, LV_ANIM_ON);
}

Or in real life you know uibar and have one temp, then complete remove bar from set_temp or complete set_temp. And simply call lv_bar inplace…