概述
本项目基于Wio Terminal开发平台,通过板载WIFI模块联网,使用和风天气提供的免费API获取实时天气、空气质量及未来三天的变化情况,然后通过LVGL GUI在屏幕上进行显示。本文将对该项目的实现思路及关键技术细节进行描述。
项目来源
Funpack 第12期,任务二:
制作一个自动联网的天气预报仪,在设计界面显示温湿度、天气情况、空气质量以及未来三天内的天气变化。
本项目完成效果如下:

Wio Terminal平台
高度集成的设计
MCU, LCD, WIFI, BT, IMU, 麦克风, 蜂鸣器, microSD Card, 光传感器, 五向开关, 光传感器和红外发射器 (IR 940nm), 加密验证
由Microchip ATSAMD51P19提供支持
- ARM Cortex-M4F运行速度 120MHz (最高可达200MHz)
- 4 MB 外置闪存, 192 KB RAM
强大的无线连接
- 双频 2.4Ghz / 5Ghz Wi-Fi (802.11 a/b/g/n)
- BLE / BLE 5.0
软件支持
- Arduino
- MicroPython
Wio Terminal支持Arduino开发,虽然Arduino我已经听说10几年了,但实际上本项目才真正使用这个平台。我认为Arduino
最大的优点:我无需知道它具体是怎么实现的,但写几行应用代码它就可以跑起来了。
最大的缺点:虽然我只写了几行代码它就跑起来了,但我却完全不清楚它是怎么实现的。
基于Arduino这种特性,很多学生/爱好者都喜欢拿它来开发和学习。我认为是利弊并存的,可能它可以很容易让你实现一个应用而不用过多关心硬件底层,但却容易让你忽略了底层的基础知识学习。
方案设计
Wio Terminal板载资源丰富,无需而外硬件资源,便可以完成联网、显示功能了,因而该项目关键在于找到合适的天气API。选择和风天气API的原因是:
- 免费且门槛低,普通免费用户既可有1000次/天的请求额度。
- 满足题目需求,普通免费用户既可获取实时天气温湿度、空气质量、未来3天的天气预报。
- 有Arduino平台参考软件库,开发简单。
- 提供了天气图标字体库,可以很方便的进行天气图标显示。
开发平台
- 硬件平台:Wio Terminal
- 软件环境:VS Code / Arduino
联网方案
- 硬件:板载WIFI模块
- 软件库:rpcWifi / WiFiClientSecure
天气API
- 平台:和风天气,网址:https://dev.qweather.com/
- 软件库:ESP8266_Heweather,源码地址:https://github.com/Ldufan/ESP8266_Heweather
显示方案
- 硬件:板载2.4寸LCD
- GUI库:LVGL
环境搭建
Arduino虽然经过了10几年的发展,但是其开发环境仍然是一言难尽,没有跳转到函数实现的功能,没有代码提示、没有智能补全……。好在VS Code有Arduino插件,可以用它来开发、编译、下载。但我实测发现VS Code的Arduino编译下载做得并不好,所以我还是决定VS Code只用于编码,编译、下载、串口终端仍旧使用Arduino官方IDE,互补不足。
VS Code安装Arduino插件

添加库文件路径

