How to structure the GUI?

@embeddedt seems to have smoothed it out quite a bit, thanks!!
I did the following as you suggested, but only on the gauge object, as it failed to compile when I tried to pass the image object for the background in the function

Good to know; that means the gauge implementation is missing an invalidation somewhere.

Next question: are you using a separate widget for the background or are you just using a style on the gauge?

Here is the complete block of code for the gauge. This was suggested to me on Github, I think by you as well :smile:

{
static lv_color_t needleC[1]; // Gauge Needle Color
needleC[0].full = 0xF840;	  //0x0272;
static lv_color_t needleCenter;
needleCenter.full = 0x39E7;

static lv_style_t needle1;
lv_style_init(&needle1);
lv_style_set_line_width(&needle1, LV_STATE_DEFAULT, 7);			  // Set needle width
lv_style_set_line_rounded(&needle1, LV_STATE_DEFAULT, true);	  // Set needle end rounded corners
lv_style_set_size(&needle1, LV_STATE_DEFAULT, 34);				  // Set needle Circle radius
lv_style_set_bg_color(&needle1, LV_STATE_DEFAULT, LV_COLOR_GRAY); // Set needle circle color

lv_obj_t *guage_bg = lv_img_create(gauge_cont, NULL); // gauge_cont is the parent object
lv_img_set_src(guage_bg, &guage_bg_bar);

lv_obj_t *gauge1 = lv_gauge_create(guage_bg, NULL);
lv_obj_clean_style_list(gauge1, LV_GAUGE_PART_MAJOR);	  // Reset the gauge scale styles
lv_obj_clean_style_list(gauge1, LV_GAUGE_PART_MAIN);	  // Reset the gauge scale styles
lv_obj_add_style(gauge1, LV_GAUGE_PART_NEEDLE, &needle1); // Add style to the needle object
lv_gauge_set_scale(gauge1, 266, 0, 0);
lv_gauge_set_angle_offset(gauge1, -43);
lv_gauge_set_range(gauge1, 0, 750);
lv_gauge_set_needle_count(gauge1, 1, needleC);
lv_obj_set_size(gauge1, 320, 319);
lv_obj_align(gauge1, NULL, LV_ALIGN_CENTER, 0, 0);
}

I uploaded my code to the teensy after invalidating the guage object when the value of the needle changes but although it looks smoother, the needle is still quite choppy when moving. I’m not sure if that’s due to the bottleneck of the SPI interface with the display of if it’s a bug with the gauge widget.
ezgif.com-video-to-gif (1)

1 Like

The invalidation hack I suggested is causing the whole gauge to be redrawn (instead of the space the needle is occupying), so that’s wasting SPI bandwidth. The real problem is that the gauge is not invalidating the needle area properly (probably somewhere around these lines).

Unfortunately, I don’t have time to investigate the exact reason this is happening, but you could take a peek at what coordinates that logic is coming up with - maybe you’ll find an obvious typo.

(cc @kisvegabor)

@embeddedt to be honest I’m not quite sure I will be able to spot anything, but I will do some experiments such as use the default background and see if it still happens. If it does, then it’s a core issue with the gauge widget I guess. If not, then some type of issue is introduced when I clean the style for LV_GAUGE_PART_MAJOR and LV_GAUGE_PART_MAIN perhaps.

@embeddedt I think I found the culprit…
lv_gauge_set_angle_offset
I have the offset set to -43. If I set it to anything below 0 it causes the issue of the needle not invalidating.

I suspect that perhaps there is a negative value being passed to a signed integer in the gauge widget code and it’s breaking the calculation of the area that needs to be redrawn…

Nice catch. With that line added I’m seeing the same thing on my board. Working on a fix now.

Much appreciated! I tried to fool the system and set the value to 317 (to get the same offset but in a positive value) but it demonstrated the same behaviour as the negative value.

I’ve fixed it in master. The invalidation hack should not be needed anymore.

1 Like

@embeddedt you rock!!! Thanks for a super quick fix!

I will update to the latest master, test, and confirm later on!

I’m back for more!

How do I pass two objects into a button callback?
I have the active screen >> obj0 (the main object)
Within obj0 I have two children, gauge_cont and param_cont

I want to run an animation on gauge_cont and param_cont when an object within gauge_cont is clicked.

I was thinking of using the following function in my click callback:

static void return_click(lv_obj_t * obj, lv_event_t e)
{
    if(e == LV_EVENT_CLICKED) {
        lv_obj_t * child = lv_obj_get_child_back(lv_scr_act(), NULL);
        while(child) {
        }
}

child now should be = obj0, so how do I access gauge_cont and param_cont?
I want to run this animation on them:

lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_time(&a, 1200);

lv_anim_path_t path;
lv_anim_path_init(&path);
lv_anim_path_set_cb(&path, lv_anim_path_ease_out);

//Set the path in an animation
lv_anim_set_path(&a, &path);

//Set the start and end points for each object
lv_anim_set_var(&a, gauge_cont);
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_x);
lv_anim_set_values(&a, 0, -320);
lv_anim_start(&a);

lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y);
lv_anim_set_values(&a, 0, 100);
lv_anim_start(&a);

lv_anim_set_var(&a, param_cont);
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_x);
lv_anim_set_values(&a, 280, 480);
lv_anim_start(&a);

lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y);
lv_anim_set_values(&a, 0,1000);
lv_anim_start(&a);

If it’s a simple UI where objects aren’t continually being added or removed, the cleanest solution is often one or more global variables.

So you mean at the top of my file I declare something in the lines of:

static lv_obj_t * gauge_cont;
static lv_obj_t * param_cont;

and in my code replace

lv_obj_t *gauge_cont = lv_obj_create(obj0, NULL);
lv_obj_t *param_cont = lv_obj_create(obj0, NULL);

with

gauge_cont = lv_obj_create(obj0, NULL);
param_cont = lv_obj_create(obj0, NULL);

And then I don’t need to start accessing parents/children within other functions?

Yes; that’s the idea. It’s not the neatest solution, but it often produces less code than searching for parents/children, especially for just a few objects.

1 Like

Awesome, that did the trick! Now I need to find out why my callback is not working :sweat_smile:

Just want to update on my progress so far… This library is AMAZING!!
ezgif.com-gif-maker

3 Likes

Very cool! :clap:

1 Like

So after a few weeks of trying to get the STM32 to run the ILI9488 in landscape mode with DMA2D (with no success), I went back to the teensy with a new display driver that was shared with me over at the the pjrc forum, and a few more days of work to get it all plumbed in - its finally working
https://youtu.be/Eo6UM204VMk

I still have more screens to build, and need to test it with live data stream, but it looks pretty cool in reality :slight_smile:

1 Like

So back to the Teensy 4.1 - the demo runs great.
I’ve now connected the LVGL app to the CAN BUS data stream and have prepared to test.
But I face a very very strange issue: The moment I update an objects value (Gauge, label, led) the whole app crashes.
The Teensy will stop after one main loop cycle and does not respond anymore.

Has anyone come across this behaviour?