How to create a clock?

Description

I want to make the dial as shown in the picture below, how can I achieve it? The efficiency of using canvas is too low to clear the previously drawn dial. The ram is too small, how to make a beautiful dial with as little overhead as possible.
clock_skin_model

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

Core-M4

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:

/*You code here*/

Screenshot and/or video

If possible, add screenshots and/or videos about the current state.

You should be able to use the lv_gauge object (possibly with some customization), if you increase its degree span to 360 degrees. This will be much more efficient than using a canvas.

Note that in 6.1 I’m not sure that you can apply a background to the gauge directly. You might want to consider trying the beta version of 7.0, which includes more features for changing the gauge’s style.

fast clock crate
/*

LV_IMG_DECLARE(watch_bg);
LV_IMG_DECLARE(hour);
LV_IMG_DECLARE(minute);
LV_IMG_DECLARE(second);

lv_obj_t * lvMinute;
lv_obj_t * lvHour;
lv_obj_t * lvSecond ;

uint8_t Minute =24;
uint8_t Hour =8;
uint8_t Second=2 ;

static void update_time(void *arg)
{
time_t now_t;
char strftime_buf[64];

if(Second++>60)
{
   Second=0;
    if(Minute++>60)
    {
        Minute=0;
       if(Hour++>12) Hour=0;
    }

}


if(main_clock_label !=NULL)
{
 sprintf(strftime_buf,"%d:%d:%d",Hour,Minute,Second);
 lv_label_set_text(main_clock_label, strftime_buf);
 }

if(lvHour !=NULL)
{

   // Hour,Minute,Second;


    lv_img_set_angle(  lvHour, Hour*30*10);
    lv_img_set_angle(  lvMinute, Minute*6*10);
    lv_img_set_angle(  lvSecond, Second*6*10);

}

}

void analog( lv_obj_t *win)
{

lv_obj_t *central = lv_page_create(win, NULL);
lv_obj_set_size(central, vres-2 , hres/2-2);
lv_obj_set_pos(central,  0, 0);
lv_page_set_scrlbar_mode(central, LV_SCRLBAR_MODE_OFF);


lv_obj_t * img = lv_img_create(central,NULL);
lv_img_set_src(img, &watch_bg);
lv_obj_set_size(img, 200, 200);
lv_obj_set_pos(img,pos_x,pos_y);



lvHour = lv_img_create(central,NULL);
lv_img_set_src( lvHour, &hour);
lv_obj_align(  lvHour, img,LV_ALIGN_CENTER, 0, 0);
lv_img_set_angle(  lvHour, 750);

lvMinute = lv_img_create(central,NULL);
lv_img_set_src( lvMinute, &minute);
lv_obj_align(  lvMinute, img,LV_ALIGN_CENTER, 0, 0);
lv_img_set_angle(  lvHour, 1950);

lvSecond = lv_img_create(central,NULL);
lv_img_set_src( lvSecond, &second);
lv_obj_align(  lvSecond, img,LV_ALIGN_CENTER, 0, 0);
lv_img_set_angle(  lvSecond, 600);

lv_task_create(update_time, 100, LV_TASK_PRIO_LOW, NULL);

}

*/
clock_app.zip (175.1 KB)WhatsApp Video 2020-08-02 at 18.09.01.zip (2.4 MB)

1 Like

Hi Hadi_Bashniji,

I’m trying to get your clock_app to compile.
Is there a .h file to include variables like vres, hres, pos_x, pos_y ?
I declare it myself but not sure the value for pos_x and pos_y.

