大家好,我这次非常开心能够参加本期有硬禾学堂和得捷电子联合举办的Fun pack活动,我对物联网开发经验较少,之前在网络上学习了一些ESP8266的基础知识,不过一直没有接触过ESP32,购物平台上ESP32质量参差不齐,这次刚好是DFROBOT的主控FIREBEETLE ESP32作为本期的主角,非常开心。下面就和大家来分享一下我的设计思路。
0、FireBeetle ESP32-E 简介
FireBeetle ESP32-E深度支持ArduinoIDE,还可以使用MicroPython、Mind+图形化等编程环境来操控板载硬件资源。DFRobot公司提供上千种免焊接的Gravity接口传感器与执行器
一、题目方向选择
本期活动的自由度非常大,主办方给了大家非常充足的时间,多样化的项目视角来让大家好好玩起来。我自己对LVGL和iot非常感兴趣,也不太清楚该从哪里入手。结合这次的Funpack活动,我给自己设定的目标是
1)能够初步使用LVGL来动态显示一个传感器的数据
2)能够把数据透过MQTT协议来上传到IoT网站,实现动态显示
综合起来看,比较贴近任务6.
任务六:开放性题目
用FireBeetle ESP32-E开发板,再任选一个及以上传感器 + 一个屏幕搭配完成任务,难度不低于以上题目难度。
二、LVGL方面设计
我选择了在Arduino中使用LVGL。目前网络上对这部分的介绍也比较多,我使用的版本在目前比较新的8.3版本,在使用LVGL之前,需要先把屏幕驱动库安装,调试好。
采用的屏幕是:SPI接口的240 X 320分辨率电阻触摸屏。
这里用到的驱动是Arduino环境下提供的TFT_eSPI库,可以非常方便在库管理器中搜索“TFT_eSPI”这里安装的版本是2.4.72.
安装好库文件后,要根据自己的屏幕去修改一些配置,比如:
之后安装LVGL,版本选择8.3.0
安装好后,需要进行一些配置参数的设定:
这里屏幕用于动态显示采集的声音传感器数据,所以自然而然的想起用图表来展示数据,LVGL有个自带的小组件“Chart”,核心的代码如下。
主要思路是:1)先创建一个Chart,然后再创建几个“标签”来显示一些文字信息。
/*Create a chart to show voice data*/
Chart_VoiceSensor = lv_chart_create(lv_scr_act());
//lv_obj_set_size(Chart_VoiceSensor, 100, 130);
lv_obj_set_size(Chart_VoiceSensor, 180, 150);
lv_obj_center(Chart_VoiceSensor);
lv_chart_set_type(Chart_VoiceSensor, LV_CHART_TYPE_LINE); /*Show lines and points too*/
lv_chart_set_div_line_count(Chart_VoiceSensor, 3, 5);
lv_chart_set_axis_tick(Chart_VoiceSensor, LV_CHART_AXIS_PRIMARY_Y, 6, 3, 9, 1, true, 30);
lv_chart_set_axis_tick(Chart_VoiceSensor, LV_CHART_AXIS_PRIMARY_X, 6, 3, 5, 1, true, 10);
lv_obj_add_event_cb(Chart_VoiceSensor, draw_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL);
lv_chart_set_update_mode(Chart_VoiceSensor, LV_CHART_UPDATE_MODE_SHIFT);
ser1 = lv_chart_add_series(Chart_VoiceSensor, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y);
uint32_t i;
for (i = 0; i < 10; i++) {
lv_chart_set_next_value(Chart_VoiceSensor, ser1, lv_rand(20, 90));
}
lv_timer_create(add_data, 100, NULL);
lv_obj_t * label = lv_label_create(lv_scr_act());
lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 5);
lv_label_set_recolor(label, true);
lv_label_set_text(label, "#0000ff FireBeetle# #ff00ff ESP32-E# & DFR0034");
lv_obj_t * label2 = lv_label_create(lv_scr_act());
lv_obj_align(label2, LV_ALIGN_LEFT_MID, 0, 0);
lv_label_set_recolor(label2, true);
lv_label_set_text(label2, "#ff00ff 2048#");
lv_obj_t * label1 = lv_label_create(lv_scr_act());
lv_label_set_recolor(label1, true);
lv_obj_align_to(label1, Chart_VoiceSensor, LV_ALIGN_OUT_BOTTOM_LEFT, -60, -20);
lv_label_set_text(label1, "#0000ff 0#");
lv_obj_t * label3 = lv_label_create(lv_scr_act());
lv_obj_align_to(label3, Chart_VoiceSensor, LV_ALIGN_OUT_TOP_LEFT, -70, 18);
lv_label_set_recolor(label3, true);
lv_label_set_text(label3, "#ff0000 4095 #");
我这里采用的是FreeRTOS,然后把MQTT相关的工作放入了一个单独的Task中,这个Task是分配在Core1上运行的。然后LVGL相关的工作是分配在Core0上运行的。下面是创建两个Task,分别分配到Core1和Core0.
void setup{
...
// Now set up two tasks to run independently.
xTaskCreatePinnedToCore(
TaskMqtt
, "TaskMqtt" // A name just for humans
, 10240 // This stack size can be checked & adjusted by reading the Stack Highwater
, NULL
, 1 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
, NULL
, 1);
xTaskCreatePinnedToCore(
TaskReadA0_GUI
, "TaskReadA0_GUI"
, 10240 // Stack size
, NULL
, 1 // Priority
, NULL
, 0);
...
}
void TaskReadA0_GUI(void *pvParameters) // This is a task.
{
(void) pvParameters;
Serial.print("TaskReadA0_GUI 在核心 ");Serial.print(xPortGetCoreID());Serial.println(" 上运行");
for (;;)
{
lv_timer_handler(); /* let the GUI do its work */
delay(5);
}
}
效果如下:
三、IOT方面设计
IoT网站方面,自己之前了解过thingSpeak.com这个物联网平台,可以使用MQTT来上传数据。
第一步:注册一个免费的MQTT服务器,这里我使用的是ThingSpeak.
然后新建一个Channel:
然后建立两个栏位,第一个LED主要是希望通过MQTT来控制Fire Beetle板载的LED;第二个栏位“VOICE_SENSOR”主要是用于接收声音传感器通过ESP32-MQTT上传来的数据。
然后点击Save:
在API KEYS,比较重要的是Write API KEy和 Read API Keys,分别对应向MQTT服务器写入数据以及从MQTT服务器读取数据时候用到。比如下面的ThingSpeak()API在调用的时候,需要填写你自己的writeAPIKey,否则上传数据失败的。我这里采用的是FreeRTOS,然后把MQTT相关的工作放入了一个单独的Task中,这个Task是分配在Core1上运行的。然后LVGL相关的工作是分配在Core0上运行的。
void TaskMqtt(void *pvParameters) // This is a task.
{
(void) pvParameters;
Serial.print("TaskMqtt 在核心 ");Serial.print(xPortGetCoreID());Serial.println(" 上运行");
// Connect or reconnect to WiFi
// Connect or reconnect to WiFi
if(WiFi.status() != WL_CONNECTED){
Serial.print("Attempting to connect to SSID: ");
Serial.println(SECRET_SSID);
while(WiFi.status() != WL_CONNECTED){
WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network. Change this line if using open or WEP network
Serial.print(".");
delay(5000);
}
Serial.println("\nConnected.");
}
for (;;) // A Task shall never return or exit.
{
// Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to store up to 8 different
// pieces of information in a channel. Here, we write to field 1.
tempValtoIOT = tempVal;
int x = ThingSpeak.writeField(myChannelNumber, 1, tempValtoIOT, myWriteAPIKey);
if(x == 200){
Serial.print("------------Channel update successful----Value: ");
Serial.print(tempValtoIOT);
Serial.println(" -------------------.");
}
else{
Serial.println("Problem updating channel. HTTP error code " + String(x));
}
delay(20000); // Wait 20 seconds to update the channel again
}
}
一些遇到的栈溢出错误:这个是由于LVGL和WIFI相关的库运行需要比较大的RAM,我使用的默认的值比较小,从1024字节改为10240字节后,程序运行正常。
四、结果展示
请大家跟我一起看一下我的项目展示。其中左侧的4095,2048,0分别是纵坐标对应的ADC采样值,纵坐标0-100是一个百分比,比如100,对应的ADC采样值是4095。这款声音传感器在没有声音输入的情况下,ADC值是0。
下面是上传到IoT网站:
总结:
衷心的感谢硬禾学堂和得捷电子联合举办的这次Firebeetle ESP32-E活动,让我能够静下心来学习如何使用ESP32开发板来搭建一个简单的声音数据采集,屏幕展示,上传到IoT网站整个过程。希望这个活动可以越办越好!