虽然安装Arduino插件之后,用VS Code打开ion工程时,它会自动添加一些Arduino基本的库路径,但可能不全,或者有些库可能是我们后来自行安装的它并不知道。为了让VS Code能够索引到,则需要手动把库路径添加到c_cpp_properties.json文件中。
方案实现
WIFI联网
更新最新WIFI固件
按照Seed官方WIKI步骤操作升级最新WIFI固件。
联网代码
1
2
3
4
5WiFi.mode(WIFI_STA);
WiFi.disconnect();
Serial.println("Connecting to wifi...");
WiFi.begin(ssid,password);
LVGL初始化
TFT初始化
1
2tft.begin(); /* TFT init */
tft.setRotation(3); /* Landscape orientation */LVGL初始化
- 实现LVGL缓存刷新到TFT函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
uint16_t c;
tft.startWrite(); /* Start new TFT transaction */
tft.setAddrWindow(area->x1, area->y1, (area->x2 - area->x1 + 1), (area->y2 - area->y1 + 1)); /* set the working window */
for (int y = area->y1; y <= area->y2; y++) {
for (int x = area->x1; x <= area->x2; x++) {
c = color_p->full;
tft.writeColor(c, 1);
color_p++;
}
}
tft.endWrite(); /* terminate TFT transaction */
lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */
}- 初始化LVGL相关参数
1
2
3
4
5
6
7
8
9
10
11
12lv_init();
lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);
/*Initialize the display*/
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = 320;
disp_drv.ver_res = 240;
disp_drv.flush_cb = my_disp_flush;
disp_drv.buffer = &disp_buf;
lv_disp_drv_register(&disp_drv);- 启动一个5ms定时器中断,用于执行LVGL定时任务。
1
2TimerTc3.initialize(5000);//5ms
TimerTc3.attachInterrupt(lv_timer_int_handler);- 定时中断中执行如下LVGL任务
1
2
3
4
5void lv_timer_int_handler(void)
{
lv_tick_handler();
lv_task_handler(); /* let the GUI do its work */
}这样做的好处是,你可以只管更新LVGL的组件、显示内容,在主循环中可以正常使用delay函数,而无需担心影响LVGL的显示刷新。
和风API获取天气
官方提供的参考Arduino库本身提供了获取和解析实时天气、空气质量、未来三天预报功能,但是适用于ESP8266平台的,要想在Wio Terminal上使用,需要做一点简单的修改。
以获取实时天气的WeatherNow.cpp文件为例(其它类似),改动点如下:

修改WiFi Client的定义
client必须定义为全局变量,若在get()函数中定义为局部变量,则调用get()函数时会卡死。由于Arduino无法单步调试,我完全不知道发生了什么问题,推测应该是堆栈溢出这类吧。
初始化配置增加根证书参数
我看ESP8266的代码,可以将Client设置为非安全模式,不需要服务器根证书。但在Wio Terminal上没找到这个函数,所以还是老老实实在https.get()前进行根证书配置。
和风服务器根证书获取
使用Google浏览器,输入API获取一次天气,就可以参考这篇文章导出根证书字符串了。

值得提醒的是,查看和导出证书一定要选到根那级,不要选到下面qweather.com这级。
天气图标显示
和风API获取天气时,有个参数是ICON编号,每个编号对应一个图标。和风已在GitHub上提供了所有天气图标的字体库。要想在LVGL上使用该图标库,还需要将字体库转换成C代码。
LVGL官方转换网址为:https://lvgl.io/tools/fontconverter。上传图标字体库ttf文件,填写相关参数,既可得到生成的字体C文件。

和风API中得到的ICON是101/102这样的编号,要想根据编号对应上相应的图标,还需要做一些转换。
![]()
字体库预览,可使用网站:http://blog.luckly-mjw.cn/tool-show/iconfont-preview/index.html。
图标名称对应UTF-8编码
1
2
3
4
5
...图标编号对应图标名称
1
2
3
4
5
6
7
8
9
10inline const char* qw_get_icon_utf8_code(int iconcode)
{
switch(iconcode)
{
case 100: return(QW_SYMBOL_100); break;
case 101: return(QW_SYMBOL_101); break;
...
}
return (QW_SYMBOL_DUMMY);
}
这样就可以很容易用LVGL显示天气图标了。
主循环
界面的整体UI,我使用的是LVGL建立了1个TableView,添加了3个标签。其中标签1用于显示当前实时天气、温湿度、空气质量,标签2用于显示未来三天天气变化,标签3则用于显示了项目源代码获取方式。
所以主循环事情则比较简单,主要处理:
- 处理按键,切换TableView各个标签的显示
- 每隔5分钟调用API更新天气信息,并更新到UI中
1 | void loop() { |
小结
本文阐述了基于Wio Terminal联网天气预报仪的设计思路及关键实现细节,如仍有描述不清楚的地方,欢迎下载源码共同探讨。项目源码,请扫码关注下方公众号,并回复“SmartWeather”获取。
