1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 基于FireBeetle 2 ESP32-E开发板的LVGL移植及传感器显示(Arduino+TFT_eSPI+LVGL)

基于FireBeetle 2 ESP32-E开发板的LVGL移植及传感器显示(Arduino+TFT_eSPI+LVGL)

时间:2022-06-30 13:34:45

相关推荐

基于FireBeetle 2 ESP32-E开发板的LVGL移植及传感器显示(Arduino+TFT_eSPI+LVGL)

目录

项目介绍硬件介绍硬件结构说明LVGL移植综合实现功能展示项目总结

👉 【Funpack2-3】基于FireBeetle 2 ESP32-E开发板的LVGL移植及传感器显示

👉 CSDN-工程源文件

👉 Github-KafCoppelia/FireBeetle2_lvgl_sensors

项目介绍

本项目基于FireBeetle2 ESP32-E开发板,使用VSCode+Arduino插件开发,通过TFT_eSPI库使用硬件SPI驱动LCD屏幕,并移植LVGL。搭配SHT40温湿度传感器与VL53L0激光测距传感器,将检测的数据较为美观地显示在屏幕上。

👉 Github-lvgl/lvgl

硬件介绍

FireBeetle ESP32-E是一款基于ESP-WROOM-32E双核芯片的主控板,它专为IoT设计。

它支持WIFI和蓝牙双模通信并具有体积小巧、超低功耗、板载充电电路、接口易用等特性。可灵活的用于家庭物联网改装、工业物联网改装、可穿戴设备等等。

硬件资源:

Type-C: USB接口:4.75v-5.5vpH2.0锂电池接口:3.5-4.2v2/D9 LED灯:使用2/09号脚控制的LED灯充电指示灯:指示充电方式的红色LED,通过三种方式指示充电状态:1充满电或末充电时熄灭2、充电时常亮3、USB供电,末连接锂电池时高频闪烁RST复位引脚:单击复位按钮,将程序复位5/D8 WS2812指示灯:使用5/D8引脚控制的WS2812RGB灯珠低功耗焊盘:此焊盘专为低功耗设计,默认为连接状态,使用小刀轻轻刮粉中间的细线即可断开,断开后可降低500u4静态功耗,通过程序控制主控进入睡眠模式后可将功耗降低至131A。注意:焊盘断开后仅UsE方式供电可驱动RGE灯GDI显示接口:DFRobot专用显示屏接口,详情后文GD显示接口ESP32模组:乐鑫公司推出的最新ESP32-E模组按钮:连接27/D4的按钮

👉 更多介绍

Funpack第二季第三期:FireBeetle 2 ESP32-E IoT 开发板DFRobot-FireBeetle Board ESP32 E

此外,介绍本工程内的两款传感器。MIKROE TEMP&HUM 15 CLICK 为一款SHT40温湿度传感器,I2C模式通信,可以获取温度、湿度信息。本工程通过Adafruit SHT4x库实现数据的读取,可直接在Arduino搜索下载该库

👉 MIKROE-TEMP&HUM 15 CLICK产品介绍

👉 Github-adafruit/Adafruit_SHT4X

DFRobot的VL53L0激光测距传感器是一款基于意法半导体(STMicroelectronics)新出的基于飞行时间测距 (ToF) 原理设计的高精度测距传感器,通过I2C通信,其Arduino库文件通过官网帮助页面可直接获得,也可直接在Arduino内搜索下载该库

👉 DFRobot-VL53L0

硬件结构说明

SHT40及VL53L0直接连在FireBeetle2的两路硬件I2C上,如此可直接调用库函数实现对传感器数据的读取,十分方便。两个传感器通过I2C地址查询,所以无所谓I2C1、I2C2的区分。

此外,TFT LCD 240x320通过硬件SPI驱动,具体连接关系如下(除电源与地外):

上述LCD与开发板的连接关系需要在配置TFT_eSPI驱动时再次用到。

LVGL移植

首先在Arduino内,安装TFT_eSPI库,再在TFT_eSPI库内找到User_Setup.h,并根据屏幕实际配置做修改,注意看注释的说明。主要需要修改的地方有:

👉 Github-Bodmer/TFT_eSPI

屏幕驱动IC对于ST7789,可能出现RGB颜色交换的问题屏幕尺寸颜色反色的问题, 根据实际问题开启或关闭反色SPI等引脚对应如果有背光控制,可设置启动的字体,如果内存大可全部启用SPI速率,根据实际需求即可

