基于ESP32S2实现本地气象台/温度计
本项目基于ESP32S2开发板,通过Arduino编写代码,从阿里云获取时间信息,从心知天气获取气象信息,再将获取的信息进行处理后显示在OLED 屏幕上。
标签
嵌入式系统
显示
网络与通信
2022寒假在家练
开元来的小禾苗
更新2022-03-02
安徽大学
1498

一、项目介绍

    制作一个本地气象台/温度计

    要求:1.利用OLED显示

             2.显示当前本地的时间、温度和气象信息

二、设计思路

     先简单介绍一下,具体代码在后面解释。通过wifi联网获取信息,根据从阿里云获取时间信息,处理后在再OLED 屏幕上显示;在从心知天气的api上获取本地(合肥)的天气信息,获取的信息是Json格式,所以用ArduinoJson来处理信息。最后再排版显示在OLED 屏幕上。

                                               流程图

Fq31SJPVqmBCPIe3Mrg5g9xNhp0T

三、实现的功能和图片展示

   时间显示

   Fv60IR23uWkEXm011y5I0ba_zkLS

   地点显示

   Fv1QNGT2ftpPFP8E7iq0BFiVu56O

   温度和天气显示

   FgitbJKWWLiqlKXpwcPTzVWWK_WF

四、主要代码片段和说明

      Arduino的开始片段,在这段代码实现了wifi的配置和通过http协议从心知天气调用api获取天气信息。

      本段代码需要注意的是变量weather,在代码中他保存要显示的天气信息并且在后面显示,本段代码中保存的是示例图片中的"text_day":"多云"的信息,所以保存下来的数据是多云。

FlbxqzCuE1WHj_NpdW9BIsPrSfXX

void setup() {
  // oled使能
  u8g2.begin();             
  u8g2.enableUTF8Print();   
  // oled使能

  ////////////////////////WIFI配置
  Serial.begin(115200);
  Serial.printf("Connecting to %s",ssid);
  WiFi.begin(ssid,password);
  while(WiFi.status()!=WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }
  Serial.println(" CONNECTED");
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  //////////////////////WIFI配置

    //////////////////////天气信息获取
    https.begin("https://api.seniverse.com/v3/weather/daily.json
    key=SmLKKd0aGxnk67ZRE&location=hefei&language=zh-Hans&unit=c&start=0&days=5");
    int httpCode = https.GET();
    if(httpCode > 0)
    {
        String pageData = https .getString();
        deserializeJson(doc,pageData);
        JsonObject obj = doc.as<JsonObject>();
        
        String weatherInfo = obj["results"][0];
        deserializeJson(doc1,weatherInfo);
        JsonObject obj1 = doc1.as<JsonObject>();
        
        String dailytoday = obj1["daily"][0];
        Serial.println(dailytoday);
        deserializeJson(doc2,dailytoday);
        JsonObject obj2 = doc2.as<JsonObject>();
        
        String city = obj1["location"]["name"];
        String temp1 = obj2["high"];
        String temp2 = obj2["low"];
        temp11=temp1;temp22=temp2;
        String weather = obj2["text_day"];
        wea = weather;
     }
     else
     {
        Serial.println("GET ERROR");
     }
    https.end();
    /////////////////////天气信息获取
    Serial.println(temp11);
    configTime(8 * 3600, 0, NTP1, NTP2,NTP3);
}

      接下来这段代码是获取时间的函数,实施条件如下:

  • ESP32需要在:WIFI.MODE(WIFI_STA;)模式下,配网并接入网络。
  • 使用下面函数从网络时间服务器上获取并设置时间:
    configTime(long gmtOffset_sec, int daylightOffset_sec, const char* server1, const char* server2 = nullptr, const char* server3 = nullptr)
    参数说明:
    gmtOffset_sec参数就是用来修正时区的,比如对于我们东八区(UTC/GMT+08:00)来说该参数就需要填写 8 * 3600 ;
    daylightOffset_sec使用夏令时 daylightOffset_sec 就填写3600,否则就填写0;
  • 格式化输出
    Serial.println(&timeinfo, "%F %T %A"); // 格式化输出:2021-10-24 23:00:44 Sunday
    Serial.print(asctime(&timeinfo));//默认打印格式:Mon Oct 25 11:13:29 2021​

    %a 星期几的简写
    %A 星期几的全称
    %b 月分的简写
    %B 月份的全称
    %c 标准的日期的时间串
    %C 年份的后两位数字
    %d 十进制表示的每月的第几天
    %D 月/天/年
    %e 在两字符域中,十进制表示的每月的第几天
    %F 年-月-日
    %g 年份的后两位数字,使用基于周的年
    %G 年分,使用基于周的年
    %h 简写的月份名
    %H 24小时制的小时
    %I 12小时制的小时
    %j 十进制表示的每年的第几天
    %m 十进制表示的月份
    %M 十时制表示的分钟数
    %p 本地的AM或PM的等价显示
    %r 12小时的时间
    %R 显示小时和分钟:hh:mm
    %S 十进制的秒数
    %t 水平制表符
    %T 显示时分秒:hh:mm:ss
    %u 每周的第几天,星期一为第一天 (值从0到6,星期一为0)
    %U 第年的第几周,把星期日做为第一天(值从0到53)
    %V 每年的第几周,使用基于周的年
    %w 十进制表示的星期几(值从0到6,星期天为0)
    %W 每年的第几周,把星期一做为第一天(值从0到53)
    %x 标准的日期串
    %X 标准的时间串
    %y 不带世纪的十进制年份(值从0到99)
    %Y 带世纪部分的十进制年份
    %z,%Z 时区名称,如果不能得到时区名称则返回空字符

    获取时间的实例代码
void setClock() {
  struct tm timeinfo;
    if (!getLocalTime(&timeinfo))
    {//如果获取失败,就开启联网模式,获取时间
        Serial.println("Failed to obtain time");
         WiFi.disconnect(false);
        WiFi.mode(WIFI_STA);//开启网络  
       WiFi.begin(ssid, password);
         while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }
     configTime(8 * 3600, 0, NTP1, NTP2,NTP3);
        return;
    }
    u8g2.firstPage();
    u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(30, 20);
  u8g2.print("当前时间");
    u8g2.setCursor(2, 35);
    u8g2.print(&timeinfo,"%T");
    u8g2.print(str);
     u8g2.sendBuffer();
    //delay(1000);
    Serial.println(&timeinfo, "%F %T %A"); // 格式化输出:2021-10-24 23:00:44 Sunday
    Serial.print(asctime(&timeinfo));//默认打印格式:Mon Oct 25 11:13:29 2021
     WiFi.disconnect(true);
}

