Funpack2-3: 基于FireBeetle ESP32和LVGL的声音传感器数据采集和显示设计
本设计目标是完成任务二:lvgl图形库和应用 用FireBeetle-E (ESP32)开发板作为控制单元,搭配显示屏移植lvgl 8.3图形库,动态显示声音传感器(SEN0487)采集到的数据并在显示屏上进行展示
标签
嵌入式系统
lvgl
FireBeetle ESP32
DFROBOT
Funpack2-3
ESP32-E
littlestudent
更新2023-01-03
813

内容介绍

感谢硬禾学堂提供的这次学习DFRBOT单片机FireBeetle-E ESP32和LVGL图形库的机会,也是自己首次尝试在单片机上使用LVGL图形库。

开箱图:自带的排母只能单面插接

Fl11l3WWW-P8wRUJW62ed9D7dyfgFjN-JMh_rZmfKbGRwqhDGJmv4KY2

首先是理解本次设计的任务:

任务二:lvgl图形库和应用
用FireBeetle-E开发板作为控制单元,搭配显示屏移植lvgl图形库,动态显示任意一个及以上传感器采集到的数据,或者使用触摸屏对执行器进行控制。

根据自己选择的传感器,实现的是:用FireBeetle-E (ESP32)开发板作为控制单元,搭配显示屏移植lvgl 8.3图形库,动态显示声音传感器(SEN0487)采集到的数据并在显示屏上进行展示。

下图是FireBeetle-E开发板的Pinout:

    FmWFK5P8BeNn3lLqvsvEP2Hi12ZV

具体的硬件连线:

FjU2NS6ZW08Z5SFj8y7sN9gZARZV

根据任务描述,把任务2分成三个子任务:

  • Sub-1:移植LVGL 8.3图形库
  • Sub-2:声音传感器SEN0487数据采集
  • Sub-3:使用Sub-1中的LVGL组件动态显示Sub-2中的传感器数据

下面分别介绍各模块的实现方法。

Sub-1:移植LVGL 8.3图形库

在开始移植LVGL8.3图形库之前,需要确保LCD屏幕可以被正常驱动,此处我们使用的是TFT_eSPI这个Arduino库。手头的一块带电阻触摸的屏幕驱动芯片是ILI9341,在TFT_eSPI的适用范围内。这块屏幕是2.4寸彩屏,支持16BIT RGB 65K色显示,显示色彩丰富 320X240高清分辨率,可选触摸功能 采用SPI串行总线,只需几个IO即可点亮显示。

    FtT1UD_Yi2sUcyO5yb_COUbxMY5h

下面先安装这个触摸屏的驱动库TFT_eSPI,在IDE中打开库管理器,然后搜索:“TFT_eSPI”,选择合适的版本,点击安装即可。

    FtIGi50fkLx_xIGfYcQx4ORYknFR

之后安装FireBeetle-ESP32主板相关的驱动库。这部分操作可以参考DFROBOT官网7.1 Arduino环境配置,不过Arduino->文件->首选项->附件开发板管理器网址输入的是: http://download.dfrobot.top/FireBeetle/package_esp32_index.json

更新板卡,打开“工具” -> 开发板管理,待自动更新完成后,会在列表中看到FireBeetle-ESP32主板(现已更新至0.1.1版本),点击安装:

    FtKJLX6FcsMZAFo-sy6m40SHrApr

    FrNgEVAopyWCzHl1Leel7Bf30yKh

根据屏幕驱动来修改库文件中的User_Setup.h文件,库里面内置了很多种屏幕的驱动,具体可以到TFT_Drivers目录下查看。

    Fn5RQhntY_sPZZcIvbsXpLINhSu8

这个User_Setup.h里面定义了相关的硬件接口,包括屏幕显示和屏幕触摸部分。需要结合屏幕的引脚进行准确的分配。比如下面TFT_CS定义了屏幕的片选引脚,TOUCH_CS定义了触摸部分SPI接口的片选引脚。

    FoKfOjxwc3gCJEtWP2-x1S89R1L2