例如,本工程的LCD屏幕为ST7789,对应保留的宏定义有:

#define ST7789_DRIVER#define TFT_RGB_ORDER TFT_BGR #define TFT_WIDTH 240#define TFT_HEIGHT 320#define TFT_INVERSION_OFF#define TFT_BL 4 // LED back-light control pin#define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW)#define TFT_MISO 19#define TFT_MOSI 23#define TFT_SCLK 18#define TFT_CS 16 // Chip select control pin#define TFT_DC 17 // Data Command control pin#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST#define SPI_FREQUENCY 27000000

之后,下载LVGL release 源码,并通过zip包安装至Arduino库内。主要步骤可参考LVGL on Arduino帮助页面,主要进行:

转到安装的Arduino库的目录转到lvgl并复制lv_conf_template.h到与Arduino 库目录中lvgl同级的地方,改名为lv_conf.h。打开lv_conf.h并将第一个更改为启用文件的内容#if 1设置显示的颜色深度LV_COLOR_DEPTH 16(根据屏幕实际,本工程为16)设置LV_TICK_CUSTOM 1如果需要开启LVGL 日志功能,则修改对应宏开关LV_USE_LOG 1如果想启用LVGL的demo 或 exmaples,除了修改对应宏开关LV_BUILD_EXAMPLES 1外,参见LVGL on Arduino进行一些额外的步骤

在代码上,需要为LVGL实现一个my_disp_flush()函数,使用TFT_eSPI库的函数进行包装,即可将绘图功能打包给LVGL实现。Arduino实现的最简单的例子(LVGL库内可找到该例):

#include <lvgl.h>#include <TFT_eSPI.h>#include <lv_demo.h>/*Change to your screen resolution*/static const uint16_t screenWidth = 480;static const uint16_t screenHeight = 320;static lv_disp_draw_buf_t draw_buf;static lv_color_t buf[ screenWidth * 10 ];TFT_eSPI tft = TFT_eSPI(screenWidth, screenHeight); /* TFT instance *//* Display flushing */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 */String LVGL_Arduino = "Hello Arduino! ";LVGL_Arduino += String('V') + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();Serial.println( LVGL_Arduino );Serial.println( "I am LVGL_Arduino" );lv_init();#if LV_USE_LOG != 0lv_log_register_print_cb( my_print ); /* register print function for debugging */#endiftft.begin();/* TFT init */tft.setRotation( 3 ); /* Landscape orientation, flipped */lv_disp_draw_buf_init( &draw_buf, buf, NULL, screenWidth * 10 );/*Initialize the display*/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 );lv_demo_widgets();Serial.println( "Setup done" );}void loop(){lv_timer_handler(); /* let the GUI do its work */delay( 5 );}

综合实现

首先,实现两款传感器数据的读取函数,便于之后在lvgl事务内直接获取数据。对于SHT40,在初始化后,读取温度及湿度信息

