Recently, I was idle and bored. I saw a tft color screen in hand and wanted to play with it. Since the display screen is used, it is naturally inseparable from ui design. lvgl is an embedded open-source graphics library with the characteristics of "Light" (lightweight) and "Versatile" (high availability). For me, the most difficult thing is that the initial environment has been built, and many learning enthusiasm has been gradually extinguished at the moment. But Kung Fu pays off. It took a day to finally learn a general idea.
Follow my steps and teach you to build LVGL development environment from 0 to 1!
1. Preparation
Hardware:
1. ESP32 development version
2. 1.44TFT color screen ST7735S driver[ TaoBao ](the student party can't afford expensive color screens, which are similar to other color screens. The official has built-in many driver libraries. Identify the driver of your own screen and modify it slightly)
Knowledge reserve:
1. LVGL official website: https://lvgl.io/
2. LVGL documents:[ Official website document ](scientific Internet access may be required)[ github]
3. Other recommended documents
- Baiwen tutorial: http://lvgl.100ask.org/8.1/intro/index.html
Library file download
A complete LVGL project file. Its directory contains at least the following library files
Library file | explain | link |
---|---|---|
lvgl | lvgl main library | https://github.com/lvgl/lvgl |
lv_demos | lvgl official sample library | https://github.com/lvgl/lv_demos |
TFT_eSPI | tft color screen driver library | https://github.com/Bodmer/TFT_eSPI |
TFT_Touch | tft color touch screen driver library | https://github.com/Bodmer/TFT_Touch |
Download these libraries locally for backup!
2. Project creation (based on VScode+PlatformIO)
I use the VScode+PlatformIO environment here (see for the building tutorial) entrance ), developed with arduino IDE.
1. Create Platform project
On platform Add monitor to ini configuration file_ Speed = 115200. Its function is to modify the serial port frequency. The lvgl official routine uses the frequency of 115200
2. Add a library file to the platform project
Description: lvgl, TFT_eSPI,TFT_Touch can be downloaded directly on the platform, except Lv_ Except demos, it needs to be added manually. Therefore, for the sake of unification, I will add it manually.
Right click Open pio\libdeps\esp32doit-devkit-v1 from Explorer and add the required library files in this directory
Open vscode/c_cpp_properties.json to add the path of the new library file
Make a copy of the following
Note: no error is correct. Check whether the path marked wrong is correct. If the configuration is not successful here, the error XX will be reported in the later compilation The H file cannot be found. 99% of the reasons are here. Because it is added manually, platform Ini configuration file does not need to add the imported library file, but lib should be added_ DEPs field (left blank), otherwise the above json file will be automatically modified during compilation
3. Configure color screen file
Open pio\build\esp32doit-devkit-v1\TFT_eSPI\User_Setup_Select.h. modify the configuration document price
You can only uncomment one configuration file. If you uncomment more than one, an error will be reported. The official has built-in more than 60 common screen driven configuration files. Of course, you can also set a configuration file yourself, that is/ User_Setup.h configuration file, uncomment and configure relevant options under this file,
Since there are already ST7735 configuration files here, I will directly use the official one.
get into. pio\build\esp32doit-devkit-v1\TFT_eSPI\User_Setups\Setup7_ST7735_128x128.h file, slightly modified
Note: all configuration files must be modified according to the principle of non essential and do not change if they do not know their role, otherwise they will suffer a lot of losses (personal experience)
An ESP32 pin diagram is attached here
4. Test whether the color screen is available
After the above modifications, you can test whether the color screen is configured normally. After connecting the cables in sequence, open it \src\main.cpp file, add the official color test code, in pio\build\esp32doit-devkit-v1\TFT_eSPI\examples\Test and diagnostics\Colour_Test\Colour_Test.ino, as follows
#include <SPI.h> #include <TFT_eSPI.h> // Hardware-specific library TFT_eSPI tft = TFT_eSPI(); // Invoke custom library void setup(void) { tft.init(); tft.fillScreen(TFT_BLACK); // Set "cursor" at top left corner of display (0,0) and select font 4 tft.setCursor(0, 0, 4); // Set the font colour to be white with a black background tft.setTextColor(TFT_WHITE, TFT_BLACK); // We can now plot text on screen using the "print" class tft.println("Intialised default\n"); tft.println("White text"); tft.setTextColor(TFT_RED, TFT_BLACK); tft.println("Red text"); tft.setTextColor(TFT_GREEN, TFT_BLACK); tft.println("Green text"); tft.setTextColor(TFT_BLUE, TFT_BLACK); tft.println("Blue text"); delay(5000); } void loop() { // Set text color and print tft.invertDisplay( false ); // Where i is true or false tft.fillScreen(TFT_BLACK); tft.setCursor(0, 0, 4); tft.setTextColor(TFT_WHITE, TFT_BLACK); tft.println("Invert OFF\n"); tft.println("White text"); tft.setTextColor(TFT_RED, TFT_BLACK); tft.println("Red text"); tft.setTextColor(TFT_GREEN, TFT_BLACK); tft.println("Green text"); tft.setTextColor(TFT_BLUE, TFT_BLACK); tft.println("Blue text"); delay(5000); // Binary inversion of colours // Invert screen color tft.invertDisplay( true ); // Where i is true or false tft.fillScreen(TFT_BLACK); tft.setCursor(0, 0, 4); // Set text color and print tft.setTextColor(TFT_WHITE, TFT_BLACK); tft.println("Invert ON\n"); tft.println("White text"); tft.setTextColor(TFT_RED, TFT_BLACK); tft.println("Red text"); tft.setTextColor(TFT_GREEN, TFT_BLACK); tft.println("Green text"); tft.setTextColor(TFT_BLUE, TFT_BLACK); tft.println("Blue text"); delay(5000); }
The purpose of each function of the code is well understood. After uploading to the ESP32 development version, check whether the color of the text is consistent with the color described in the text. If not, see the description on the first two figures. If the color screen is not configured successfully, the lvgl behind will naturally not be displayed
5. Configure LVGL
Same as TFT_eSPI library, lvgl also has configuration files to modify
Open pio\libdeps\esp32doit-devkit-v1\lvgl\lv_conf_template.h. Copy a file to the same directory and rename it lv_conf.h
Change 0 after if to 1
Connect LV_ TICK_ Modify custom to 1
Other configurations are modified according to their own needs
6. Test LVGL case
Open pio\libdeps\esp32doit-devkit-v1\lvgl\examples\arduino\LVGL_Arduino\LVGL_Arduino.ino file, copy the code to / SRC / main In CPP, the official case includes touch function test, but since my color screen has no touch function, the code needs to be modified as follows
#include <lvgl.h> #include <TFT_eSPI.h> /*If you want to use the LVGL examples, make sure to install the lv_examples Arduino library and uncomment the following line. #include <lv_examples.h> */ #include <lv_demo.h> TFT_eSPI tft = TFT_eSPI(); /* TFT instance */ /*The width and height of the screen are modified here*/ static const uint32_t screenWidth = 128; static const uint32_t screenHeight = 128; static lv_disp_draw_buf_t draw_buf; static lv_color_t buf[ screenWidth * 10 ]; //The function that is invoked after logging is enabled, enabling lvgl_ to modify the function. Corresponding functions of conf.h #if LV_USE_LOG != 0 /* Serial debugging */ void my_print( lv_log_level_t level, const char * file, uint32_t line, const char * fn_name, const char * dsc ) { Serial.printf( "%s(%s)@%d->%s\r\n", file, fn_name, line, dsc ); Serial.flush(); } #endif /* Refresh screen */ void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p ) { 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 * )&color_p->full, w * h, true ); tft.endWrite(); lv_disp_flush_ready( disp ); } void setup() { Serial.begin( 115200 ); /* prepare for possible serial debug */ Serial.println( "Hello Arduino! (V8.0.X)" ); Serial.println( "I am LVGL_Arduino" ); lv_init(); #if LV_USE_LOG != 0 lv_log_register_print_cb( my_print ); /* register print function for debugging */ #endif tft.begin(); /* TFT init */ tft.setRotation( 3 ); /* Rotate the screen, n * 90 degrees, 3 = 270 degrees*/ // Create a buffer of screen width * 10 lv_disp_draw_buf_init( &draw_buf, buf, NULL, screenWidth * 10 ); /*Novice screen*/ static lv_disp_drv_t disp_drv; lv_disp_drv_init( &disp_drv ); /*Change the following line to your display resolution*/ disp_drv.hor_res = screenWidth; disp_drv.ver_res = screenHeight; disp_drv.flush_cb = my_disp_flush; disp_drv.draw_buf = &draw_buf; lv_disp_drv_register( &disp_drv ); /*Novice input device*/ static lv_indev_drv_t indev_drv; lv_indev_drv_init( &indev_drv ); indev_drv.type = LV_INDEV_TYPE_POINTER; lv_indev_drv_register( &indev_drv ); #if 0 // Uncomment displays text on the screen /* Create simple label */ lv_obj_t *label = lv_label_create( lv_scr_act() ); lv_label_set_text( label, "Hello Arduino! (V8.0.X)" ); lv_obj_align( label, LV_ALIGN_CENTER, 0, 0 ); #else // Uncomment enables the corresponding case lv_demo_widgets(); // OK // lv_demo_benchmark(); // OK // lv_demo_keypad_encoder(); // works, but I haven't an encoder // lv_demo_music(); // NOK // lv_demo_printer(); // lv_demo_stress(); // seems to be OK #endif Serial.println( "Setup done" ); } void loop() { lv_timer_handler(); /* Let lvgl handle some corresponding events in the loop */ delay( 5 ); }
The screen is too small to put down the whole case, hhh
7.next?
Since it is UI design, how to design a UI? This requires learning the official components of lvgl, such as text, slider, input box, etc. this development method may be similar to the pyqt5 I learned before. Select the building blocks that meet your own needs from different components and finally build a fortress. Of course, you can also transplant them from other people's lvgl UI. The UI parts of lvgl developed in C language are common, A simple UI example is given below
//Create a tag, like a Sketchpad (lv_src_act() to get the currently active screen) lv_obj_t *label = lv_label_create( lv_scr_act() ); // Write words on the drawing board lv_label_set_text( label, "Hello World!I'm fine!" ); // Set the alignment on the palette, that is, the layout lv_obj_align( label, LV_ALIGN_CENTER, 0, 0 );
How to use the UI when it is available?
In fact, the code in the above case is common to all arduino development boards. It is basically a set of templates. Of course, deeper use needs to be explored slowly
Don't want trouble? Of course, there is also a way to download the whole project file (including the simulator project), which can be downloaded and imported into the platform project
3. Use of lvgl simulator (based on VS2019)
Isn't it troublesome to brush firmware every time you design a UI? Therefore, with the help of LVGL simulator, you can directly view your designed UI on the computer. After meeting your expectations, you can transplant it to Arduino project.
Because the article is too long, it will be introduced in the next blog - >[ Portal]