FunPack12期——使用Wio Terminal制作一个在线天气预报仪
使用Wio Terminal连接WiFi,通过各家API获得地址、天气和天气预报,并显示在屏幕上
标签
Arduino
MCU
yekai
更新2021-12-30
中国计量大学
1143

使用Wio Terminal制作一个天气预报仪开发板介绍

本次我使用的开发板是一块来自矽递科技的Wio Terminal。

Wio Terminal 基于来自ATEML的SAMD51系列微控制器。这颗处理器可以运行在120MHz的主频上,同时可以超频至200MHz。这颗处理器带有192KB RAM, 496KB Flash,矽递也为它通过QSPI接口扩展了4MB的Flash,尽管它不支持XiP。

同时,Wio Terminal带有一个 Realtek RTL8720DN模块来连结无线连接。这个无线模块支持2.4GHz和5GHz的Wifi网络,也支持BLE。

实现的功能

本次我选择任务二:使用Wio Terminal制作一个天气预报仪

程序主要分为以下几个部分:

  • GUI

  • WiFi连接和HTTP访问

  • Json解析与数据填入GUI

程序首先初始化屏幕和LVGL,开启LVGL心跳,然后连接网络,访问各个API来获取当前地址、当前天气和未来天气,并显示在屏幕上。循环中每隔一小时进行一次天气的更新。

具体实现GUI

本次GUI我主要使用了LVGL进行实现。由于GUI-Guider(1.2.1)目前似乎只支持LVGL7,故本次使用的依然是LVGL7.11.0。

TFT接口函数Wio Terminal已帮我们使用TFT_eSPI做好,直接调用即可。

TFT_eSPI tft;
static lv_disp_buf_t disp_buf;
static lv_color_t buf[TFT_HEIGHT * 10] = {0};
​
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p);
​
void GUI_Init()
{
   lv_init(); // 初始化LVGL
​
   lv_log_register_print_cb((lv_log_print_g_cb_t)my_print); // 注册log输出组件
​
   tft.begin();
   tft.setRotation(3);
   tft.fillScreen(TFT_WHITE);
​
   lv_disp_buf_init(&disp_buf, buf, NULL, TFT_HEIGHT * 10); // 注册buffer
​
   // 注册屏幕组件
   static lv_disp_drv_t disp_drv;
   lv_disp_drv_init(&disp_drv);
   disp_drv.hor_res = TFT_HEIGHT;
   disp_drv.ver_res = TFT_WIDTH;
   disp_drv.flush_cb = my_disp_flush;
   disp_drv.buffer = &disp_buf;
   lv_disp_drv_register(&disp_drv);
}
​
void GUI_Run(void *parm)
{
   while (true){
       lv_task_handler();
       delay(10);
  }
}
​
void my_print(lv_log_level_t level, const char *file, uint32_t line, const char *fn_name, const char *dsc)
{
   Serial.printf("%s(%s)@%d->%s", file, fn_name, line, dsc);
   Serial.println("");
   Serial.flush();
}
​
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
   uint32_t w = (area->x2 - area->x1 + 1);
   uint32_t h = (area->y2 - area->y1 + 1);
​
   tft.startWrite();
   tft.setAddrWindow(area->x1, area->y1, w, h);
   tft.pushColors((uint16_t *)&color_p->full, w * h, true);
   tft.endWrite();
​
   lv_disp_flush_ready(disp);
}

main中开一个线程调用LVGL保持心跳即可:

// 新建一个全局变量以运行GUI-Guider的UI
lv_ui guider_ui;
// 初始化LVGL后新建一个线程保持LVGL的心跳
GUI_Init();
   setup_ui(&guider_ui);
   xTaskCreate(GUI_Run, "GUI_Task", 4096, NULL, 2, NULL);

Wi-Fi连接及HTTP访问

WiFi的初始化在seeed的Wiki中有示例进行介绍。需要注意的是,初始化WiFi后就无需使用vTaskStartScheduler();进行开启线程调度。

void Network_Init()
{
   uint8_t retry = 0;
   WiFi.mode(WIFI_STA);
   WiFi.disconnect();
   delay(100);
   WiFi.begin(WiFi_SSID, WiFi_PASSWORD);
   while ((WiFi.status() != WL_CONNECTED) && (retry < 10))
  {
       retry++;
       delay(500);
       Serial.println("Connecting to WiFi..");
       WiFi.begin(WiFi_SSID, WiFi_PASSWORD);
  }
   if (retry == 10)
  {
       Serial.println("Failed to connect to WiFi");
  }
   else
  {
       Serial.println("Connected to the WiFi network");
       Serial.print("IP Address: ");
       Serial.println(WiFi.localIP()); // prints out the device's IP address
  }
}

HTTP的访问,也有相应api可以调用:

   http.begin(locationAPI);
   httpCode = http.GET();
   if (httpCode != HTTP_CODE_OK)
  {
       Serial.printf("http GET err:");
       Serial.println(httpCode);
       http.end();
       goto err_handle;
  }
   jsonData = http.getString();
   http.end();

Json解析与数据填入GUI

Json解析我使用了ArduinoJson这个库。根据说明文档编写即可。

下面是一个例子:

   jsonData = http.getString();
   deserializeJson(jsonBuffer, jsonData);
​
   String2Enum parser1;
   Enum2CharArr parser2;
​
   weatherState skycon = parser1.Parse(jsonBuffer["result"]["realtime"]["skycon"]);
   float temperature = jsonBuffer["result"]["realtime"]["temperature"];
   float humidity = jsonBuffer["result"]["realtime"]["humidity"];
   int air = jsonBuffer["result"]["realtime"]["air_quality"]["aqi"]["chn"];

然后将这些数据转化成字符串写入LVGL设计好的标签中即可

   char temp[10];
   lv_label_set_text(guider_ui.screen_skycon_label, parser2.Parse(skycon));
   sprintf(temp, "%.2f", temperature);
   lv_label_set_text(guider_ui.screen_temp_label, temp);
   sprintf(temp, "%.2f", humidity);
   lv_label_set_text(guider_ui.screen_humi_label, temp);
   sprintf(temp, "%d", air);
   lv_label_set_text(guider_ui.screen_air_label, temp);

功能展示

FqRmNQLuSu3ZI312jD8IWOL3qWbQ

心得体会

  • platformIO+arduino开发方式,能让我们更注重于功能的实现而不是底层,这对快速开发很有优势。

  • Seeed对Wio Terminal进行了很多适配,出了很多的基于开源库的专用的库,但有时候platformIO对库的索引和编译会导致一些问题。

  • 学习arduino打的同时,我同时也在学习c++的一些特点及用法。

完整代码可查看Github仓库:kaidegit/funpack12-WeatherForecaster: 使用WioTerminal制作一个天气预报机 (github.com)

附件下载
funpack12-WeatherForecaster.7z.001
funpack12-WeatherForecaster.7z.002
funpack12-WeatherForecaster.7z.003
团队介绍
团队成员
yekai
一个大三的电子小白
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号