OLED 屏幕显示代码,此段代码重复度较高,举一个例子说明

  u8g2.clearBuffer();         //清除内部缓冲区
  u8g2.setFontDirection(0);   //设置字体方向
  u8g2.setFont(u8g2_font_unifont_t_chinese2);  //字体设置
  u8g2.setCursor(30, 20);     //位置设置
  u8g2.print("天气");
  u8g2.setCursor(25, 50);
  u8g2.print("today");
  u8g2.sendBuffer();  

接下来的代码调用从心知天气获取的Json信息并且显示在oled上,可以看到这里获取的是前文提到的weather的信息,所以实例图片显示的是多云。

void disptianqii(String temp1,String temp2) 
{
  u8g2.firstPage();
  u8g2.clearBuffer();         //清除内部缓冲区
  u8g2.setFontDirection(0);   //设置字体方向
  drawWeatherSymbol(0,48, wea);
  u8g2.setFont(u8g2_font_unifont_t_chinese2);
  u8g2.setCursor(51,55);
  u8g2.print("wea");
  u8g2.setCursor(48+3, 20);
  String tempInfo ="temp: ";
  Serial.println(temp1 + "~" + temp2);
  u8g2.print(tempInfo);
  String tempInfoo = temp1+" 度~"+temp2+" 度";
  u8g2.setCursor(48+3, 35);
  u8g2.print(tempInfoo);
  u8g2.sendBuffer(); 
}

五、遇到的问题及解决方法

在我选用的oled库时u8g2库,在我实验过程中有些中文会显示不出来,但是由于这个库功能齐全,所以我还是选择了这个库。以后我会在实践中学习自己编写字体库或者选择更全面的oled库。

六、未来的计划或者建议

未来我可能会更加加深对ESP32的学习,或许通过本次的学习制作一个天气手表。也会在本次寒假练后自己学习一下其他的项目来增加自己的经验。

软硬件
元器件
ESP32-S2-MINI-1
2.4GHz Wi­Fi (802.11 b/g/n) 模组, 内置ESP32­S2系列芯片,Xtensa® 单核32位LX7微处理器, 内置芯片叠封4MB flash,可叠封2MB PSRAM, 37个GPIO,丰富的外设, 板载PCB天线或外部天线连接器
附件下载
zhongjitianqiyubao.zip
团队介绍
安徽大学
团队成员
开元来的小禾苗
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号