|
| 1 | +--- |
| 2 | +title: Guide for Using LVGL With the Giga Display Shield |
| 3 | +description: 'Learn how to use LVGL with the GIGA display shield' |
| 4 | +author: Benjamin Dannegård |
| 5 | +tags: [Display, LVGL] |
| 6 | +--- |
| 7 | + |
| 8 | +## Introduction |
| 9 | + |
| 10 | +LVGL is a very powerful graphical framework that is compatible with the Giga Display Shield. It will allow you to put components on the screen like buttons, images, loading bars, sliders, checkboxes etc. It also allows you fully customize the screenspace on the display. This guide will go through the different components in detail so you can learn how to best implement it to your project. |
| 11 | + |
| 12 | +## Hardware & Software Needed |
| 13 | + |
| 14 | +- [GIGA R1 WiFi](/hardware/giga-r1). |
| 15 | +- [GIGA Display Shield]() |
| 16 | +- [Arduino IDE](https://www.arduino.cc/en/software) |
| 17 | +- [Arduino_H7_Video]() library. |
| 18 | +- [Arduino_GigaDisplayTouch]() library. |
| 19 | + |
| 20 | +## Downloading the Library and Core |
| 21 | + |
| 22 | +The Giga core includes a library that will help us handle the display, so make sure you have the latest version of the core. This library is called **Arduino_H7_Video**. |
| 23 | + |
| 24 | +In this guide, we will be using three different libraries: |
| 25 | +- **Arduino_H7_Video**, this one is bundled with the core, so make sure you have the latest version of the [Mbed core](https://github.com/arduino/ArduinoCore-mbed) |
| 26 | +- **Arduino_GigaDisplayTouch** |
| 27 | +- **lvgl** |
| 28 | + |
| 29 | +Open the library manager and install the latest version of **Arduino_GigaDisplayTouch** and **lvgl**. |
| 30 | + |
| 31 | +In the sketch include the libraries like this: |
| 32 | + |
| 33 | +```arduino |
| 34 | +#include "Arduino_H7_Video.h" |
| 35 | +#include "lvgl.h" |
| 36 | +
|
| 37 | +#include "Arduino_GigaDisplayTouch.h" |
| 38 | +``` |
| 39 | + |
| 40 | +## General Set Up |
| 41 | + |
| 42 | +### Display Shield Configuration |
| 43 | + |
| 44 | +We then will also need to define the screen we are using, do this by adding this line of code after the library inclusions. This function will use the **Arduino_H7_Video** library: |
| 45 | + |
| 46 | +```arduino |
| 47 | +Arduino_H7_Video Display(800, 480, GigaDisplayShield); |
| 48 | +```` |
| 49 | +
|
| 50 | +And if you want to use touch with your application call the following to use the **Arduino_GigaDisplayTouch** library: |
| 51 | +
|
| 52 | +```arduino |
| 53 | +Arduino_GigaDisplayTouch TouchDetector; |
| 54 | +``` |
| 55 | + |
| 56 | +Then we have to start these functions by putting these lines in the `setup()` function: |
| 57 | + |
| 58 | +```arduino |
| 59 | +Display.begin(); |
| 60 | +TouchDetector.begin(); |
| 61 | +``` |
| 62 | + |
| 63 | +### LVGL Screen Configuration |
| 64 | + |
| 65 | +When creating elements, information about the screen and placement needs to be provided. Lets create a pointer variable that can be used whenever the screenspace needs to be used. The pointer variable will be named `screen` and to use the current screen for the pointer use `lv_scr_act()`. |
| 66 | + |
| 67 | +```arduino |
| 68 | + lv_obj_t * screen = lv_obj_create(lv_scr_act()); |
| 69 | +``` |
| 70 | + |
| 71 | +The size of the screen space needs to be set for the pointer that is declared. The size can be set to anything within the displays size parameters. To make it easy we can use the entire size: |
| 72 | + |
| 73 | +```arduino |
| 74 | + lv_obj_set_size(screen, Display.width(), Display.height()); |
| 75 | +``` |
| 76 | + |
| 77 | +### Creating a Grid Layout |
| 78 | + |
| 79 | +Creating a grid that you can then fill with elements will consist of a defined column and row. This `col_dsc[] = {370, 370, LV_GRID_TEMPLATE_LAST};` will create two columns with 370 px width. To add more columns simply add more values, like so `col_dsc[] = {100, 100, 100, 100, LV_GRID_TEMPLATE_LAST};`, this will create four columns with 100 px width. The same logic is applied to the row definition. |
| 80 | + |
| 81 | +```arduino |
| 82 | + static lv_coord_t col_dsc[] = {370, 370, LV_GRID_TEMPLATE_LAST}; |
| 83 | + static lv_coord_t row_dsc[] = {215, 215, LV_GRID_TEMPLATE_LAST}; |
| 84 | +``` |
| 85 | + |
| 86 | +Then like before a pointer for the screenspace needs to be created. Here it will be called `grid`. |
| 87 | + |
| 88 | +```arduino |
| 89 | + lv_obj_t * grid = lv_obj_create(lv_scr_act()); |
| 90 | +``` |
| 91 | + |
| 92 | +To set the grid description that we defined before use: |
| 93 | + |
| 94 | +```arduino |
| 95 | + lv_obj_set_grid_dsc_array(grid, col_dsc, row_dsc); |
| 96 | +``` |
| 97 | + |
| 98 | +Now that the columns and rows have been defined the overall screen needs to be taken into account. This is achieved by using `lv_obj_set_size(grid, Display.width(), Display.height())`, to make it easy we will allow the `grid` to use the entire screen. |
| 99 | + |
| 100 | +```arduino |
| 101 | + lv_obj_set_size(grid, Display.width(), Display.height()); |
| 102 | +``` |
| 103 | + |
| 104 | +Then if we want to center the grid on the screen, simply use: |
| 105 | + |
| 106 | +```arduino |
| 107 | + lv_obj_center(grid); |
| 108 | +``` |
| 109 | + |
| 110 | +### Update Loop |
| 111 | + |
| 112 | +Include this in the loop of your sketch to make sure the LVGL engine is running and updating the screen. |
| 113 | + |
| 114 | +```arduino |
| 115 | +void loop() { |
| 116 | + lv_timer_handler(); |
| 117 | +} |
| 118 | +``` |
| 119 | + |
| 120 | +## Visual Elements |
| 121 | + |
| 122 | +### Image |
| 123 | + |
| 124 | +To display an image on the screen we first need to define what that image that should be. Take the desired image, convert it into the correct format and place the image in the same folder as the sketch. Now use `LV_IMG_DECLARE(filename);`. For example the image we use will be named `img_arduinologo`. |
| 125 | + |
| 126 | +```arduino |
| 127 | + LV_IMG_DECLARE(img_arduinologo); |
| 128 | +``` |
| 129 | + |
| 130 | +`obj` will be a pointer that will be used to hold the information about the screenspace information for the image. The `img1` pointer will be used for the elements of the image itself. |
| 131 | + |
| 132 | +```arduino |
| 133 | + lv_obj_t * obj; |
| 134 | + lv_obj_t * img1; |
| 135 | +``` |
| 136 | + |
| 137 | +Then create the image object with `obj` as a parent. Then we can link the image and image pointer together. |
| 138 | + |
| 139 | +```arduino |
| 140 | + img1 = lv_img_create(obj); |
| 141 | + lv_img_set_src(img1, &img_arduinologo); |
| 142 | +``` |
| 143 | + |
| 144 | +To make sure we see the image use the align function to make it centered. Then at last set the size of image with `lv_obj_set_size(img1, WIDTH, HEIGHT)`. |
| 145 | + |
| 146 | +```arduino |
| 147 | + lv_obj_align(img1, LV_ALIGN_CENTER, 0, 0); |
| 148 | + lv_obj_set_size(img1, 200, 150); |
| 149 | +``` |
| 150 | + |
| 151 | + |
| 152 | + |
| 153 | +## Functional Elements |
| 154 | + |
| 155 | +### Checkbox |
| 156 | + |
| 157 | +`obj` will be a pointer that will be used to hold the information about the screenspace information for the checkbox. The `checkbox` pointer will be used for the elements in the checkbox itself. |
| 158 | + |
| 159 | +```arduino |
| 160 | + lv_obj_t * obj; |
| 161 | + lv_obj_t * checkbox; |
| 162 | +``` |
| 163 | + |
| 164 | +Assign the screenspace info to `obj`, that was detailed in the #Screen configuration section. To create the checkbox object use `lv_checkbox_create(obj)` and assign it to a suitable variable, here we use the `checkbox` pointer. Next set the text that will appear next to the checkbox by using `lv_checkbox_set_text(checkbox, "Example");`, here `Example` will be printed next to the checkbox. |
| 165 | + |
| 166 | +```arduino |
| 167 | + obj = lv_obj_create(screen); |
| 168 | + checkbox = lv_checkbox_create(obj); |
| 169 | + lv_checkbox_set_text(checkbox, "Example"); |
| 170 | +``` |
| 171 | + |
| 172 | +The startup state of the checkbox can be set with `lv_obj_add_state()`. Where the object and state has to be specified: |
| 173 | + |
| 174 | +```arduino |
| 175 | + lv_obj_add_state(checkbox, LV_STATE_CHECKED); |
| 176 | +``` |
| 177 | + |
| 178 | + |
| 179 | + |
| 180 | +### Radio Button |
| 181 | + |
| 182 | +A radio button is created in the same way as a checkbox, but with some additional calls to change the style of the element. Adding these two style elements will allow for them to be added to the checkbox options. |
| 183 | + |
| 184 | +```arduino |
| 185 | + static lv_style_t style_radio; |
| 186 | + static lv_style_t style_radio_chk; |
| 187 | +``` |
| 188 | + |
| 189 | +Now initialize the style variable that was set in the previous step: |
| 190 | + |
| 191 | +```arduino |
| 192 | + lv_style_init(&style_radio); |
| 193 | +``` |
| 194 | + |
| 195 | +The size of the radio button is set with `lv_style_set_radius`. To make the radio button checkable use `lv_style_init(&style_radio_chk);`. And the color or background of the filled radio check can be set with `lv_style_set_bg_img_src`. |
| 196 | + |
| 197 | +```arduino |
| 198 | + lv_style_set_radius(&style_radio, LV_RADIUS_CIRCLE); |
| 199 | + lv_style_init(&style_radio_chk); |
| 200 | + lv_style_set_bg_img_src(&style_radio_chk, NULL); |
| 201 | +``` |
| 202 | + |
| 203 | + |
| 204 | + |
| 205 | +### Slider |
| 206 | + |
| 207 | +`obj` will be a pointer that will be used to hold the information about the screenspace information for the slider. The `slider` pointer will be used for the elements of the slider itself. The `label` pointer will be used for the text that will attached to the slider. |
| 208 | + |
| 209 | +```arduino |
| 210 | + lv_obj_t * obj; |
| 211 | + lv_obj_t * slider; |
| 212 | + lv_obj_t * label; |
| 213 | +``` |
| 214 | + |
| 215 | +Now the slider can be created with: |
| 216 | + |
| 217 | +```arduino |
| 218 | + slider = lv_slider_create(obj); |
| 219 | +``` |
| 220 | + |
| 221 | +Now the value of the slider needs to be defined, here the max value of the slider will be `75` and the animation will be default set as off as it is only needed when it is interacted with. |
| 222 | + |
| 223 | +```arduino |
| 224 | + lv_slider_set_value(slider, 75, LV_ANIM_OFF); |
| 225 | +``` |
| 226 | + |
| 227 | +If you want a label by your slider it can be created like you would create any other label. Using `lv_obj_align_to` allows for the label to be attached to the slider element. Changing the `LV_ALIGN_OUT_BOTTOM_MID` to determine where the text will be relative to the slider. You can find all the different options for alignment [here.](https://docs.lvgl.io/master/widgets/obj.html#coordinates) |
| 228 | + |
| 229 | +```arduino |
| 230 | + label = lv_label_create(obj); |
| 231 | + lv_label_set_text(label, "Drag me!"); |
| 232 | + lv_obj_align_to(label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); |
| 233 | +``` |
| 234 | + |
| 235 | + |
| 236 | + |
| 237 | +### Bar |
| 238 | + |
| 239 | +To make a bar, for example a loading bar, we need to include some animation. Lets first set up the slider itself and then move on to the animation. |
| 240 | + |
| 241 | +`obj` will be a pointer that will be used to hold the information about the screenspace information for the bar. The `bar` pointer will be used for the elements of the bar itself. |
| 242 | + |
| 243 | +```arduino |
| 244 | + lv_obj_t * obj; |
| 245 | + lv_obj_t * bar; |
| 246 | +``` |
| 247 | + |
| 248 | +Now the bar can be created with: |
| 249 | + |
| 250 | +```arduino |
| 251 | + bar = lv_bar_create(obj); |
| 252 | +``` |
| 253 | + |
| 254 | +Set the desired size of the bar with `lv_obj_set_size`. The value of the bar needs to be defined, here the max value of the bar will be `70` and the animation will be default set as off. |
| 255 | + |
| 256 | +```arduino |
| 257 | + lv_obj_set_size(bar, 200, 20); |
| 258 | + lv_bar_set_value(bar, 70, LV_ANIM_OFF); |
| 259 | +``` |
| 260 | + |
| 261 | +Now for the animation. First create the slider variable and initialize it: |
| 262 | + |
| 263 | +```arduino |
| 264 | + lv_anim_t animation; |
| 265 | + lv_anim_init(&animation); |
| 266 | +``` |
| 267 | + |
| 268 | +The animation time needs to be defined. It can be set with `lv_anim_set_time` which sets the duration of the animation and `lv_anim_set_playback_time` which makes the animation play back to when the forward direction is ready. The animation variable and the time in milliseconds has to be defined. |
| 269 | + |
| 270 | +```arduino |
| 271 | + lv_anim_set_time(&animation, 3000); |
| 272 | + lv_anim_set_playback_time(&animation, 3000); |
| 273 | +``` |
| 274 | + |
| 275 | +To connect the animation to the bar use: |
| 276 | + |
| 277 | +```arduino |
| 278 | + lv_anim_set_var(&animation, bar); |
| 279 | +``` |
| 280 | + |
| 281 | +The start and end values of the animation has to be set, here they are `0` and `100` respectively. |
| 282 | + |
| 283 | +```arduino |
| 284 | + lv_anim_set_values(&animation, 0, 100); |
| 285 | +``` |
| 286 | + |
| 287 | +How many times the animation will repeat can also be set, with this code the animation will repeat forever. And then at last we can create the animation with `lv_anim_start`. |
| 288 | + |
| 289 | +```arduino |
| 290 | + lv_anim_set_repeat_count(&animation, LV_ANIM_REPEAT_INFINITE); |
| 291 | + lv_anim_start(&animation); |
| 292 | +``` |
| 293 | + |
| 294 | +When the bar animates we can set it so that a separate callback function will be called. Here that function will be named `set_bar_val`. |
| 295 | + |
| 296 | +```arduino |
| 297 | + lv_anim_set_exec_cb(&animation, set_bar_val); |
| 298 | +``` |
| 299 | + |
| 300 | +In this separate callback function the bar value will be reset and the animation will be turned on again. |
| 301 | + |
| 302 | +```arduino |
| 303 | +static void set_bar_val(void * bar, int32_t val) { |
| 304 | + lv_bar_set_value((lv_obj_t *)bar, val, LV_ANIM_ON); |
| 305 | +} |
| 306 | +``` |
| 307 | + |
| 308 | + |
| 309 | + |
| 310 | +### Button |
| 311 | + |
| 312 | +A button will need two parts, the design of the button itself and the callback event function which determines what happens when the button is pressed. Lets start with designing the button. |
| 313 | + |
| 314 | + |
| 315 | +`obj` will be a pointer that will be used to hold the information about the screenspace information for the button. The `button` pointer will be used for the elements in the button itself. The `label` pointer will be used for the text that will be put on the button. |
| 316 | + |
| 317 | +```arduino |
| 318 | + lv_obj_t * obj; |
| 319 | + lv_obj_t * button; |
| 320 | + lv_obj_t * label; |
| 321 | +``` |
| 322 | + |
| 323 | +Now the button can be created with: |
| 324 | + |
| 325 | +```arduino |
| 326 | + button = lv_btn_create(obj); |
| 327 | +``` |
| 328 | + |
| 329 | +Set the size of the button with `lv_obj_set_size(btn, WIDTH, HEIGHT)`. For example: |
| 330 | + |
| 331 | +```arduino |
| 332 | + lv_obj_set_size(btn, 100, 40); |
| 333 | +``` |
| 334 | + |
| 335 | +Lets make the label on the button a child of the button by using `label = lv_label_create(button)`. Then the label can be set to whatever text it needs to be and center the text on top of the button so that it looks correct. The button will now say `Click me!` at the center of it. |
| 336 | + |
| 337 | +```arduino |
| 338 | + label = lv_label_create(button); |
| 339 | + lv_label_set_text(label, "Click me!"); |
| 340 | + lv_obj_center(label); |
| 341 | +``` |
| 342 | + |
| 343 | +When the button is clicked we need to assign it a function to execute, lets call this function `button_event_callback`. Assign it to the correct button and set it to be executed when the button is clicked with `LV_EVENT_CLICKED`. |
| 344 | + |
| 345 | +```arduino |
| 346 | + lv_obj_add_event_cb(button, button_event_callback, LV_EVENT_CLICKED, NULL); |
| 347 | +``` |
| 348 | + |
| 349 | +Now lets create the callback function that will be called when the button is clicked. By creating pointers that will point to the original elements we can change them easily in our function. This function will make it so that when the button is clicked the label text on the button will be changed to `Clicked!`. |
| 350 | + |
| 351 | + |
| 352 | +```arduino |
| 353 | +static void button_event_callback(lv_event_t * e) { |
| 354 | + lv_obj_t * button = lv_event_get_target(e); |
| 355 | + lv_obj_t * label = lv_obj_get_child(button, 0); |
| 356 | + lv_label_set_text_fmt(label, "Clicked!"); |
| 357 | +} |
| 358 | +``` |
| 359 | + |
| 360 | + |
| 361 | + |
| 362 | + |
| 363 | +## Conclusion |
| 364 | + |
| 365 | +This guide went through the building blocks of the different components that can be implemented with lvgl. To see these examples in a full running example sketch go to **File->Examples->Arduino_H7_Video->LVGLDemo**. |
| 366 | + |
| 367 | +This example sketch will show the different components in a 2x2 grid. |
| 368 | + |
| 369 | +## Next Step |
| 370 | +If you are interested in finding out how to use LVGL with the on-board IMU check out our [Orientation tutorial](). There are more features of the display shield to discover, for example using the camera connector. For more information on that have a look at our [Camera tutorial](). LVGL has a lot of customizability, if you are interested in playing around more with this, you can find many different examples on the official website for [LVGL](https://docs.lvgl.io/master/examples.html). These can easily be put in a sketch for the display shield just remember to use the display-specific configuration that was shown at the [start of this tutorial](#Display Shield Configuration). |
0 commit comments