[RVB2601 Creative Application Development] Environmental Monitoring Terminal 03-Using LVGL to Design the Interface
[Copy link]
This article introduces how to design an interface on the OLED display screen of the RVB2601 development board based on the LVGL library.
The RVB2601 development board has a built-in monochrome OLED display with a resolution of 128*64, and the open source LVGL GUI library has been ported based on this platform. I have never used the LVGL GUI library before, so I just wanted to give it a try, so I searched for tutorials online. I happened to find a user manual translated by someone else, which is attached to this article. Students who need it can download it.
First, design a draft of the interface. As shown in the figure below, I plan to display 5 lines of information on the screen. The first line, the title, can be displayed directly using labels. The second line, the temperature, the left field does not need to be updated, and the right field needs to be refreshed regularly, and all are displayed using labels. The third and fourth lines are humidity and noise levels, respectively, and the same method is used to display temperature. The fifth line plans to make an indicator bar to dynamically indicate the real-time amplitude of the noise, so that it is more intuitive to view.
Figure 1. Interface sketch
I encountered various problems during the actual design. The first was how to display Chinese characters. After searching, I learned that I had to make and add built-in fonts myself. I looked at several tutorials and found that they were very complicated. I was lazy and decided to skip the Chinese display and use English instead.
The next problem is that the default English font is "LV_FONT_MONTSERRAT_14", which is relatively large. If it is displayed in 5 lines, it looks too crowded. By changing the configuration item, the font "LV_FONT_MONTSERRAT_12" is relatively better. I also tried to change it to a smaller font, but it was a bit horrible and I couldn't even distinguish it. It looked a bit like the Martian text in the blockbuster movies. The specific modification method is as shown in the figure below.
Figure 2: Modify font
Next, we will actually program to display text. When we were doing the title display, we saw that LVGL supports scrolling display. In order to reflect our learning results, we changed the original two-word title into a sentence and let it scroll at the top, which is more fun. For the specific setting method, please refer to the code below.
When setting the temperature display, it is necessary to display floating point numbers. I wrote the code in the conventional way and found that it could not be displayed normally. Then I checked the information and found that it was set to not support floating point mode by default in order to improve efficiency. I originally wanted to check the manual to change it to support floating point mode, but later I saw someone used a better method to solve it. That is, format the floating point number into a string first, and then display it as a string. I followed this method and successfully solved the problem. For specific methods, refer to the following code.
The last thing to be implemented is the noise indicator bar. After repeatedly consulting the manual, I finally decided to use the progress bar "LV_BAR" control design. After directly following the simple routine in the manual, I found that both ends were rounded, which was not the type I liked. Then I searched a lot, and the Internet is a good thing. I found a solution again. Friends who are interested can refer to the following post.
https://www.csdn.net/tags/MtTaEg4sMjI1OTA0LWJsb2cO0O0O.html
After repeated modifications and debugging, I finally built the interface framework, and the display effect is as shown below.
Figure 3: Interface framework
The entire framework initialization code is as follows.
lv_obj_t *pGui_label_temp;
lv_obj_t *pGui_label_humi;
lv_obj_t *pGui_label_noise;
lv_obj_t *pGui_bar_noise;
static void gui_label_create(void)
{
char cdata[10] = { 0 };
lv_obj_t *p_label_title = lv_label_create(lv_scr_act(), NULL);
lv_label_set_long_mode(p_label_title, LV_LABEL_LONG_SROLL_CIRC); /*滚动显示*/
lv_obj_set_width(p_label_title, 160);
lv_label_set_text(p_label_title, "Hello EEWOLRD,This is a Environment Monitor based on RVB2601.");
lv_obj_align(p_label_title, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);
lv_obj_t *p_label_temp = lv_label_create(lv_scr_act(), NULL);
lv_label_set_align(p_label_temp, LV_LABEL_ALIGN_LEFT);
lv_obj_set_pos(p_label_temp, 0, 12);
lv_obj_set_size(p_label_temp, 128, 64);
lv_label_set_text(p_label_temp, "Temperature:");
lv_obj_t *p_label_humi = lv_label_create(lv_scr_act(), NULL);
lv_label_set_align(p_label_humi, LV_LABEL_ALIGN_LEFT);
lv_obj_set_pos(p_label_humi, 0, 24);
lv_obj_set_size(p_label_humi, 128, 64);
lv_label_set_text(p_label_humi, "Humidity:");
lv_obj_t *p_label_noise = lv_label_create(lv_scr_act(), NULL);
lv_label_set_align(p_label_noise, LV_LABEL_ALIGN_LEFT);
lv_obj_set_pos(p_label_noise, 0, 36);
lv_obj_set_size(p_label_noise, 128, 64);
lv_label_set_text(p_label_noise, "Noise level:");
pGui_bar_noise = lv_bar_create(lv_scr_act(), NULL);
lv_obj_set_size(pGui_bar_noise, 120, 10);
lv_obj_align(pGui_bar_noise, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, -1);
lv_bar_set_anim_time(pGui_bar_noise, 200);
lv_bar_set_range(pGui_bar_noise, 1, 100);
lv_bar_set_type(pGui_bar_noise, LV_BAR_TYPE_NORMAL);
lv_bar_set_value(pGui_bar_noise, 50, LV_ANIM_OFF);
lv_obj_set_style_local_radius(pGui_bar_noise, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, 0); /*Add a local style*/
lv_obj_set_style_local_bg_color(pGui_bar_noise, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_BLACK);
static lv_style_t style;
lv_style_init(&style);
lv_style_set_radius(&style, LV_STATE_DEFAULT, 0);//这里的参数0意思是进度条的指示器样式弧度为零,也就是直角。
lv_style_set_bg_color(&style, LV_STATE_DEFAULT, LV_COLOR_WHITE);//进度条背景颜色
lv_style_set_border_width(&style, LV_STATE_DEFAULT, 1); //进度条背景线条宽度
lv_style_set_border_color(&style, LV_STATE_DEFAULT, LV_COLOR_BLACK);//颜色
lv_style_set_pad_top(&style, LV_STATE_DEFAULT, 2);//指示器到背景四周的距离
lv_style_set_pad_bottom(&style, LV_STATE_DEFAULT, 2);
lv_style_set_pad_left(&style, LV_STATE_DEFAULT, 2);
lv_style_set_pad_right(&style, LV_STATE_DEFAULT, 2);
lv_obj_add_style(pGui_bar_noise, LV_BAR_TYPE_NORMAL, &style);//样式加到进度条中
//https://www.csdn.net/tags/MtTaEg4sMjI1OTA0LWJsb2cO0O0O.html
pGui_label_temp = lv_label_create(lv_scr_act(), NULL);
lv_label_set_align(pGui_label_temp, LV_LABEL_ALIGN_RIGHT);
lv_obj_set_pos(pGui_label_temp, 90, 12);
lv_obj_set_size(pGui_label_temp, 128, 64);
sprintf((char*)cdata, "%.1fC", 25.68);//格式化输出 浮点数转成字符串输出
lv_label_set_text_fmt(pGui_label_temp,"%s", (const char*)cdata);
pGui_label_humi = lv_label_create(lv_scr_act(), NULL);
lv_label_set_align(pGui_label_humi, LV_LABEL_ALIGN_RIGHT);
lv_obj_set_pos(pGui_label_humi, 90, 24);
lv_obj_set_size(pGui_label_humi, 128, 64);
sprintf((char*)cdata, "%.1f%%", 55.8);//格式化输出 浮点数转成字符串输出
lv_label_set_text_fmt(pGui_label_humi,"%s", (const char*)cdata);
pGui_label_noise = lv_label_create(lv_scr_act(), NULL);
lv_label_set_align(pGui_label_noise, LV_LABEL_ALIGN_RIGHT);
lv_obj_set_pos(pGui_label_noise, 90, 36);
lv_obj_set_size(pGui_label_noise, 128, 64);
lv_label_set_text_fmt(pGui_label_noise, "%ddB", 55);
}
static void gui_lvgl_task(void *arg)
{
lv_init();
/*Initialize for LittlevGL*/
oled_init();
/*Select display 1*/
// demo_create();
gui_label_create();
while (1) {
/* Periodically call the lv_task handler.
* It could be done in a timer interrupt or an OS task too.*/
lv_task_handler();
aos_msleep(5);
lv_tick_inc(1);
}
}
Since I haven't adjusted the detection procedures for each parameter yet, I have to create a task first, create simulated data, and make the interface move first to show the effect. The code is as follows.
struct Result_S
{
float temp;
float humi;
int noise;
}res_data;
static void res_update_task(void *arg)
{
int num_temp = 200;
char cdata[10] = { 0 };
while(1)
{
num_temp++;
if(num_temp>1000)
{
num_temp = 200;
}
res_data.temp = num_temp / 20.0;
res_data.humi = num_temp / 10.0;
res_data.noise = num_temp % 99;
sprintf((char*)cdata, "%.1fC", res_data.temp);//格式化输出 浮点数转成字符串输出
lv_label_set_text_fmt(pGui_label_temp,"%s", (const char*)cdata);
sprintf((char*)cdata, "%.1f%%", res_data.humi);//格式化输出 浮点数转成字符串输出
lv_label_set_text_fmt(pGui_label_humi,"%s", (const char*)cdata);
lv_label_set_text_fmt(pGui_label_noise, "%ddB", res_data.noise);
lv_bar_set_value(pGui_bar_noise, res_data.noise+1, LV_ANIM_OFF);
aos_msleep(500);
}
}
The dynamic effect of the interface is as follows. When the detection parameters are adjusted in the future, the results will be assigned to the corresponding variables to complete the formal interface display.
Figure 4: Dynamic display effect
At this point, the interface display design of the environmental monitoring terminal is completed. Through this practice, we have a basic understanding of the process of using LVGL to design UI, which adds a new idea for the subsequent UI design.
LVGL Documentation.zip
(5.34 MB, downloads: 12)
|