一、Wio Terminal板卡介绍
Wio Terminal基于SAMD51的控制器,支持无线连接,蓝牙和Wi-Fi,为物联网提供开发平台。
Wio Terminal自身配有一个2.4英寸 LCD屏幕, 板载IMU(LIS3DHTR),麦克风,蜂鸣器,microSD卡槽,光传感器和940nm红外发射器。 除了这些它还有两个用于Grove生态系统的多功能Grove接口和兼容Raspberry pi的40个GPIO引脚,用于支持更多附加组件。
二、使用Wio Terminal完成了任务二
制作了一个自动联网的天气预报仪,在设计界面显示温度、湿度、天气情况、空气质量以及未来三天内的天气变化。
三、主要代码及分析
void showfirstdata() {
tft.fillScreen(TFT_BLACK);
tft.setFreeFont(FF17);
tft.setTextColor(tft.color565(224,225,232));
tft.drawString(date,20,10);
tft.fillRoundRect(10, 30, 300, 40, 5, tft.color565(173,216,230));
tft.fillRoundRect(10, 75, 300, 40, 5, tft.color565(173,216,230));
tft.fillRoundRect(10, 120, 300, 40, 5, tft.color565(173,216,230));
tft.fillRoundRect(10, 175, 300, 55, 5, tft.color565(173,216,230));
tft.setFreeFont(FM9);
tft.setTextColor(TFT_RED);
tft.drawString("Temperature:", 25, 40);
tft.setTextColor(TFT_RED);
tft.drawString("Weather:",25, 85);
tft.setTextColor(TFT_RED);
tft.drawString("Quality:",25, 130);
tft.setTextColor(TFT_RED);
tft.drawString("Night Weather:",25, 185);
tft.setFreeFont(FMB12);
tft.setTextColor(TFT_RED);
tft.drawFloat(tem,1 , 180, 40);//获取温度
tft.drawString("C",230, 40);
tft.setTextColor(tft.color565(224,225,232));
tft.setTextColor(TFT_RED);
tft.drawString(dw, 160, 85);//获取天气状况
tft.setFreeFont(FF9);
tft.setTextColor(TFT_RED);
tft.drawString(quality0,160,130);
tft.setTextColor(TFT_RED);
tft.drawString(nw,160, 210); //获取晚上天气
}
页面一,连接心知天气,接收数据,然后通过tft库中的代码显示出来,其中显示了,日期,天气温度,天气状况,空气质量,晚上天气状况。
void p2lcd()
{
digitalWrite(LCD_BACKLIGHT, HIGH);
tft.fillScreen(TFT_OLIVE);
tft.fillRoundRect(10, 45, 80, 40, 5, tft.color565(40,40,86));
tft.fillRoundRect(120, 45, 80, 40, 5, tft.color565(40,40,86));
tft.fillRoundRect(230, 45, 80, 40, 5, tft.color565(40,40,86));
//
tft.fillRoundRect(10, 100, 80, 120, 5, tft.color565(40,40,86));
tft.fillRoundRect(120, 100, 80, 120, 5, tft.color565(40,40,86));
tft.fillRoundRect(230, 100, 80, 120, 5, tft.color565(40,40,86));
//
tft.setFreeFont(FF10);
tft.drawString("Wuhu"+ date,25, 10);
tft.setTextColor(tft.color565(224,225,232));
tft.setFreeFont(FF10);
tft.drawString("Today", 10, 55);
tft.drawString("Tomorrow",100, 55);
tft.drawString("TDAT",245, 55);//The Day After Tomorrow
tft.setTextColor(tft.color565(0,225,0));
tft.setFreeFont(FF9);
tft.drawString(d0,20,110);
tft.drawString(d1,130,110);
tft.drawString(d2,240,110);
tft.setTextColor(tft.color565(0,191,255));
tft.setFreeFont(FF10);
tft.drawFloat(t0,2,20,135);
tft.drawFloat(t1,2,130,135);
tft.drawFloat(t2,2,240,135);
tft.setFreeFont(FMB12);
tft.drawString("℃",26,135);
tft.drawString("℃",136,135);
tft.drawString("℃",246,135);
tft.setTextColor(tft.color565(238,221,130));
tft.setFreeFont(FF9);
tft.drawString(w0,20,160);
tft.drawString(w1,130,160);
tft.drawString(w2,240,160);
tft.drawFloat(wa0,0,40,160);
tft.drawFloat(wa1,0,150,160);
tft.drawFloat(wa2,0,260,160);
tft.setTextColor(tft.color565(173,216,230));
tft.setFreeFont(FF9);
tft.drawFloat(h0,1,20,180);
tft.drawFloat(h1,1,130,180);
tft.drawFloat(h2,1,240,180);
tft.drawString("RH",65,180);
tft.drawString("RH",175,180);
tft.drawString("RH",285,180);
tft.setTextColor(tft.color565(176,196,222));
tft.setFreeFont(FF9);
tft.drawFloat(r0,2,20,200);
tft.drawFloat(r1,2,130,200);
tft.drawFloat(r2,2,240,200);
}
页面二,显示今天的API值,PM2.5以及一氧化碳等空气指数。
void p3lcd()
{
digitalWrite(LCD_BACKLIGHT, HIGH);
tft.fillScreen(TFT_OLIVE);
tft.fillRoundRect(10, 35, 300, 40, 5, tft.color565(40,40,86));
//
tft.fillRoundRect(10, 90, 300, 40, 5, tft.color565(40,40,86));
tft.fillRoundRect(10, 140, 300, 40, 5, tft.color565(40,40,86));
tft.fillRoundRect(10, 190, 300, 40, 5, tft.color565(40,40,86));
//
tft.setFreeFont(FF10);
tft.drawString("Wuhu" + date,25, 10);
tft.setTextColor(tft.color565(224,225,232));
tft.setFreeFont(FF10);
tft.drawString(" Today", 5, 40);
tft.setTextColor(tft.color565(0,225,0));
tft.setFreeFont(FF9);
tft.drawString("API:",20,100);
tft.drawFloat(api0,1,70,100);
tft.setTextColor(tft.color565(0,191,255));
tft.setFreeFont(FF10);
tft.drawString("PM2.5:",20,150);
tft.drawFloat(pm25_0,1,110,150);
tft.setTextColor(tft.color565(238,221,130));
tft.setFreeFont(FF9);
tft.drawString("CO_1:",20,200);
tft.drawFloat(co0,1,70,200);
}
页面三,显示未来三天的天气状况。
void httpRequest1(String reqRes){
WiFiClient client;
String httpRequest = String("GET ") + reqRes + " HTTP/1.1\r\n" + // 建立http请求信息
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n";
if (client.connect(host, 80)){
client.print(httpRequest); // 向服务器发送http请求信息
String status_response = client.readStringUntil('\n'); // 获取并显示服务器响应状态行
if(client.find("\r\n\r\n")); // 使用find跳过HTTP响应头
parseInfo1(client); // 利用ArduinoJson库解析心知天气响应信息
}
else {
Serial.println(" connection failed!");
}
client.stop(); //断开客户端与服务器连接工作
}
void httpRequest2(String reqRes){
WiFiClient client;
String httpRequest = String("GET ") + reqRes + " HTTP/1.1\r\n" + // 建立http请求信息
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n";
if (client.connect(host, 80)){
client.print(httpRequest); // 向服务器发送http请求信息
String status_response = client.readStringUntil('\n'); // 获取并显示服务器响应状态行
if(client.find("\r\n\r\n")); // 使用find跳过HTTP响应头
parseInfo2(client); // 利用ArduinoJson库解析心知天气响应信息
}
else {
Serial.println(" connection failed!");
}
client.stop(); //断开客户端与服务器连接工作
}
与心知天气连接。
void parseInfo1(WiFiClient client){
const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(3) + JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 3*JSON_OBJECT_SIZE(14) + 860;
DynamicJsonDocument doc(capacity);
deserializeJson(doc, client);
JsonObject results_0 = doc["results"][0];
JsonArray results_0_daily = results_0["daily"];
JsonObject results_0_daily_0 = results_0_daily[0];
const char* results_0_daily_0_date = results_0_daily_0["date"];
const char* results_0_daily_0_text_day = results_0_daily_0["text_day"];
const char* results_0_daily_0_code_day = results_0_daily_0["code_day"];
const char* results_0_daily_0_text_night = results_0_daily_0["text_night"];
const char* results_0_daily_0_code_night = results_0_daily_0["code_night"];
const char* results_0_daily_0_high = results_0_daily_0["high"];
const char* results_0_daily_0_low = results_0_daily_0["low"];
const char* results_0_daily_0_rainfall = results_0_daily_0["rainfall"];
const char* results_0_daily_0_precip = results_0_daily_0["precip"];
const char* results_0_daily_0_wind_direction = results_0_daily_0["wind_direction"];
const char* results_0_daily_0_wind_direction_degree = results_0_daily_0["wind_direction_degree"];
const char* results_0_daily_0_wind_speed = results_0_daily_0["wind_speed"];
const char* results_0_daily_0_wind_scale = results_0_daily_0["wind_scale"];
const char* results_0_daily_0_humidity = results_0_daily_0["humidity"];
JsonObject results_0_daily_1 = results_0_daily[1];
const char* results_0_daily_1_date = results_0_daily_1["date"];
const char* results_0_daily_1_text_day = results_0_daily_1["text_day"];
const char* results_0_daily_1_code_day = results_0_daily_1["code_day"];
const char* results_0_daily_1_text_night = results_0_daily_1["text_night"];
const char* results_0_daily_1_code_night = results_0_daily_1["code_night"];
const char* results_0_daily_1_high = results_0_daily_1["high"];
const char* results_0_daily_1_low = results_0_daily_1["low"];
const char* results_0_daily_1_rainfall = results_0_daily_1["rainfall"];
const char* results_0_daily_1_precip = results_0_daily_1["precip"];
const char* results_0_daily_1_wind_direction = results_0_daily_1["wind_direction"];
const char* results_0_daily_1_wind_direction_degree = results_0_daily_1["wind_direction_degree"];
const char* results_0_daily_1_wind_speed = results_0_daily_1["wind_speed"];
const char* results_0_daily_1_wind_scale = results_0_daily_1["wind_scale"];
const char* results_0_daily_1_humidity = results_0_daily_1["humidity"];
JsonObject results_0_daily_2 = results_0_daily[2];
const char* results_0_daily_2_date = results_0_daily_2["date"];
const char* results_0_daily_2_text_day = results_0_daily_2["text_day"];
const char* results_0_daily_2_code_day = results_0_daily_2["code_day"];
const char* results_0_daily_2_text_night = results_0_daily_2["text_night"];
const char* results_0_daily_2_code_night = results_0_daily_2["code_night"];
const char* results_0_daily_2_high = results_0_daily_2["high"];
const char* results_0_daily_2_low = results_0_daily_2["low"];
const char* results_0_daily_2_rainfall = results_0_daily_2["rainfall"];
const char* results_0_daily_2_precip = results_0_daily_2["precip"];
const char* results_0_daily_2_wind_direction = results_0_daily_2["wind_direction"];
const char* results_0_daily_2_wind_direction_degree = results_0_daily_2["wind_direction_degree"];
const char* results_0_daily_2_wind_speed = results_0_daily_2["wind_speed"];
const char* results_0_daily_2_wind_scale = results_0_daily_2["wind_scale"];
const char* results_0_daily_2_humidity = results_0_daily_2["humidity"];
const char* results_0_last_update = results_0["last_update"];
// 从以上信息中摘选几个通过串口监视器显示
String results_0_daily_0_date_str = results_0_daily_0["date"].as<String>();
String results_0_daily_0_text_day_str = results_0_daily_0["text_day"].as<String>();
int results_0_daily_0_code_day_int = results_0_daily_0["code_day"].as<int>();
String results_0_daily_0_text_night_str = results_0_daily_0["text_night"].as<String>();
int results_0_daily_0_code_night_int = results_0_daily_0["code_night"].as<int>();
int results_0_daily_0_high_int = results_0_daily_0["high"].as<int>();
int results_0_daily_0_low_int = results_0_daily_0["low"].as<int>();
String results_0_last_update_str = results_0["last_update"].as<String>();
//page2
String results_0_daily_1_text_day_str = results_0_daily_1["text_day"].as<String>();
String results_0_daily_2_text_day_str = results_0_daily_2["text_day"].as<String>();
int results_0_daily_1_high_int = results_0_daily_1["high"].as<int>();
int results_0_daily_1_low_int = results_0_daily_1["low"].as<int>();
int results_0_daily_2_high_int = results_0_daily_2["high"].as<int>();
int results_0_daily_2_low_int = results_0_daily_2["low"].as<int>();
String results_0_daily_0_text_direction_str = results_0_daily_0["wind_direction"].as<String>();
String results_0_daily_1_text_direction_str = results_0_daily_0["wind_direction"].as<String>();
String results_0_daily_2_text_direction_str = results_0_daily_0["wind_direction"].as<String>();
int results_0_daily_0_direction__angle_int=results_0_daily_0["wind_direction_degree"].as<int>();
int results_0_daily_1_direction__angle_int=results_0_daily_1["wind_direction_degree"].as<int>();
int results_0_daily_2_direction__angle_int=results_0_daily_2["wind_direction_degree"].as<int>();
int results_0_daily_0_humidity_int = results_0_daily_0["humidity"].as<int>();
int results_0_daily_1_humidity_int = results_0_daily_1["humidity"].as<int>();
int results_0_daily_2_humidity_int = results_0_daily_2["humidity"].as<int>();
int results_0_daily_0_rainfall_String = results_0_daily_0["rainfall"].as<int>();
int results_0_daily_1_rainfall_String = results_0_daily_1["rainfall"].as<int>();
int results_0_daily_2_rainfall_String = results_0_daily_2["rainfall"].as<int>();
if(results_0_daily_0_high_int!=0)
{
date=results_0_daily_0_date_str;
tem=(results_0_daily_0_high_int+results_0_daily_0_low_int)/2;
dw=results_0_daily_0_text_day_str;
nw=results_0_daily_0_text_night_str;
//page2
d0=results_0_daily_0_text_day_str;
d1=results_0_daily_1_text_day_str;
d2=results_0_daily_2_text_day_str;
t0=(results_0_daily_0_high_int+results_0_daily_0_low_int)/2;
t1=(results_0_daily_1_high_int+results_0_daily_1_low_int)/2;
t2=(results_0_daily_2_high_int+results_0_daily_2_low_int)/2;
w0=results_0_daily_0_text_direction_str;
w1=results_0_daily_1_text_direction_str;
w2=results_0_daily_2_text_direction_str;
wa0=results_0_daily_0_direction__angle_int;
wa1=results_0_daily_1_direction__angle_int;
wa2=results_0_daily_2_direction__angle_int;
h0=results_0_daily_0_humidity_int;
h1=results_0_daily_1_humidity_int;
h2=results_0_daily_2_humidity_int;
}
}
void parseInfo2(WiFiClient client){
const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(5) + JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 5*JSON_OBJECT_SIZE(9) + 720;
DynamicJsonDocument doc(capacity);
deserializeJson(doc, client);
JsonObject results_0 = doc["results"][0];
JsonObject results_0_location = results_0["location"];
const char* results_0_location_id = results_0_location["id"]; // "WTS4JZ3WMZMC"
const char* results_0_location_name = results_0_location["name"]; // "Wuhu"
const char* results_0_location_country = results_0_location["country"]; // "CN"
const char* results_0_location_path = results_0_location["path"]; // "Wuhu,Wuhu,Anhui,China"
const char* results_0_location_timezone = results_0_location["timezone"]; // "Asia/Shanghai"
const char* results_0_location_timezone_offset = results_0_location["timezone_offset"]; // "+08:00"
JsonArray results_0_daily = results_0["daily"];
JsonObject results_0_daily_0 = results_0_daily[0];
const char* results_0_daily_0_aqi = results_0_daily_0["aqi"]; // "135"
const char* results_0_daily_0_pm25 = results_0_daily_0["pm25"]; // "90"
const char* results_0_daily_0_pm10 = results_0_daily_0["pm10"]; // "221"
const char* results_0_daily_0_so2 = results_0_daily_0["so2"]; // "10"
const char* results_0_daily_0_no2 = results_0_daily_0["no2"]; // "53"
const char* results_0_daily_0_co = results_0_daily_0["co"]; // "0.913"
const char* results_0_daily_0_o3 = results_0_daily_0["o3"]; // "39"
const char* results_0_daily_0_date = results_0_daily_0["date"]; // "2021-12-11"
const char* results_0_daily_0_quality = results_0_daily_0["quality"]; // "Unhealthy for Sensitive Groups"
JsonObject results_0_daily_1 = results_0_daily[1];
const char* results_0_daily_1_aqi = results_0_daily_1["aqi"]; // "94"
const char* results_0_daily_1_pm25 = results_0_daily_1["pm25"]; // "70"
const char* results_0_daily_1_pm10 = results_0_daily_1["pm10"]; // "129"
const char* results_0_daily_1_so2 = results_0_daily_1["so2"]; // "11"
const char* results_0_daily_1_no2 = results_0_daily_1["no2"]; // "59"
const char* results_0_daily_1_co = results_0_daily_1["co"]; // "1.039"
const char* results_0_daily_1_o3 = results_0_daily_1["o3"]; // "8"
const char* results_0_daily_1_date = results_0_daily_1["date"]; // "2021-12-12"
const char* results_0_daily_1_quality = results_0_daily_1["quality"]; // "Moderate"
JsonObject results_0_daily_2 = results_0_daily[2];
const char* results_0_daily_2_aqi = results_0_daily_2["aqi"]; // "74"
const char* results_0_daily_2_pm25 = results_0_daily_2["pm25"]; // "31"
const char* results_0_daily_2_pm10 = results_0_daily_2["pm10"]; // "97"
const char* results_0_daily_2_so2 = results_0_daily_2["so2"]; // "10"
const char* results_0_daily_2_no2 = results_0_daily_2["no2"]; // "45"
const char* results_0_daily_2_co = results_0_daily_2["co"]; // "0.600"
const char* results_0_daily_2_o3 = results_0_daily_2["o3"]; // "56"
const char* results_0_daily_2_date = results_0_daily_2["date"]; // "2021-12-13"
const char* results_0_daily_2_quality = results_0_daily_2["quality"]; // "Moderate"
JsonObject results_0_daily_3 = results_0_daily[3];
const char* results_0_daily_3_aqi = results_0_daily_3["aqi"]; // "72"
const char* results_0_daily_3_pm25 = results_0_daily_3["pm25"]; // "45"
const char* results_0_daily_3_pm10 = results_0_daily_3["pm10"]; // "88"
const char* results_0_daily_3_so2 = results_0_daily_3["so2"]; // "13"
const char* results_0_daily_3_no2 = results_0_daily_3["no2"]; // "57"
const char* results_0_daily_3_co = results_0_daily_3["co"]; // "0.733"
const char* results_0_daily_3_o3 = results_0_daily_3["o3"]; // "43"
const char* results_0_daily_3_date = results_0_daily_3["date"]; // "2021-12-14"
const char* results_0_daily_3_quality = results_0_daily_3["quality"]; // "Moderate"
JsonObject results_0_daily_4 = results_0_daily[4];
const char* results_0_daily_4_aqi = results_0_daily_4["aqi"]; // "107"
const char* results_0_daily_4_pm25 = results_0_daily_4["pm25"]; // "81"
const char* results_0_daily_4_pm10 = results_0_daily_4["pm10"]; // "133"
const char* results_0_daily_4_so2 = results_0_daily_4["so2"]; // "19"
const char* results_0_daily_4_no2 = results_0_daily_4["no2"]; // "63"
const char* results_0_daily_4_co = results_0_daily_4["co"]; // "1.194"
const char* results_0_daily_4_o3 = results_0_daily_4["o3"]; // "17"
const char* results_0_daily_4_date = results_0_daily_4["date"]; // "2021-12-15"
const char* results_0_daily_4_quality = results_0_daily_4["quality"]; // "Unhealthy for Sensitive Groups"
const char* results_0_last_update = results_0["last_update"]; // "2021-12-11T03:22:03+08:00"
int daily_0_aqi = results_0_daily_0["aqi"].as<int>();
int daily_0_pm25 = results_0_daily_0["pm25"].as<int>();
int daily_0_co = results_0_daily_0["co"].as<int>();
String daily_0_quality = results_0_daily_0["quality"].as<String>();
if(daily_0_aqi!=0)
{
api0=daily_0_aqi;
pm25_0=daily_0_pm25;
co0=daily_0_co;
quality0=daily_0_quality;
}
}
利用ArduinoJson库解析心知天气响应信息。
connectWiFi();
连接Wi-Fi。
四、功能展示及说明
这是Wi-Fi连接成功后,第一个页面,显示了今天的日期,温度,天气状况,空气质量,以及夜间的天气状况。
这个是按下按键A之后,显示的第三个界面,未来三天的天气,如,天气状况,温度等等。
这是按下按键B之后,显示的第二个界面,显示了今天的API、PM2.5、一氧化碳含量。
五、对本活动的心得体会
首先呢!非常感谢硬禾学堂举办的FunPack第12期——玩成就送活动,是FunPack主题活动的最后一期,这也是我参加的第2个硬禾学堂活动,每一次参加都收获满满,无论是硬件知识还是软件知识。相比于上一次参加的活动,这一次空出了更多一点学习软件方面知识的时间,对arduino编译环境有了初步的应用和了解。同时,使用了心知天气免费版产品和试用版产品,对天气预报也有了一定的理解。