Also I changed the
void analog( lv_obj_t *win)
{
to
void analog( void)
{
lv_obj_t *win;

In my main routine I call analog();

The program compile but the screen is blank.

I’m using the Teensy 4.0 with a 480x320 LCD and got the
lv_demo_widgets(); working so I know the hardware is ok.

Got it to work now. Not sure why the colour is different.

I think reds and blues are being swapped. If you’re using 16-bit color you can try flipping the value of LV_COLOR_16_SWAP.

I encountered the same problem as you, how did you solve it?

No, did you try

#define LV_COLOR_16_SWAP 1

I tried that but it made it worst.

Can you share the PNG images of this dial and hands? My color displayed on AMOLED is incorrect, I want to generate a C array test by myself. Thanks!

The files are from Hadi_Bashniji,
https://forum.lvgl.io/uploads/short-url/zUf3cBGX6h6Mtwln2QiAZnAd14.zip

Do you have the original PNG image of this watch dial?

clock.zip (116 Bytes)
As shown in my attachment, sometimes the pointer gets messy when it turns, have you encountered this situation?

Hi skpang,
Does your clock display normally when the hands move?
What is the vres, hres, pos_x, pos_y you set?

Do you use lv_lib_png? If so for some mysterious reasons we need to swap the Red and Blu color time to time because always the opposite seems valid. :smiley: It needs to be investigated once…

Anyway, you can try to swap the channels here.

1 Like

I use:
uint16_t vres = 320;
uint16_t hres = 480;
uint16_t pos_x = 0;
uint16_t pos_y = 0;

The clock displays ok when the hands move but when the second hand reaches 12, it goes back by 1 then advance forward again. I think there is some issue when the minute and second hand moves at the same time.

My test found that in addition to this problem, when the second hand turns to a certain angle, the entire screen is messed up. I don’t know what’s the cause?
Is there any additional modification to your test code?

uint16_t pos_x = 0;
uint16_t pos_y = 0;
hi its ok
i test clock in simulation is ok but on test my bord color is change i dont understand ?

I found the PNG image of watch_bg and converted it into a C array again. The test color is correct, but the pointer gets messed up when it rotates to a certain angle, I haven’t found the reason yet. I used the code under the latest Master branch.

static void update_time(lv_task_t *t)
{
 //  char strftime_buf[64];
    if(Second++>60)
    {
       Second=0;
        if(Minute++>60)
        {
           Minute=0;
           if(Hour++>12) Hour=0;
        }

    }
    if(lvHour !=NULL)
    {
       // Hour,Minute,Second;
        lv_img_set_angle(lvHour, Hour*300);
        lv_img_set_angle(lvMinute, Minute*60);
        lv_img_set_angle(t->user_data, Second*60);    
    }
}


void analog(void)
{
     lv_obj_t *central = lv_page_create(lv_scr_act(),NULL);
    //lv_obj_set_size(central, vres-2 , hres/2-2);
    lv_obj_set_size(central, 340 ,340);
   // lv_obj_set_pos(central,  0, 0);
    lv_page_set_scrlbar_mode(central, LV_SCRLBAR_MODE_OFF);
    lv_obj_align(central, NULL,LV_ALIGN_CENTER, 0, 0);

    lv_obj_t * img = lv_img_create(central,NULL);
    lv_img_set_src(img, &watch_bg);
    lv_obj_set_size(img, 320,320);
    lv_obj_align(img, NULL,LV_ALIGN_CENTER, 0, 0);
 
    lvHour = lv_img_create(central,NULL);
    lv_img_set_src( lvHour, &hour);
    lv_obj_align(lvHour, central,LV_ALIGN_CENTER,0 ,0);
    lv_img_set_angle(lvHour, 750);
    lv_img_set_pivot(lvHour, 15, 77);

    lvMinute = lv_img_create(central,NULL);
    lv_img_set_src( lvMinute, &minute);
    lv_obj_align(  lvMinute, central,LV_ALIGN_CENTER, 0, 0);
    lv_img_set_angle(lvMinute, 1950);
    lv_img_set_pivot(lvMinute, 11, 106);

    lvSecond = lv_img_create(central,NULL);
    lv_img_set_src( lvSecond, &second); 
    lv_obj_align(  lvSecond, central,LV_ALIGN_CENTER, 0, 0);
    lv_img_set_angle(lvSecond, 600);
    lv_img_set_pivot(lvSecond, 10, 118);

    lv_task_create(update_time, 1000, LV_TASK_PRIO_LOW, lvSecond);
}

webwxgetvideo.zip (132 Bytes)

The attached video is broken. It’s size is 0 bytes for me.

If you add the images you used I’d test your code.

A few days ago I fixed an issue related to rotating and zoomig large images. PLease try the latest master.

Attached the code clock app.zip (525.5 KB)


The blue marked area is not displayed properly.