The Sunday Blog: Understanding and Customizing HMI components
Part 6: The timer component and animated GIFs
Today, we’ll get more acquainted with the Timer component and we’ll then use it to display an animated GIF. Thus, we’ll have to learn how an animated GIF works and we have to teach our NEXTION HMI to display it.
The Timer component
To prevent any misconception, you should know at first that the timer component is implemented in the Nextion firmware, and thus, it is running on single threaded software. Don’t expect it to interrupt your Nextion code which makes sure that your timer event code will always be executed from A to Z before the timer fires again, even if that means that the real timer interval might become longer that you initially set it. Heavy serial communication might also delay the time’s firing. What might be interrupted, though, are secondary processes like screen or component refreshing or drawing which are triggered but not directly executed by the command processor. Thus, always make sure to terminate your event code with a doevents command if there is refreshing or drawing invoked, so that these processes can come to their end before a new drawing or refreshing is started.
But when it fires and while nothing is in the command buffer, it will execute the timer event code. And that’s what we’ll use for displaying our animated GIF.
What is an animated GIF?
An animated GIF file is a container for a series of pictures which are to be displayed consecutively. Displaying an animated GIF means displaying the first picture in the container, wait a few milliseconds, display the second picture, wait a few milliseconds, and so on. After displaying the last picture in the series, the whole loop starts again. Theoretically, a gif file can even handle different delays between single pictures or frames, similar to the PowerPoint timer, but we’ll leave that academic case out for the moment and simply concentrate on displaying a fluid animation. That means cycling through the single frames and display them consecutively with a delay in-between which is short enough to give the desired impression.
How to display an animated GIF on a Nextion HMI
There could be a component to handle GIF containers on the fly. We don’t have that in the firmware of the standard (T) and enhance (K) series because it’s a complex task, eating up too much of the precious system memory. Thus, we’ll have to unpack that container and repack it in a format which our NEXTION HMI can easily handle:
After finding and downloading a nice animated gif, we use a free online tool to unpack it and to extract the single frames which is only a question of seconds. For our project, I found that spinner in 142 x 142px format with 12 frames. Thus, I ended up with 12 single png pictures which now have to be reassembled in a picture resource which our NEXTION can handle. Thus, I imported these 12 png pics as different layers in my graphic program (The Gimp, but Photoshop would also have done the job) and arranged them side by side, like tiles in a 1704px (12 x 142) wide and 142px heigh picture:
Since the program was already open, I created in a second step a 240 x 400px picture with the same background color as a page background, putting all the static text on it to further save on system resources:
As you can see, I used guide lines to determine the centered 142 x 142px area for the future spinner within the upper 240 x 240px screen area, and to place the text box centered in the lower 240 x 160px area. Everything which is already done in graphics will demand less effort and resources during the GUI design in the Nextion editor. Exporting both pictures as bmp files in RGB565 encoding and importing these in the Nextion editor is then trivial.
Creating a custom component in the Nextion Editor
We care about page0 first, set the sta attribute to image and the pic attribute to the number of our imported background pic resource. That’s the easiest part.
Then, we’ll have to think about our custom component, the spinner. Knowing that every component can basically be reproduced with GUI commands, why shouldn’t that be possible for custom components? Our spinner needs a few variables to define its x, y, w, and h attributes like for any other visible component. Furthermore, we need to know from which picture resource id it will have to crop the different tiles consecutively, we need to know the width of that container in order to prevent cropping beyond its boundaries and we need a pointer for the x coordinate of the next tile to pick. That’s what we do in the program.s file, and with the page 0 startup command a two liner:
int spinner_x=49,spinner_y=49,spinner_w=142,spinner_h=142,frapic_id=1,frapic_w=1704,frame_ptr=0 // define the variables for our custom component page 0 //Power on start page 0
Now, we need a timer which will care of picking or cropping and drawing one tile after the other from our picture resource onto the screen, 80ms as a tim attribute is a reasonable value for a fluid animation.
Finally the timer’s event code which has several duties:
– First, using the xpic command, pick the tile where the x coordinate is equal to frame_ptr and the y coordinate is 0 from the picture resource whose id is frapic_id, and draw it on the screen at (spinner_x,spinner_y) with the height spinner_h and the width spinner_w.
– Second, move the frame_ptr by adding spinner_w to point towards the beginning of the next tile. Rollover and respecting the boundaries is done using a modulo operation with frapic_w.
– Third, the famous doevents command to make sure that the drawing of the current tile will be accomplished before the drawing of the next one starts.
And that’s it already!
xpic spinner_x,spinner_y,spinner_w,spinner_h,frame_ptr,0,frapic_id // draw the current frame frame_ptr+=spinner_w%frapic_w // advance the pointer to the next frame in the pic resource and roll over when reaching the resource's end doevents // finish drawing before next timer event triggers
So, with 5 lines of code, a page and a timer (consuming just 52 bytes of RAM), and two well prepared picture resources, we can fluidly display an animated gif!
As always, the full project hmi file including all needed resources can be downloaded from the Nextion forums. Have fun!