1. 项目介绍
项目采用基于ESP32主控制器的FireBeetle 开发板,采集VL53 TOF测距模块,将采集结果,通过LVGL显示到屏幕上,开发环境为arduino。
ESP32 微控制器是一款集成有 2.4 GHz Wi-Fi 和蓝牙 4.0 双模的物联网芯片方案,采用台积电 (TSMC) 超低功耗的 40 纳米工艺代工。片上集成有天线开关、射频巴伦、功率放大器、接收低噪声放大器、滤波器、电源管理模块等功能,仅需要 20 余个外围元件,就可以适配大量的物联网场景。
VL53L3CX是意法半导体新推出的一款激光测距传感器,搭配ST的第三代FlightSense算法,在提高了检测精度的同时,测距范围覆盖了25mm到3000mm,还具有自动污迹校正,抗玻璃盖板串扰等特性。VL53L3CX借助算法和巧妙的模块构造,VL53L3CX还能够通过深度了解来检测视场内的不同对象。
2. 各功能对应的主要代码片段及说明
系统GUI主要分为三个部分,上电后首先显示FUNPACK的log,然后显示主界面,主界面有三个按钮组成,分别为测量数据显示,wifi信息显示,SD卡信息显示。通过按钮可选择相应界面查看详细数据信息。
系统上电后,通过动画方式,显示funpack的logo。
void boot_page_run(void)
{
lv_obj_t *scr = lv_scr_act();
lv_obj_clean(scr);
lv_obj_remove_style_all(scr);
lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0);
lv_obj_set_style_bg_color(scr, lv_color_white(), 0);
lv_obj_t *image = lv_img_create(scr);
lv_img_set_src(image, &funpack_img);
lv_obj_align(image, LV_ALIGN_TOP_MID, 0, 0);
obj_set_anim(image, -250, 90, 800, 1000, (lv_anim_exec_xcb_t)anim_set_y_cb, (lv_anim_ready_cb_t)anim_ready_cb, lv_anim_path_bounce);
}
系统主界面部分,有三个按钮组成,分别为测量数据显示,wifi信息显示,sd卡信息显示。当开机动画运行完毕后,会自动切换至系统主界面,同时,界面的各个组件也加入了动画功能。
void main_menu_page(uint32_t delay)
{
lv_group_t *group = get_group();
//LV_FONT_DECLARE(my_font_chinese_18);
/* create wifi menu btn */
wifi_menu_btn_obj = lv_btn_create(bg_cont_obj);
lv_obj_remove_style_all(wifi_menu_btn_obj);
lv_obj_set_size(wifi_menu_btn_obj, 100, 90);
lv_obj_set_style_radius(wifi_menu_btn_obj, 10, 0);
lv_obj_set_style_bg_color(wifi_menu_btn_obj, lv_color_hex(MY_COLOR_DODGER_BLUE), 0);
lv_obj_set_style_bg_opa(wifi_menu_btn_obj, LV_OPA_COVER, 0);
lv_obj_set_style_bg_color(wifi_menu_btn_obj, lv_color_hex(MY_COLOR_DODGER_BLUE), LV_STATE_FOCUSED);
lv_obj_set_style_bg_opa(wifi_menu_btn_obj, LV_OPA_80, LV_STATE_FOCUSED);
lv_obj_set_style_bg_opa(wifi_menu_btn_obj, LV_OPA_60, LV_STATE_PRESSED);
lv_obj_align(wifi_menu_btn_obj, LV_ALIGN_BOTTOM_LEFT, 5, -25);
lv_obj_t *wifi_menu_icon_label = lv_label_create(wifi_menu_btn_obj);
lv_label_set_text(wifi_menu_icon_label, LV_SYMBOL_WIFI);
lv_obj_set_style_text_font(wifi_menu_icon_label, &lv_font_montserrat_14, 0);
lv_obj_set_style_text_color(wifi_menu_icon_label, lv_color_white(), 0);
lv_obj_center(wifi_menu_icon_label);
lv_obj_add_event_cb(wifi_menu_btn_obj, wifi_menu_btn_event_cb, LV_EVENT_CLICKED, NULL);
/* create sdcard menu btn */
sdcard_menu_btn_obj = lv_btn_create(bg_cont_obj);
lv_obj_remove_style_all(sdcard_menu_btn_obj);
lv_obj_set_size(sdcard_menu_btn_obj, 100, 90);
lv_obj_set_style_radius(sdcard_menu_btn_obj, 10, 0);
lv_obj_set_style_bg_color(sdcard_menu_btn_obj, lv_color_hex(MY_COLOR_DODGER_BLUE), 0);
lv_obj_set_style_bg_opa(sdcard_menu_btn_obj, LV_OPA_COVER, 0);
lv_obj_set_style_bg_color(sdcard_menu_btn_obj, lv_color_hex(MY_COLOR_DODGER_BLUE), LV_STATE_FOCUSED);
lv_obj_set_style_bg_opa(sdcard_menu_btn_obj, LV_OPA_80, LV_STATE_FOCUSED);
lv_obj_set_style_bg_opa(sdcard_menu_btn_obj, LV_OPA_60, LV_STATE_PRESSED);
lv_obj_align(sdcard_menu_btn_obj, LV_ALIGN_BOTTOM_RIGHT, -5, -25);
lv_obj_t *sdcard_menu_icon_label = lv_label_create(sdcard_menu_btn_obj);
lv_label_set_text(sdcard_menu_icon_label, LV_SYMBOL_SD_CARD);
lv_obj_set_style_text_font(sdcard_menu_icon_label, &lv_font_montserrat_14, 0);
lv_obj_set_style_text_color(sdcard_menu_icon_label, lv_color_white(), 0);
lv_obj_center(sdcard_menu_icon_label);
lv_obj_add_event_cb(sdcard_menu_btn_obj, sdcard_menu_btn_event_cb, LV_EVENT_CLICKED, NULL);
/* create terminal menu cont */
ui_memory_menu_btn_obj = lv_btn_create(bg_cont_obj);
lv_obj_remove_style_all(ui_memory_menu_btn_obj);
lv_obj_set_size(ui_memory_menu_btn_obj, 230, 90);
lv_obj_set_style_radius(ui_memory_menu_btn_obj, 10, 0);
lv_obj_set_style_bg_color(ui_memory_menu_btn_obj, lv_color_hex(MY_COLOR_SPRING_GREEN), 0);
lv_obj_set_style_bg_opa(ui_memory_menu_btn_obj, LV_OPA_COVER, 0);
lv_obj_set_style_bg_color(ui_memory_menu_btn_obj, lv_color_hex(MY_COLOR_SPRING_GREEN), LV_STATE_FOCUSED);
lv_obj_set_style_bg_opa(ui_memory_menu_btn_obj, LV_OPA_80, LV_STATE_FOCUSED);
lv_obj_set_style_bg_opa(ui_memory_menu_btn_obj, LV_OPA_60, LV_STATE_PRESSED);
lv_obj_align_to(ui_memory_menu_btn_obj, wifi_menu_btn_obj, LV_ALIGN_OUT_TOP_LEFT, 0, -15);
lv_obj_t *terminal_text_label = lv_label_create(ui_memory_menu_btn_obj);
lv_label_set_text(terminal_text_label, "TOF VL53");
//lv_obj_set_style_text_font(terminal_text_label, &my_font_chinese_18, 0);
lv_obj_set_style_text_opa(terminal_text_label, LV_OPA_COVER, 0);
lv_obj_set_style_text_color(terminal_text_label, lv_color_white(), 0);
lv_obj_center(terminal_text_label);
lv_obj_add_event_cb(ui_memory_menu_btn_obj, ui_memory_menu_btn_event_cb, LV_EVENT_CLICKED, NULL);
/* astronaut cont */
// astronaut_cont = lv_obj_create(bg_cont_obj);
// lv_obj_remove_style_all(astronaut_cont);
// lv_obj_set_size(astronaut_cont, 150, 150);
// lv_obj_set_style_radius(astronaut_cont, 75, 0);
// lv_obj_set_style_bg_color(astronaut_cont, lv_color_black(), 0);
// lv_obj_set_style_bg_opa(astronaut_cont, LV_OPA_0, 0);
// lv_obj_align(astronaut_cont, LV_ALIGN_TOP_MID, 0, 10);
/* 添加组 */
lv_group_add_obj(group, ui_memory_menu_btn_obj);
lv_group_add_obj(group, wifi_menu_btn_obj);
lv_group_add_obj(group, sdcard_menu_btn_obj);
/* 页面入场动画 */
// astronaut_anim();
main_menu_page_anim_in(delay);
}
测量数据显示部分,VL53最大测量距离为3000mm,数据显示部分会将数据以2种方式进行显示,一种为百分比形式,根据测量距离与最大距离的比值进行显示,第二种为显示实际测量的结果数据。
void vl53_page(uint32_t delay)
{
lv_group_t *group = get_group();
LV_FONT_DECLARE(my_font_chinese_18);
/* retrun btn */
return_btn = lv_btn_create(bg_cont_obj);
lv_obj_remove_style_all(return_btn);
lv_obj_set_size(return_btn, 30, 30);
lv_obj_set_style_radius(return_btn, 15, 0);
lv_obj_set_style_bg_color(return_btn, lv_color_white(), LV_STATE_PRESSED);
lv_obj_set_style_bg_opa(return_btn, LV_OPA_30, LV_STATE_PRESSED);
lv_obj_align(return_btn, LV_ALIGN_TOP_LEFT, 5, 10);
lv_style_init(&icon_style);
lv_style_set_text_color(&icon_style, lv_color_white());
lv_style_set_text_opa(&icon_style, LV_OPA_50);
lv_style_set_text_font(&icon_style, &lv_font_montserrat_14);
lv_obj_t *return_icon_label = lv_label_create(return_btn);
lv_label_set_text(return_icon_label, LV_SYMBOL_LEFT);
lv_obj_add_style(return_icon_label, &icon_style, 0);
lv_obj_add_event_cb(return_btn, return_btn_cb, LV_EVENT_CLICKED, NULL);
lv_obj_add_event_cb(return_btn, return_btn_cb, LV_EVENT_FOCUSED, return_icon_label);
lv_obj_add_event_cb(return_btn, return_btn_cb, LV_EVENT_DEFOCUSED, return_icon_label);
lv_obj_align(return_icon_label, LV_ALIGN_CENTER, 0, 0);
/* ui memory cont */
ui_memory_used_cont = lv_obj_create(bg_cont_obj);
lv_obj_remove_style_all(ui_memory_used_cont);
lv_obj_set_size(ui_memory_used_cont, 240, 120);
lv_obj_set_style_radius(ui_memory_used_cont, 20, 0);
lv_obj_set_style_bg_opa(ui_memory_used_cont, LV_OPA_0, 0);
lv_obj_align_to(ui_memory_used_cont, bg_cont_obj, LV_ALIGN_TOP_MID, 0, 30);
/* ui memory title label */
lv_obj_t *ui_memory_title_label = lv_label_create(ui_memory_used_cont);
lv_label_set_text_fmt(ui_memory_title_label, "RANGE");
//lv_obj_set_style_text_font(ui_memory_title_label, &my_font_chinese_18, 0);
lv_obj_set_style_text_color(ui_memory_title_label, lv_color_white(), 0);
lv_obj_set_style_text_opa(ui_memory_title_label, LV_OPA_COVER, 0);
lv_obj_align_to(ui_memory_title_label, ui_memory_used_cont, LV_ALIGN_TOP_MID, 0, 5);
/* ui memory arc */
ui_memory_used_rate_arc = lv_arc_create(ui_memory_used_cont);
lv_obj_set_size(ui_memory_used_rate_arc, 80, 80);
lv_obj_set_style_arc_width(ui_memory_used_rate_arc, 10, 0);
lv_obj_set_style_arc_width(ui_memory_used_rate_arc, 10, LV_PART_INDICATOR);
lv_obj_set_style_arc_color(ui_memory_used_rate_arc, lv_color_hex(MY_COLOR_SPRING_GREEN), LV_PART_INDICATOR);
lv_obj_set_style_arc_opa(ui_memory_used_rate_arc, LV_OPA_10, 0);
lv_arc_set_rotation(ui_memory_used_rate_arc, 270);
lv_arc_set_bg_angles(ui_memory_used_rate_arc, 0, 360);
lv_obj_remove_style(ui_memory_used_rate_arc, NULL, LV_PART_KNOB);
lv_obj_clear_flag(ui_memory_used_rate_arc, LV_OBJ_FLAG_CLICKABLE);
lv_obj_align_to(ui_memory_used_rate_arc, ui_memory_used_cont, LV_ALIGN_TOP_MID, 0, 30);
/* ui memory used rate label */
ui_memory_used_rate_label = lv_label_create(ui_memory_used_cont);
lv_label_set_text_fmt(ui_memory_used_rate_label, "%d%%", rate);
lv_obj_set_style_text_font(ui_memory_used_rate_label, &lv_font_montserrat_14, 0);
lv_obj_set_style_text_color(ui_memory_used_rate_label, lv_color_hex(MY_COLOR_SPRING_GREEN), 0);
lv_obj_set_style_text_opa(ui_memory_used_rate_label, LV_OPA_COVER, 0);
lv_obj_align_to(ui_memory_used_rate_label, ui_memory_used_rate_arc, LV_ALIGN_CENTER, 0, 0);
/* ui memory label cont */
ui_memory_label_cont = lv_obj_create(bg_cont_obj);
lv_obj_remove_style_all(ui_memory_label_cont);
lv_obj_set_size(ui_memory_label_cont, 240, 100);
lv_obj_set_style_radius(ui_memory_label_cont, 20, 0);
lv_obj_set_style_bg_opa(ui_memory_label_cont, LV_OPA_0, 0);
lv_obj_align_to(ui_memory_label_cont, ui_memory_used_rate_arc, LV_ALIGN_OUT_BOTTOM_MID, 0, 5);
/* line */
static lv_point_t line_points[] = { {0, 5}, {85, 5} };
static lv_style_t style_line;
lv_style_init(&style_line);
lv_style_set_line_width(&style_line, 3);
lv_style_set_line_color(&style_line, lv_color_hex(MY_COLOR_SPRING_GREEN));
lv_style_set_line_opa(&style_line, LV_OPA_COVER);
lv_style_set_line_rounded(&style_line, true);
line = lv_line_create(ui_memory_label_cont);
lv_line_set_points(line, line_points, 2);
lv_obj_add_style(line, &style_line, 0);
lv_obj_align_to(line, ui_memory_label_cont, LV_ALIGN_LEFT_MID, 70, 0);
/* ui used memory label */
ui_used_memory_label = lv_label_create(ui_memory_label_cont);
lv_label_set_text_fmt(ui_used_memory_label, "%d.%d", 0, 0);
lv_obj_set_style_text_font(ui_used_memory_label, &lv_font_montserrat_14, 0);
lv_obj_set_style_text_color(ui_used_memory_label, lv_color_white(), 0);
lv_obj_set_style_text_opa(ui_used_memory_label, LV_OPA_COVER, 0);
lv_obj_align_to(ui_used_memory_label, line, LV_ALIGN_OUT_TOP_MID, 0, 0);
lv_mem_monitor(&mon);
total_size = mon.total_size;
/* ui memory total label */
lv_obj_t *ui_memory_total_label = lv_label_create(ui_memory_label_cont);
lv_label_set_text_fmt(ui_memory_total_label, "%d", 3000);
lv_obj_set_style_text_font(ui_memory_total_label, &lv_font_montserrat_14, 0);
lv_obj_set_style_text_color(ui_memory_total_label, lv_color_white(), 0);
lv_obj_set_style_text_opa(ui_memory_total_label, LV_OPA_COVER, 0);
lv_obj_align_to(ui_memory_total_label, line, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
/* ui memory KB label */
ui_memory_kb_label = lv_label_create(ui_memory_label_cont);
lv_label_set_text_fmt(ui_memory_kb_label, "mm");
//lv_obj_set_style_text_font(ui_memory_kb_label, &my_font_chinese_18, 0);
lv_obj_set_style_text_color(ui_memory_kb_label, lv_color_white(), 0);
lv_obj_set_style_text_opa(ui_memory_kb_label, LV_OPA_COVER, 0);
lv_obj_align_to(ui_memory_kb_label, line, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
/* timer create */
timer2 = lv_timer_create(mem_chekc_timer_cb, 800, NULL);
lv_group_add_obj(group, return_btn);
vl53_page_anim_in(delay);
}
3. 功能展示及说明
开机log
系统主界面
数据测量显示界面
4. 对本活动的心得体会
非常高兴能够参加此次活动,通过活动,掌握了许多新的东西,arduino的开发环境使用起来非常方便,但是如果工程稍微大一点的话,编译速度会非常的慢,而且管理起来也非常不方便,ESP32的功能非常强大,不仅集成了WIFI,蓝牙,软件生态也非常完善。虽然第一次使用LVGL,但是上手还是比较容易的,借助官方的几个demo,以及网上的各种demo,入门非常简单,本次所用的界面框架就是参考了b站上的史达芬林网友的代码,在此表示感谢!
希望活动越办越好!