安装LVGL库,此处选择的是lvgl 8.3.0

    FtOEd033iNZw8_HzjABUDlUF7858

移植LVGL到Arduino平台还是非常方便的!下面是移植步骤:

官方参考文档: https://docs.lvgl.io/latest/en/html/get-started/arduino.html#configure-lvgl

在Arduino ide中,项目 -> 显示项目文件夹,在文件管理器中打开当前项目文件夹,然后向上一级目录,找到libraries文件夹并进入,进入lvgl文件夹,复制lv_conf_template.h文件,向上一级目录,粘贴并重命名为lv_conf.h。此时lv_conf.h在libraries文件夹中。

修改如下内容:

第10行,将其设为1。

#if 1 /*Set it to "1" to enable content*/

第32行,设置自己显示器的颜色深度,笔者对自己显示器的颜色深度也不是很了解,故使用的默认值16。

第303行,将LV_TICK_CUSTOM设为1

#define LV_TICK_CUSTOM     1

第384行,将列出的字体全部设为1,在lv_examples中,用到了很多不同的字体大小。

#define LV_FONT_MONTSERRAT_8     1
#define LV_FONT_MONTSERRAT_10    1
#define LV_FONT_MONTSERRAT_12    1
#define LV_FONT_MONTSERRAT_14    1
#define LV_FONT_MONTSERRAT_16    1
#define LV_FONT_MONTSERRAT_18    1
#define LV_FONT_MONTSERRAT_20    1
#define LV_FONT_MONTSERRAT_22    1
#define LV_FONT_MONTSERRAT_24    1
#define LV_FONT_MONTSERRAT_26    1
#define LV_FONT_MONTSERRAT_28    1
#define LV_FONT_MONTSERRAT_30    1
#define LV_FONT_MONTSERRAT_32    1
#define LV_FONT_MONTSERRAT_34    1
#define LV_FONT_MONTSERRAT_36    1
#define LV_FONT_MONTSERRAT_38    1
#define LV_FONT_MONTSERRAT_40    1
#define LV_FONT_MONTSERRAT_42    1
#define LV_FONT_MONTSERRAT_44    1
#define LV_FONT_MONTSERRAT_46    1
#define LV_FONT_MONTSERRAT_48    1

之后运行LVGL的Btn例程后,发现触摸Button的位置,没有什么反应,即不会进入cbk。后面阅读手册,发现需要先运行

    FlDLhgzlVdsw-d2xY7b-8e6y_peN

执行完屏幕校准程序“lvgl_demo_Touch_calibrate_240x320.ino”后,串口监视器有如下的输出,然后将下面两行代码拷贝到自己的项目中,覆盖默认的屏幕校准数据。
          uint16_t calData[5] = { 403, 3530, 292, 3483, 3 };
          tft.setTouch(calData);

这个屏幕校准是非常重要的一个步骤,如果跳过这个步骤,后面的屏幕触摸将不能正常工作。下面展示的是校准后的,触摸屏幕上的LVGL中的“Button”类小组件,颜色发生变化,说明触摸正常工作。

    lnk6eqizYndnNxmRIAL01fWmIhHu

相关核心代码:

