Demo 概述
这个 Demo 展示了如何使用 Wio Terminal 天气小助手,Wio Terminal 通过 I2C 接口连接温湿度传感器 AHT10 通过对室内环境温湿度的实时监测,同时通过 WiFi 网络可以在未来三天获取当地天气信息和天气预报,并使用按钮切换显示界面。
- 启动自动联网获取现场天气和预报天气
- 室外和室内的温湿度同时显示在主界面上
- 按上左键手动更新天气信息
- 可通过五向开关 Left 和 Right 查看未来几天的天气预测
- 实现温湿度传感器的实时读取和显示
- 从 Web API 获取天气信息并进行分析 JSON 数据
- 1 x Wio Terminal
- 1x AHT10 传感器模块
安装依赖库
本示例 Demo 依赖 库、 库、 库和 库:
LCD
库在安装 Seeed SAMD Boards 库时已经包含了,可以参考 Wio Terminal 开发环境。ArduinoJson
库可以在 GitHub 仓库下载,在 Arduino IDE 点击 项目 > 加载库 > 添加 .ZIP 库… 可添加库。AHTX0
库可以在 GitHub 仓库下载,在 Arduino IDE 点击 项目 > 加载库 > 添加 .ZIP 库… 可添加库。Bounce2
库可以在 GitHub 仓库下载,在 Arduino IDE 点击 项目 > 加载库 > 添加 .ZIP 库… 可添加库。
提示:这些库也可以在 Arduino IDE 搜索并安装库管理器。
另外,我们也用过 Free_Fonts.h
库中提供的一些免费字体一些免费字体,并将其放在这里 Arduino 工程中。
读取传感器
读取 AHT10 传感器温湿度数据的示例代码如下:
#include <Adafruit_AHTX0.h> Adafruit_AHTX0 aht; void setup() {
Serial.begin(115200); if (! aht.begin()) {
while (1) delay(10); } } void loop() {
sensors_event_t humidity, temp; // populate temp and humidity objects with fresh data aht.getEvent(&humidity, &temp); Serial.print("Temperature: "); Serial.print(temp.temperature); Serial.print("Humidity: "); Serial.print(humidity.relative_humidity);
delay(500);
}
天气 API
有很多提供天气信息的 Web API,可以参考《一些好用的天气 API》,本文使用高德地图 API 获取实时天气及天气预测。GET 请求的 URL 如下:
(当天)
https://restapi.amap.com/v3/weather/weatherInfo?city=441802&key=yourkey
(未来三天)
https://restapi.amap.com/v3/weather/weatherInfo?city=441802&key=yourkey&extensions=all
参数说明:
city
是城市编码,比如 441802 代表广州;key
是应用对应的代码,需要在平台申请(提示:将yourkey
替换为你申请的 Key 代码);extensions
表示获取类型,缺省值是base
,表示获取实况天气,all
表示获取预报天气;output
表示返回格式,可选 JSON 或 XML,默认返回 JSON 格式数据。
以实时天气 API 为例,返回的 JSON 数据如下:
{
"status":"1",
"count":"1",
"info":"OK",
"infocode":"10000",
"lives":[
{
"province":"广东",
"city":"广州市",
"adcode":"440100",
"weather":"晴",
"temperature":"17",
"winddirection":"北",
"windpower":"≤3",
"humidity":"64",
"reporttime":"2021-12-12 19:00:44"
}
]
}
完整代码
提示:将下面代码中的 ssid
和 password
替换成你的 WiFi 网络;将 URL_BASE
和 URL_ALL
中的 cityCode
替换成需要查询的城市,将 yourKey
替换成你的 Key。
另外,本 Demo 并未实现中文显示,如需显示中文字体,可参考 Wio Terminal LCD 中文显示。
#include <rpcWiFi.h> #include <HTTPClient.h> #include <WiFiClientSecure.h> #include <ArduinoJson.h> /* Display */ #include "Free_Fonts.h" #include "TFT_eSPI.h" /* Sensor */ #include <Adafruit_AHTX0.h> /* Button */ #include <Bounce2.h> // INSTANTIATE 3 Button OBJECT Bounce2::Button btnA = Bounce2::Button(); Bounce2::Button btnL = Bounce2::Button(); Bounce2::Button btnR = Bounce2::Button(); Adafruit_AHTX0 aht; TFT_eSPI tft; const char* ssid = "yourNetworkName"; const char* password = "yourNetworkPassword"; const char* URL_BASE = "https://restapi.amap.com/v3/weather/weatherInfo?city=cityCode&key=yourKey"; const char* URL_ALL = "https://restapi.amap.com/v3/weather/weatherInfo?city=cityCode&key=yourKey&extensions=all"; WiFiClientSecure client; #define STR_SIZE_MAX 16 typedef struct lives { char province[16]; char city[16]; char adcode[16]; char weather[16]; char temperature[16]; char humidity[16]; char winddirection[16]; char windpower[16]; char reporttime[16]; } lives_t; lives_t lives_data; typedef struct forecasts { char date[16]; char week[16]; char dayweather[16]; char nightweather[16]; char daytemp[16]; char nighttemp[16]; char daywind[16]; char nightwind[16]; char daypower[16]; char nightpower[16]; } forecasts_t; #define FORECASTS_SIZE 4 forecasts_t forecasts_data[FORECASTS_SIZE]; enum { PAGE_1 = 1, PAGE_2 = 2, PAGE_3 = 3, PAGE_4 = 4, PAGE_5 = 5, PAGE_MAX = PAGE_5 }; int currentPage = PAGE_1; boolean pageChanged = false; boolean update_flag = true; void setup() { btnA.attach( WIO_KEY_C , INPUT_PULLUP ); btnL.attach( WIO_5S_LEFT , INPUT_PULLUP ); btnR.attach( WIO_5S_RIGHT , INPUT_PULLUP ); btnA.interval(5); btnL.interval(5); btnR.interval(5); btnA.setPressedState(LOW); btnL.setPressedState(LOW); btnR.setPressedState(LOW); Serial.begin(115200); if (! aht.begin()) { Serial.println("Could not find AHT? Check wiring"); while (1) delay(10); } Serial.println("AHT10 or AHT20 found"); tft.init(); tft.setRotation(3); tft.fillScreen(tft.color565(24,15,60)); tft.fillScreen(TFT_NAVY); tft.setFreeFont(FMB12); tft.setCursor((320 - tft.textWidth("Funpack Weather Box"))/2, 100); tft.print("Funpack Weather Box"); tft.setFreeFont(FM9); tft.setTextColor(TFT_LIGHTGREY); tft.setCursor((320 - tft.textWidth("Connecting WiFi..."))/2, 180); tft.print("Connecting WiFi..."); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { //Check for the connection delay(500); Serial.println("Connecting WiFi..."); } Serial.print("Connected to the WiFi network with IP: "); Serial.println(WiFi.localIP()); //client.setCACert(test_root_ca); if(&client) { getWeatherLives(); getWeatherForecasts(); } drawWeatherLivePage(lives_data); } void loop() { btnA.update(); btnL.update(); btnR.update(); if ( btnA.pressed() ) { pageChanged = true; getWeatherLives(); getWeatherForecasts(); currentPage = PAGE_1; Serial.print("updated!"); } if ( btnL.pressed() ) { pageChanged = true; currentPage--; if (currentPage < PAGE_1) { currentPage = PAGE_MAX; } Serial.print("prev page: ");Serial.println(currentPage); } if ( btnR.pressed() ) { pageChanged = true; currentPage++; if (currentPage > PAGE_MAX) { currentPage = PAGE_1; } Serial.print("next page: ");Serial.println(currentPage); } switch (currentPage) { case PAGE_1: { static int cnt = 0; if (pageChanged) { drawWeatherLivePage(lives_data); updateSensorData(); } if (cnt++ % 100000 == 0) { updateSensorData(); } pageChanged = false; } break; case PAGE_2: { if (pageChanged) { drawWeatherForecastPage(&forecasts_data[0]); } pageChanged = false; } break; case PAGE_3: { if (pageChanged) { drawWeatherForecastPage(&forecasts_data[1]); } pageChanged = false; } break; case PAGE_4: { if (pageChanged) { drawWeatherForecastPage(&forecasts_data[2]); } pageChanged = false; } break; case PAGE_5: { if (pageChanged) { drawWeatherForecastPage(&forecasts_data[3]); } pageChanged = false; } break; default: break; } } void updateSensorData() { sensors_event_t humi, temp; aht.getEvent(&humi, &temp);// populate temp and humidity objects with fresh data drawTempValue(temp.temperature); drawHumiValue(humi.relative_humidity); } void drawTempValue(const float temp) { tft.setFreeFont(FMB24); tft.setTextColor(TFT_RED, tft.color565(40,40,86)); tft.drawString(String(temp, 1), 30, 140); } void drawHumiValue(const float humi) { tft.setFreeFont(FMB24); tft.setTextColor(TFT_GREEN, tft.color565(40,40,86)); tft.drawString(String(humi, 1), 180, 140); } void drawWeatherLivePage(lives_t &lives_data) { // -----------------LCD--------------------- tft.fillScreen(tft.color565(24,15,60)); tft.setFreeFont(FF17); tft.setTextColor(tft.color565(224,225,232)); tft.drawString("Funpack Weather Box", 10, 10); tft.setFreeFont(FMB9); if (0 == strcmp(lives_data.weather, "晴")) { tft.setTextColor(TFT_ORANGE); tft.drawString("sunny", 240, 10); } else if (0 == strcmp(lives_data.weather, "多云")) { tft.setTextColor(TFT_WHITE); tft.drawString("cloudy", 240, 10); } else if (0 == strcmp(lives_data.weather, "阴")) { tft.setTextColor(TFT_LIGHTGREY); tft.drawString("cloudy", 240, 10); } else if (0 == strcmp(lives_data.weather, "雨")) { tft.setTextColor(TFT_DARKCYAN); tft.drawString("rainy", 240, 10); } tft.fillRoundRect(10, 45, 145, 180, 5, tft.color565(40,40,86)); tft.fillRoundRect(165, 45, 145, 180, 5, tft.color565(40,40,86)); tft.setFreeFont(FM9); tft.setTextColor(TFT_WHITE); tft.drawString("Temperature", 25, 60); tft.drawString("Humidity", 195, 60); tft.setTextColor(TFT_DARKGREY); tft.drawString("degrees C", 35, 200); tft.drawString("% rH", 220, 200); tft.setFreeFont(FMB24); tft.setTextColor(TFT_RED, tft.color565(40,40,86)); tft.drawString(lives_data.temperature, 30, 100); Serial.println(lives_data.temperature); tft.setFreeFont(FMB24); tft.setTextColor(TFT_GREEN, tft.color565(40,40,86)); tft.drawString(lives_data.humidity, 180, 100); Serial.println(lives_data.humidity); } void drawWeatherForecastPage(forecasts_t *forecasts_data) { // -----------------LCD--------------------- tft.fillScreen(tft.color565(24,15,60)); tft.setFreeFont(FF17); tft.setTextColor(tft 标签:
wio传感器