funpack第十二期 自动联网天气预报仪
funpack第十二期 自动联网天气预报仪,基于seeed wio terminal 开发板,使用arduino 和processing开发完成的自动联网天气预报仪,天气数据来源知心天气
标签
嵌入式系统
显示
USB
网络与通信
linweifu
更新2022-01-11
527

       Funpack第十二期 自动联网天气预报仪

    制作一个自动联网的天气预报仪,在设计界面显示温湿度、天气情况、空气质量以及未来三天内的天气变化。

本次活动开发主要功能点是液晶屏幕中文显示,WiFi获取最近几天的天气情况和当天空气质量。

  1. 本期项目是在Seeed公司的Wio terminal 开发板上开发自动联网天气预报仪。
  2. 本期硬件是一款带屏幕的支持wifi和ble 通讯的开发板.。
  3. Wio Terminal 部分主要2.4寸的LCD显示屏,Wi-Fi、蓝牙、IMU、麦克风、 蜂鸣器、microSD 卡、三个可配置的按钮、光传感 器、五向开关、红外发射器 (IR 940 nm), 除了这些它还有两个用于Grove生态系统的多功能Grove接口和兼容Raspberry pi的40个GPIO引脚。
  4. 软件开发平台,Arduino ,Arduino是一款便捷灵活、方便上手的开源电子原型平台。包含硬件(各种型号的Arduino板)和软件(ArduinoIDE)。
  5. 本期视频演示自动联网天气预报仪。下面是设计思路。
  • 项目开始
  1. Ardiuno开发环境搭建
    1. 添加开发板
    2. 添加软件库
      1. Seeed Arduino FS
      2. Seeed Arduino rpcUnified
      3. Seeed_Arduino_mbedtls
      4. Seeed Arduino rpcWiFi
      5. Seeed Arduino SFUD
      6. ArduinoJson
    3. 升级WiFi蓝牙固件
      出场固件不支持WiFi,需要根据seeed wio terminal官方提供的文档按步操作即可升级
  2. 使用 processing制作 中文字体

         通过编写代码,导出自己所使用的字体,减小内存使用。

        下面是我编写的导出字体的函数

void export_font(String fileName,String words,int fontNumber, int fontSize){
  char[] specificUnicodes = words.toCharArray();
  println("=====================");
  
  String fontName = get_font_from_number(fontNumber);
  PFont font = createFont(fontName, fontSize, true, specificUnicodes);
  
  println("Specific unicodes included  = " + specificUnicodes.length);
  println("Specific fontname  = " + specificUnicodes.length);
  textFont(font);
  try {
    print("Saving to sketch FontFiles folder... ");

    OutputStream output = createOutput("FontFiles/" + fileName+ "_" + str(fontSize) + ".vlw");
    font.save(output);
    output.close();

    println("export OK!");

    delay(100);

    // Open up the FontFiles folder to access the saved file
    //String path = sketchPath();
    //Desktop.getDesktop().open(new File(path+"/FontFiles"));

    //System.err.println("All done! Note: Rectangles are displayed for non-existant characters.");
  }
  catch(IOException e) {
    println("Doh! Failed to create the file");
  }
}

 

     3.  天气数据获取

         天气数据获取,我们使用的是知心天气的API获取最近4天的天气情况,和当前的空气质量。 知心天气,提供了开发者免费14天 API体验服务,提供了非常丰富的天气相关的api。

      下面是我们使用的天气和空气质量的问题。使用http get方法调用,读取数据非常方便。

// 天气预报信息获取
const char* url_weather_api = "https://api.seniverse.com/v3/weather/daily.json?key=SKW-2rdwbiHmhmQmT&location=shanghai&language=zh-Hans&unit=c&start=0&days=4";
String getWeather(const char* url)
{
    // Add a scoping block for HTTPClient https to make sure it is destroyed before WiFiClientSecure *client is
    HTTPClient https;
    String weatherJson = "";
    Serial.print("[HTTPS] begin...\n");
    
    if (https.begin(client, url))
    {
        Serial.print("[HTTPS] GET...\n");
        
        int httpCode = https.GET();
        
        if (httpCode > 0)
        {
            Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
            
            if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) 
            {
                weatherJson = https.getString();
                Serial.print(weatherJson);
            }
        } else {
          Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
        }
        
        https.end();
        
    } else {
        Serial.printf("[HTTPS] Unable to connect\n");
    }
    return weatherJson;
    // End extra scoping block
}

       

