本帖最后由 xinmeng_wit 于 2022-10-23 22:44 编辑
多功能网络天气时钟
作者:xinmeng_wit
ESP32-S2-Kaluga-1开发板板上外设资源非常丰富,除了基本的led,按键,LCD之外,还有音频输入输出和WiFi/蓝牙功能。有了WiFi的加持,使这款开发板很容易开发联网类的应用。由此想到了之前一直想做但是没有做的桌面天气摆件——多功能网络天气时钟。用ESP32-S2-Kaluga-1开发板来实现网络天气时钟其实是非常合适的,毕竟不用外接WiFi模块,同时还自带有显示屏和按键输入模块,省掉了外部接线的麻烦,基本不用外接任何器件就能实现功能。很遗憾的是板载的LCD不支持触摸功能,因此输入必须借助与按键。
本作品的定位是桌面电子小摆件,主要功能是显示日历、实时时间、实时天气、闹钟功能和城市地址设置。另外,还应该有附加的小游戏功能和传感器数据采集功能。但由于本次比赛时间有限,附加功能未能实现,只留有接口,后续将继续完成既定功能。
本作品上电自动联网对时,同时自动获取实时天气信息,无需手动调节,上电第一屏显示功能选择,根据被按下的按键进入相应的功能模块。第二屏显示实时天气和时钟,另外,还附加有闹钟显示;第二屏显示的天气信息包括天气状况和对应的图标、温度、湿度和风力,其中温湿度还包括进度条的显示。板载6个用户按键,可以通过这些按键进行功能设置。
本作品全部使用板载资源,主控为ESP32S2,芯片自带wifi和蓝牙;本作品用到了wifi实现联网获取信息,板载显示部分与主控之间也是通过SPI的方式进行通讯;板载6个独立按键通过一个IO口进行检测,使用ADC进行电压检测,不同的电压对应不同的按键键值。
总结下来主要分为如下几个部分:
- Wifi通讯部分
Wifi通讯部分主要负责网络连接、NTP对时和天气消息的获取,在软件里面是单独的一个task,专门负责处理网络相关的任务。该task有几个比较重要的模块:天气数据的获取/解析/发送,SNTP对时,实时时间的获取处理和发送。
联网成功后首先进行SNTP对时,涉及到的几个主要函数如下:
天气数据的解析,使用了到了开源库cJSON,使用cJSON库确实会带来很大的方便,但同时会带来RAM的开销,对于RAM不是很够的MCU不建议使用。天气数据的处理,主要包含几个函数:
- LCD显示部分
显示部分也是单独的task,只负责显示,不参与任何检测和控制。显示部分通过消息队列接收消息进行显示。显示部分为了方便显示,使用了开源GUI图形库LVGL,极大地简化了应用程序开发,同时能使显示更加美观。对于控件的布局和设置使用了NXP开源GUI图形配置软件GUI Guider进行控件代码生成,生成的相关文件如
显示任务的主循环如下:
为了能够一目了然地显示天气状态,特意制作了几种天气图标,这些图标都做成统一大小(40*40)的彩色图片,并用GUI Guider工具取模保存为数组,显示的时候根据天气状态调用对应的图标。
天气图标的显示是根据天气代码来进行选择的,不同的天气代码显示不同的图标:
另外,闹钟和温度,湿度,风力也配置了相应的静态图片,闹钟图片大小30 * 30,温度/湿度/风力图片大小12 * 24,如下:
- 按键(ADC)部分
按键电压的采集是一个独立的线程,只负责按键电压的采集和发送,板载有6个ADC按键,只占用一个IO资源,每个按键硬件三搭配了不同阻值的电阻,每个按键按下,ADC口采集到的电压是不一样的,由此可以判断是哪个按键按下的。ADC使用连续采样,采样完成后做平均值,最后通过电压值转换为键值,完成后通过消息队列发送给gui显示任务。
//将电压值转换为对应按键的键值
static void voltage_to_button_value(double v)
{
uint16_t key_value = 0;
if (v > 2.6) {
;
} else if (v > 2.41 - DEVIATION && v <= 2.41 + DEVIATION) {
ESP_LOGI(TAG, "rec(K1)");
key_value = 1;
} else if (v > 1.98 - DEVIATION && v <= 1.98 + DEVIATION) {
ESP_LOGI(TAG, "mode(K2)");
key_value = 2;
} else if (v > 1.65 - DEVIATION && v <= 1.65 + DEVIATION) {
ESP_LOGI(TAG, "play(K3)");
key_value = 3;
} else if (v > 1.11 - DEVIATION && v <= 1.11 + DEVIATION) {
ESP_LOGI(TAG, "set(K4)");
key_value = 4;
} else if (v > 0.82 - DEVIATION && v <= 0.82 + DEVIATION) {
ESP_LOGI(TAG, "vol(K5)");
key_value = 5;
} else if (v > 0.38 - DEVIATION && v <= 0.38 + DEVIATION) {
ESP_LOGI(TAG, "vol+(K6)");
key_value = 6;
}
if(key_value != 0)
{
xQueueSend(adc_queue, (uint16_t *)&key_value, 0);
key_value = 0;
}
}
- 关于消息队列
使用RTOS最大的好处就提高资源利用率,另外多任务操作就是为了任务分块,不同的任务在控制上(或者说代码块上)相互独立,独立的同时会带来一些其它的问题,任务间的数据传输。本设计使用了四个消息队列来进行不同任务间的数据传输/同步。
①按键键值的跨任务传输
②天气消息的跨任务传输
③实时时间的跨任务传输
④显示任务与wifi任务的同步
源代码:https://gitee.com/xinmeng_wit/weather_project
首次使用ESP32系列芯片和开发板,收获颇多。在这个项目中,了解和学习了传说中的idf开发环境,idf的使用还是有门槛的,最起码cmake语法要知道,还有分区表的配置,还有遇到问题的解决方法;本次项目中遇到了很多的问题,查阅了很多的资料,最后都一一解决了(有的不一定是解决,只是换了一种方式实现),同时自己也收获了,成长了。
对于项目本身,完成了基本功能,实现了时间日期的显示,实时天气的显示,闹钟的设置和提醒,城市的设置。但是,还有一些功能由于某些原因未能在本次项目中实现,后续将继续完成既定任务。
最后,再次感谢得捷电子和EEWORLD提供这次机会,再次感谢。
多功能网络天气时钟.doc
(790 KB, 下载次数: 1)
|