Adafruit_SHT4x sht4 = Adafruit_SHT4x(); /* Global instance */void sht40_get_measured(sensors_event_t *humidity, sensors_event_t *temp) {sht4.getEvent(humidity, temp);// populate temp and humidity objects with fresh dataSerial.print("Temperature: "); Serial.print(temp->temperature); Serial.println(" degrees C");Serial.print("Humidity: "); Serial.print(humidity->relative_humidity); Serial.println("% rH");}

对于VL53L0,TOF测距,在初始化后,读取测量的距离信息:

DFRobot_VL53L0X sensor; /* Global instance */float vl53l0x_get_measured() {float distance = sensor.getDistance();Serial.print("Distance: ");Serial.println(distance);return distance;}

屏幕主要分为三块地方:

左上角显示温湿度信息,并且每秒刷新右上角通过判断开发板按键是否按下,实现TOF测距的开/关下方将TOF测距以折线图显示,并且每250ms更新动态显示

主要地,通过lvgl实现三个定时器事务,温湿度定时器,每秒获取并刷新显示文字:

lv_timer_t *sht4x_update_timer;sht4x_update_timer = lv_timer_create(temperature_update, 1000, NULL); /* Always working */static void temperature_update(lv_timer_t *timer) {sht40_get_measured(&sht4x_humidity, &sht4x_temp);lv_label_set_text_fmt(temp_label, "Temp: %.1f °C", sht4x_temp.temperature);lv_label_set_text_fmt(humd_label, "Humidity: %.1f% rH", sht4x_humidity.relative_humidity);}

对应的两个标签对象:

lv_obj_t *temp_label = lv_label_create(lv_scr_act());lv_label_set_text(temp_label, "Temp: 0 °C");lv_obj_set_style_text_color(lv_scr_act(), lv_color_black(), LV_PART_MAIN);lv_obj_align(temp_label, LV_ALIGN_TOP_LEFT, 10, 10);lv_obj_t *humd_label = lv_label_create(lv_scr_act());lv_label_set_text(humd_label, "Humidity: 0% rH");lv_obj_set_style_text_color(lv_scr_act(), lv_color_black(), LV_PART_MAIN);lv_obj_align(humd_label, LV_ALIGN_TOP_LEFT, 10, 30);

按键检测定时器,每30毫秒检测按键是否按下,其中还需要有改变开关控件的交互,当按键按下,开关切换状态,若为打开,则旁边标签显示“TOF measuring”,且TOF开始测距,vl53l0x_update_timer定时器继续工作;若为关闭,则边标签显示“TOF idle”,且TOF停止工作,vl53l0x_update_timer定时器暂停:

int last_btn_state = HIGH;lv_timer_t *btn_state_timer;btn_state_timer = lv_timer_create(btn_pressed_check, 30, NULL);static void btn_pressed_check(lv_timer_t *timer) {int reading = digitalRead(BTN_PIN);if (reading != last_btn_state) {if (reading == LOW) {if (lv_obj_has_state(tof_measuring_sw, LV_STATE_CHECKED)) {lv_obj_clear_state(tof_measuring_sw, LV_STATE_CHECKED);vl53l0x_stop();lv_timer_pause(vl53l0x_update_timer);lv_label_set_text(btn_label, "TOF idle");}else {lv_obj_add_state(tof_measuring_sw, LV_STATE_CHECKED);vl53l0x_start();lv_timer_resume(vl53l0x_update_timer);lv_label_set_text(btn_label, "TOF measuring");} }}last_btn_state = reading;}

对应的开关控件及标签对象:

lv_obj_t *btn_label = lv_label_create(lv_scr_act());lv_label_set_text(btn_label, "TOF measuring");lv_obj_set_style_text_color(lv_scr_act(), lv_color_black(), LV_PART_MAIN);lv_obj_align(btn_label, LV_ALIGN_CENTER, 50, -100);lv_obj_t *tof_measuring_sw = lv_switch_create(lv_scr_act());lv_obj_set_size(tof_measuring_sw, 40, 20);lv_obj_align(tof_measuring_sw, LV_ALIGN_TOP_RIGHT, -10, 10);lv_obj_add_state(tof_measuring_sw, LV_STATE_CHECKED); /* switch on in default */

VL530L0定时任务,每250毫秒更新测量,将下一个数据显示在折线图右侧:

lv_timer_t *vl53l0x_update_timer;vl53l0x_update_timer = lv_timer_create(tof_update, 250, NULL);static void tof_update(lv_timer_t *timer) {float tof_new_data = vl53l0x_get_measured();lv_chart_set_next_value(tof_data_chart, tof_data_series, (int)tof_new_data);lv_chart_refresh(tof_data_chart);lv_label_set_text_fmt(y_next_value_label, "%.1f", tof_new_data);if (tof_new_data > 1000) {lv_obj_align_to(y_next_value_label, tof_data_chart, LV_ALIGN_OUT_RIGHT_MID, -40, 10);}else {lv_obj_align_to(y_next_value_label, tof_data_chart, LV_ALIGN_OUT_RIGHT_MID, -40, -10);}}

折线图的更新显示,通过LVGL可以很简单的实现,一些标签对象的位置摆放,请参考LVGL帮助文档,查看具体函数的用法即可。

功能展示

上电后,两个传感器即刻开始工作。

当按下按键,关闭TOF测量开关时,折线图停止更新,开关控件关闭且显示“TOF idle”:

当按下按键,开启TOF测量开关时,折线图继续动态更新,开关控件开启且显示“TOF measuring”:

项目总结

此次成功移植了LVGL至LCD上,实现了对SHT40、VL53L0温湿度信息、ToF测距信息的简单显示,使用LVGL显示各种效果都很方便、很好看,代码上也很有条理,通过事件、定时器等功能可以实现多种控件的交互。

美中不足的是,限于时间,原本想实现动态显示ToF测距折线图的纵坐标数据,但是实现起来确实不是想的那么容易,因此目前无法实现折线图纵坐标的灵活切换。当测量数据较大时,数据会绘制在折线图范围之外。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。