void setup()
{
    pinMode(LED_BUILTIN, OUTPUT);//将LED引脚设置为输出模式

    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();

    tft.begin();          /* TFT init */
    tft.setRotation( 1 ); /* Landscape orientation, flipped */

    /*Set the touchscreen calibration data,
     the actual data for your display can be acquired using
     the Generic -> Touch_calibrate example from the TFT_eSPI library*/
    uint16_t calData[5] = { 403, 3530, 292, 3483, 3 };
    tft.setTouch( calData );

    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 = screenHeight;
    disp_drv.ver_res = screenWidth;
    disp_drv.flush_cb = my_disp_flush;
    disp_drv.draw_buf = &draw_buf;
    lv_disp_drv_register( &disp_drv );

    /*Initialize the (dummy) input device driver*/
    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init( &indev_drv );
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = my_touchpad_read;
    lv_indev_drv_register( &indev_drv );

    lv_obj_t* mySwitch = lv_btn_create(lv_scr_act());
    lv_obj_align( mySwitch, LV_ALIGN_CENTER, 0, 0 );
    lv_obj_set_size(mySwitch, 30, 30);
    lv_obj_set_style_bg_color(mySwitch, lv_color_hex(0x17a1a5), 0);
    lv_obj_add_event_cb(mySwitch, myCbk, LV_EVENT_ALL, NULL); 
    lv_obj_add_flag(mySwitch, LV_OBJ_FLAG_CHECKABLE);
    
    /* Create simple label */
    lv_obj_t *label = lv_label_create( lv_scr_act() );
    lv_label_set_text( label, "Hello MOTOR" );
    lv_obj_align_to(label, mySwitch, LV_ALIGN_OUT_BOTTOM_MID, 30, 0);
    
    Serial.println( "Setup done" );
}

void loop()
{
    lv_timer_handler(); /* let the GUI do its work */
    delay( 5 );
}

static void myCbk(lv_event_t* e) {
    Serial.println("call back func entered");
    
    lv_event_code_t code = lv_event_get_code(e);

    if(code == LV_EVENT_CLICKED) {
        LV_LOG_USER("Clicked");
        digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    }
    else if(code == LV_EVENT_VALUE_CHANGED) {
        LV_LOG_USER("Toggled");
    }
}//end-static-void-myCbk

Sub-2:声音传感器SEN0487数据采集

声音传感器数据采集使用的传感器型号是Fermion MEMS Microphone Sensor SKU:SEN0487 Fermion: 全向MEMS麦克风模块 简介 https://wiki.dfrobot.com.cn/_SKU_SEN0487_Fermion_MEMS_Microphone_Sensor

测试代码也是非常的简单,可以参考上述DFROBOT的wiki:

        void setup() {
          Serial.begin(115200);
        }
        
        void loop() {
          // read the value from the sensor:
          Serial.println(analogRead(A0));
          delay(10);
        }


 执行后,打开Arduino IDE自带的串口绘图工具。可以看到没有声音输入的时候,传感器ADC值在1600左右(1920/4095 * 3.3 v = 1.54 v,这与DFROBOT官网描述一致:这是一款超小体积的MEMS麦克风。放大器增益为66,当没有检测到声音时,输出电压在1.5V左右浮动),有声音输入的时候,波形非常明显。

    FuQkJfI4OLSwcNB14yBVfEyep545

Sub-3:使用Sub-1中的LVGL组件动态显示Sub-2中的传感器数据

这部分的工作主要是把声音传感器采集到的模拟数据经过ADC处理后,显示在屏幕上,这里使用到了LVGL的组件有:

textarea: 显示“funpack eetree & dfrobot”

chart: 用柱状图的形式显示声音数据

bar: "进度条"组件用于动态显示ADC数值并且ADC数值越大,Bar的指示器(Indicator)的宽度越宽。

结果展示:

下图是没有声音输入的时候,采样值会维持在1920(ADC最大4095)

FpcBUI4VkGgBj3aOiAgUFmrapA3k

下图是对着声音传感器吹气,可以明显的看到chart和bar这两个lvgl的小组件可以动态的准确显示ADC数值。

lqJovNRlqUlSpToDP7O3xPUSxjB_

主要的代码如下,完整代码可以参考附件:

static void add_data(lv_timer_t * timer)
{
    LV_UNUSED(timer);
    tempVal = analogRead(A0);
    lv_chart_set_next_value(chart1, ser1, tempVal>>6);
    //String mySensorValueADC = "Voice Sensor: " + String(tempVal);
    String mySensorValueADC = "    funpack eetree & dfrobt";
    lv_textarea_set_text(mySensorValue, mySensorValueADC.c_str());
    lv_bar_set_value(myBar, tempVal, LV_ANIM_OFF);
    
}