const char* url_air_api = "https://api.seniverse.com/v3/air/now.json?key=SKW-2rdwbiHmhmQmT&location=shanghai&language=zh-Hans&scope=city";
String getAirQuality(const char* url){
  HTTPClient https;
  String airQualityJson = "未知";
  if (https.begin(client, url))
    {
        Serial.print("[HTTPS] GET...\n");
        
        int httpCode = https.GET();
        
        if (httpCode > 0)
        {
            Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
            if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) 
            {
                airQualityJson = https.getString();
                Serial.print(airQualityJson);
            }
        } else {
          Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
        }
        
        https.end();
        
    } else {
        Serial.printf("[HTTPS] Unable to connect\n");
    }
    return airQualityJson;
    // End extra scoping block
}


3. ArdiunoJson库解析天气数据

void paringAirQuality(String payload){
  DynamicJsonDocument doc(1024);
  DeserializationError error = deserializeJson(doc, payload);
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
  }else{
    strcpy(airQuality, doc["results"][0]["air"]["city"]["quality"]);
    Serial.println(airQuality);
  }
}

void paringWeatherInfo(String payload){
  DynamicJsonDocument doc(2048);
  DeserializationError error = deserializeJson(doc, payload);
  
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
  }else{
    String cityName = doc["results"][0]["location"]["name"];
    for(int d=0;d<4;d++){
      strcpy(day4[d].date, doc["results"][0]["daily"][d]["date"]);
      
      strcpy(day4[d].weatherInfo, doc["results"][0]["daily"][d]["text_day"]);
      strcpy(day4[d].tempHigh , doc["results"][0]["daily"][d]["high"]);
      strcpy(day4[d].tempLow , doc["results"][0]["daily"][d]["low"]);
      strcpy(day4[d].humidity , doc["results"][0]["daily"][d]["humidity"]);
    }
  }
}


3. TFT_Spi库展示天气信息

void showdaily(int dateIndex){
  tft.fillScreen(TFT_WHITE); // WHITE background
  tft.loadFont("titleWords_32", SD);
  int xb = 20;
  // Show all characters on screen with 2 second (2000ms) delay between screens
  // tft.showFont(3000); // Note: This function moves the cursor position!
 
  tft.setTextColor(TFT_RED, TFT_WHITE);
  tft.setCursor(30,1);  //x = 30 y =1
  tft.drawString("上海天气", 90, 5);
  tft.unloadFont();
  
//  tft.drawLine( 3, 50, 3, 320, TFT_YELLOW);
  tft.loadFont("weatherWords_22", SD);
  tft.setTextColor(TFT_GREEN, TFT_WHITE);
  //tft.drawString("2021-12-31", 100,30);
  if(dateIndex==0){
    tft.drawString("今天", 130,40);
    tft.drawString("空气质量:", xb, 190);
    tft.drawString(airQuality, xb+120, 190);
  }else{
    tft.drawString(day4[dateIndex].date, 100, 40);
  }
  tft.setTextColor(TFT_BLACK, TFT_WHITE);
  tft.drawString("天气情况:", xb,70);
  tft.drawString(day4[dateIndex].weatherInfo, xb+120, 70);
  Serial.println(day4[dateIndex].weatherInfo);
  
  char tempString[10];
  tft.drawString("最高温度:", xb, 100);
  sprintf(tempString,"%s ℃ ", day4[dateIndex].tempHigh);
  tft.drawString(tempString, xb+120, 100);
  
  tft.drawString("最低温度:", xb ,130);
  sprintf(tempString,"%s ℃ ", day4[dateIndex].tempLow);
  tft.drawString(tempString, xb+120, 130);
  
  tft.drawString("相对湿度:", xb, 160);
  sprintf(tempString,"%s %%", day4[dateIndex].humidity);
  
  tft.drawString(tempString, xb+120, 160);
  
  tft.unloadFont();

}


4. 通过按键切换未来三天的天气

void loop_key_status(){
  if (digitalRead(WIO_5S_PRESS) == LOW) {
    showdaily(0);
  }else if (digitalRead(WIO_KEY_A) == LOW) {
    showdaily(3);
  }else if (digitalRead(WIO_KEY_B) == LOW) {
    showdaily(2);
  }else if (digitalRead(WIO_KEY_C) == LOW) {
    showdaily(1);
  }
}
  • 效果图片  

     

  • 项目总结

     在此次项目中,主要用到了技术点有,LCD屏幕显示,中文字库制作和使用,WiFi联网,https web api,json数据解析等。

     通过本期板卡活动,学习到了WiFi访问服务器获取数据,使用LCD展示数据,本期板卡可玩性非常强,还有很多传感器通过wifi进行环境监控上报服务器,服务器通知用户等应用场景。

     涉及技术面比较广,建议增加团队作业。团队分工,做出更完善的作品。

 

附件下载
funpack12期 源码.zip
arduino源码,和processing源码
团队介绍
主要从事物联网智能硬件开发, 蓝牙BR,BLE开发,WiFi,4G开发
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号