0.目录
-
项目要求
-
实现功能
-
项目分析
-
天气服务
-
ESP32开发
-
RP2040开发
-
成果展示
-
心得体会
-
附件
1.项目要求
制作一个简单的气象台,能够实时播放5个城市的气象信息。
2.实现功能
-
RP2040 Game Kit板通过提供的ESP32-S2的WiFi模块连接网络
-
在RP2040 Game Kit上显示某一个城市的气象信息 - 时间、温度、湿度、气压....
-
通过RP2040 Game Kit上的按键能够切换显示不同城市的信息 ,比如:上海、苏州、东京、洛杉矶、伦敦
3.项目分析
RP2040本身不具备联网功能,需利用ESP32-S2模块实现互联网访问,RP2040 Game Kit与ESP32-S2通过串口进行数据传输。天气服务使用和风天气,和风天气相较于目前主流的心知天气可以免费获得更多的天气数据。
4.天气服务
和风天气(实时天气 - API | 和风天气开发平台 (qweather.com))中的实时天气API文档对API接口进行了详细介绍。可以注册一个免费开发版账号,然后上传身份证后升级为开发者版本,API访问量即可达到16700次/天,即11.6次/分,完全可以满足我们的项目需要。
和风天气的API请求URL为(https://devapi.qweather.com/v7/weather/now?[请求参数]),文档中请求参数与key、location、lang、unit共四项,其中key与location为必选项,将语言lang设为英文en方便后续处理,单位unit为公制单位。
注意:实际使用中由于V7版本默认对返回数据进行了压缩,需要再添加一项禁止压缩的参数gzip=n,否则后续ESP32无法处理。
返回数据如下,实况数据均为近实时数据,相比真实的物理世界会5-20分钟的延迟。
// 北京实况天气
// 商业版 https://api.qweather.com/v7/weather/now?location=101010100&key=你的KEY
// 开发版 https://devapi.qweather.com/v7/weather/now?location=101010100&key=你的KEY
{
"code": "200",
"updateTime": "2020-06-30T22:00+08:00",
"fxLink": "http://hfx.link/2ax1",
"now": {
"obsTime": "2020-06-30T21:40+08:00",
"temp": "24",
"feelsLike": "26",
"icon": "101",
"text": "多云",
"wind360": "123",
"windDir": "东南风",
"windScale": "1",
"windSpeed": "3",
"humidity": "72",
"precip": "0.0",
"pressure": "1003",
"vis": "16",
"cloud": "10",
"dew": "21"
},
"refer": {
"sources": [
"QWeather",
"NMC",
"ECMWF"
],
"license": [
"commercial license"
]
}
}
下表为返回数据含义。
code
API状态码,具体含义请参考状态码 updateTime
当前API的最近更新时间 fxLink
当前数据的响应式页面,便于嵌入网站或应用 now.obsTime
数据观测时间 now.temp
温度,默认单位:摄氏度 now.feelsLike
体感温度,默认单位:摄氏度 now.icon
天气状况和图标的代码,图标可通过天气状况和图标下载 now.text
天气状况的文字描述,包括阴晴雨雪等天气状态的描述 now.wind360
风向360角度 now.windDir
风向 now.windScale
风力等级 now.windSpeed
风速,公里/小时 now.humidity
相对湿度,百分比数值 now.precip
当前小时累计降水量,默认单位:毫米 now.pressure
大气压强,默认单位:百帕 now.vis
能见度,默认单位:公里 now.cloud
云量,百分比数值。可能为空 now.dew
露点温度。可能为空 refer.sources
原始数据来源,或数据源说明,可能为空 refer.license
数据许可或版权声明,可能为空
code
API状态码,具体含义请参考状态码 updateTime
当前API的最近更新时间 fxLink
当前数据的响应式页面,便于嵌入网站或应用 now.obsTime
数据观测时间 now.temp
温度,默认单位:摄氏度 now.feelsLike
体感温度,默认单位:摄氏度 now.icon
天气状况和图标的代码,图标可通过天气状况和图标下载 now.text
天气状况的文字描述,包括阴晴雨雪等天气状态的描述 now.wind360
风向360角度 now.windDir
风向 now.windScale
风力等级 now.windSpeed
风速,公里/小时 now.humidity
相对湿度,百分比数值 now.precip
当前小时累计降水量,默认单位:毫米 now.pressure
大气压强,默认单位:百帕 now.vis
能见度,默认单位:公里 now.cloud
云量,百分比数值。可能为空 now.dew
露点温度。可能为空 refer.sources
原始数据来源,或数据源说明,可能为空 refer.license
数据许可或版权声明,可能为空。
5.ESP32开发
ESP32使用Arduino进行开发,创建工程后安装ArduinoJson库(本工程为6.19.4版本)对返回的数据进行解析。
wifi连接代码如下。
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
获取天气数据代码如下。
void getLivesWratherData(HeFengCurrentData *data, String city)
{
std::unique_ptr<WiFiClientSecure> client(new WiFiClientSecure);
client->setInsecure();
HTTPClient https;
String url = getUrl(privateKey, city);
if (https.begin(*client, url))
{
int httpCode = https.GET();
if (httpCode > 0)
{
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY)
{
String respone = https.getString();
deserializeWeatherData(data, respone, city);
}
}
else
{
Serial.printf("[HTTPS] GET... failed, error: %s\r\n", https.errorToString(httpCode).c_str());
}
https.end();
}
else
{
Serial.printf("[HTTPS] Unable to connect\r\n");
}
}
由于和风天气API不能返回实时天气,还需要通过NTP服务器对实时时间进行获取。
NTP服务器选择CN.NTP.ORG.CN,NTP服务器与很多,可以通过以下网页查看NTP服务器(公共 NTP 网络时间服务器地址大全 Public NTP Server - DNS.iCoA.CN),其返回数据格式基本一致。
NTP服务器配置代码。
// NTP授时服务器
const char *ntpServer = "CN.NTP.ORG.CN"; // NTP server
const long gmtOffset_sec = 8 * 3600; // GMT offset in seconds
const int daylightOffset_sec = 0; // daylight saving offset in seconds
// 配置NTP服务器
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
获取到的时间和天气数据通过串口1进行发送,波特率115200bits/s,通信协议如下。
内容长度(字节)备注帧起始标志1固定为0x00年1从1900年开始月1范围[0,11]日1范围[1,31]时1范围[0,23]分1范围[0,59]秒1范围[0,59]星期1范围[0,6](周日为第一天)城市代码4行政区划代码温度1单位:摄氏度体感温度1单位:摄氏度天气2天气图标代码风向2风向360角度风力1风力等级风速1单位:公里/小时湿度1相对湿度,百分比数值降水量4当前小时累计降水量,单位:毫米气压2单位:百帕能见度1单位:公里云量1百分比数值露点温度1可能为空帧结束标志1固定为0xFF
ESP32接收到城市代码后进行一次天气与时间更新,接收的数据帧格式见RP2040开发部分。
ESP32上传固件时需要先按住BOOT再连接至电脑,或者按住BOOT再按下RST。
6.RP2040开发
RP2040使用PlatformIO进行开发,开发板选择Raspberry Pi Pico,安装TFT_eSPI库(本工程为2.4.30版本)进行屏幕驱动,具体配置见代码附件。
RP2040使用串口1,配置为16与17引脚(在pins_arduino.h文件中配置)。
// Serial
#define PIN_SERIAL_TX (16u)
#define PIN_SERIAL_RX (17u)
RP2040在每次按下按键时进行按键中断,中断后更改目前的城市代码,并发送一次请求给ESP32,发送请求的代码如下。
void requestWeatherData(int cityCode)
{
itoa(cityCode, txBuf, 10);
txBuf[9] = '\r';
txBuf[10] = '\n';
Serial1.println(txBuf);
}
RP2040每5分钟自动请求一次天气与时间数据,对本地时间进行校准,同时刷新天气数据。
由于进行全局刷新屏幕会有闪烁现象,因此采用局部刷新方式,设立以下标志位,只有当数据发生变化时将标志位置1,局部刷新后将标志位重新置0。
//局部刷新标志位
bool flag_refreshSec = false;
bool flag_refreshMin = false;
bool flag_refreshHour = false;
bool flag_refreshDay = false;
bool flag_refreshMonth = false;
bool flag_refreshYear = false;
bool flag_refreshWeek = false;
bool flag_refreshWeather = false;
bool flag_refreshHumidity = false;
bool flag_refreshTemp = false;
bool flag_refreshPressure = false;
bool flag_refreshCity = false;
RP2040的BOOT键与按键B复用,按住BOOT后重启进入烧录模式。
需要注意的是,RP2040的后方连接排针后下角为1脚。
7.成果展示
实物如图所示。
8.心得体会
-
ESP32使用PlatformIO开发体验较好,相较于Arduino功能更加完善。
-
RP2040使用microPython的开发效率比较低,因此选择了C++。
-
和风天气的免费版数据更加全面,API访问次数虽有限制,但仍可以满足需求,相较于和风天气与高德天气API使用体验更好。
-
RP2040的按键未做消抖,有时候会发生误触。
9.附件
附件见百度网盘
链接:https://pan.baidu.com/s/1RsR1okFQ2NftGWrr_i66CQ?pwd=sqfk
提取码:sqfk