void lv_lvgl_chart2(void)
{
    //add a text for chart to show the sensor adc value
    mySensorValue = lv_textarea_create(lv_scr_act());
    //lv_obj_align_to(mySensorValue, chart1, LV_ALIGN_TOP_LEFT, 0, 0);
    lv_obj_align(mySensorValue, LV_ALIGN_TOP_MID,0,0);

    lv_obj_t * myLabelforBar = lv_label_create(lv_scr_act());
    lv_obj_align(myLabelforBar, LV_ALIGN_BOTTOM_LEFT,0,-10);
    lv_label_set_text(myLabelforBar, "  Voice Sensor: ");

    // Bar Related Part Start:
    static lv_style_t style_indic;

    lv_style_init(&style_indic);
    lv_style_set_bg_opa(&style_indic, LV_OPA_COVER);
    lv_style_set_bg_color(&style_indic, lv_palette_main(LV_PALETTE_RED));
    lv_style_set_bg_grad_color(&style_indic, lv_palette_main(LV_PALETTE_BLUE));
    lv_style_set_bg_grad_dir(&style_indic, LV_GRAD_DIR_VER);

    myBar = lv_bar_create(lv_scr_act());
    lv_obj_add_style(myBar, &style_indic, LV_PART_INDICATOR);
    //lv_obj_align(myBar, LV_ALIGN_BOTTOM_MID,0, -10);
    lv_obj_align_to(myBar, myLabelforBar, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
    lv_obj_add_event_cb(myBar, myBar_event_cb, LV_EVENT_DRAW_PART_END, NULL);
    lv_obj_set_size(myBar,180, 20);
    lv_bar_set_range(myBar, 0, 4095);


    // Bar Related Part End.

    /*Create a chart1*/
    chart1 = lv_chart_create(lv_scr_act());
    lv_obj_set_size(chart1, 200, 150);
    lv_obj_center(chart1);
    lv_chart_set_type(chart1, LV_CHART_TYPE_BAR);   /*Show lines and points too*/

    lv_chart_set_div_line_count(chart1, 5, 7);

    lv_obj_add_event_cb(chart1, draw_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL);
    //lv_chart_set_update_mode(chart1, LV_CHART_UPDATE_MODE_CIRCULAR);
    lv_chart_set_update_mode(chart1, LV_CHART_UPDATE_MODE_SHIFT);

    /*Comment out the 2nd data serie, only leave the 1st data serie*/
    ser1 = lv_chart_add_series(chart1, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y);
    //ser2 = lv_chart_add_series(chart1, lv_palette_main(LV_PALETTE_BLUE), LV_CHART_AXIS_SECONDARY_Y);

    uint32_t i;
    for (i = 0; i < 10; i++) {
        lv_chart_set_next_value(chart1, ser1, lv_rand(20, 90));
        //lv_chart_set_next_value(chart1, ser2, lv_rand(30, 70));
    }

    lv_timer_create(add_data, 1, NULL);  
}

总结:

DFROBOT的这款FIREBEETLE-E ESP32开发板是一款高性能、易上手开发的物联网开发板。非常感谢硬禾学堂举办的这次Funpack活动,让我有机会第一次接触ESP32,第一次移植并使用了LVGL 8.3版本,学习到了很多新知识!

附上自己收集的相关资料链接:

  1. DFROBOT官方论坛:https://wiki.dfrobot.com.cn/_SKU_DFR0654_FireBeetle_Board_ESP32_E#target_0
  2. Fermion MEMS Microphone Sensor https://wiki.dfrobot.com.cn/_SKU_SEN0487_Fermion_MEMS_Microphone_Sensor

附件下载

lvgl_8.3.0_default_demo_modified_V3_Release.ino

团队介绍

自己一个人

评论

0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号