2022寒假在家练-ESP32S2-本地气象/温度计
主要实现项目6 制作一个本地气象台/温度计 1.利用OLED显示 采用u8g2进行驱动 2.显示当前本地的时间、温度和气象信息 通过云端获取json 天气数据,解析并进行oled显示
标签
esp32s2
U8G2
2022寒假在家练
xinshuwei
更新2022-03-03
南昌大学
740

实现项目6 制作一个本地气象台/温度计

整体框图如下:

FnLn2JQ44iPB32fYL90zJx-L78Xv
1.利用OLED显示 采用u8g2进行驱动
2.显示当前本地的时间、温度和气象信息 通过云端获取json 天气数据,解析并进行oled显示

3.通过4个按钮进行页面切换

4.通过 CH340C 进行程序刷写 串口通信log 打印

实现功能如下

1.开机自动联网或者smartconfig进行联网 

2.开机联网成功后,进行气象信息获取ntp校时

3.通过4个按键进行当天信息显示、明天信息显示、后天信息显示、重新获取气象信息

 

 

具体实现如下:

1.Wifi配置及自动联网设置

void SmartConfig()
{
   WiFi.mode(WIFI_STA);
   Serial.println("\r\n wait for smartconfig....");
   WiFi.beginSmartConfig();
   while(1)
   {
    Serial.print(".");
    delay(400);
    if ( WiFi.smartConfigDone())
    {
      Serial.println("SmartConfig Success");
      //Serial.printf("SSID:%s\r\n",WiFi.SSID().c_str());
      //Serial.printf("PSW:%s\r\n",WiFi.psk().c_str());    
      break;      
    }
   }
}


bool AutoConfig()
{
  WiFi.begin();
  for (int i=0; i<20; i++)
  {
    int wstatus = WiFi.status();
    if (wstatus == WL_CONNECTED )  
       {  
          Serial.println("wifi smartConfig success");
          Serial.printf("SSID:%s",WiFi.SSID().c_str());
          Serial.printf(",PWS:%s\r\n",WiFi.psk().c_str());
          Serial.print("localIP:");
          Serial.println(WiFi.localIP());
          Serial.print(",GateIP:");
          Serial.println(WiFi.gatewayIP()); 
          esp_wifi_set_storage(WIFI_STORAGE_RAM);//自动保存wifi信息
          WiFi.setAutoConnect(true);  // 设置自动连接      
          return true;
       }
       else
       {
          Serial.print("WIFI AutoConfig Waiting ....");
          Serial.println(wstatus);
          delay(1000);
       }   
  }
  Serial.println("Wifi autoconfig faild!");
  return false;
  }

smaryconfig 可以通过微信小程序或者 点灯科技的app 进行设置 ,连接成功后会保存wifi信息

2. ssd1306 界面驱动

U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, 36, 35, 46,  33, 34);

 使用u8g2驱动,网上发现中文字都要做字库,后来终于找到资料 ,使能utf8 指定字体就能显示中文 

    u8g2.begin();
    u8g2.enableUTF8Print();
    Serial.begin(115200);
    delay(100);
    //pinMode(41, OUTPUT);
    //pinMode(42, OUTPUT);
    //digitalWrite(41, LOW);
    //digitalWrite(42, LOW);
    
    

    

    u8g2.firstPage();
    u8g2.clearBuffer();         
    u8g2.setFontDirection(0);   
    u8g2.setFont(ChineseFont); 
    u8g2.drawUTF8( 10, 24,"本地气象/温度计");
     
    u8g2.drawUTF8( 10, 36,"配网中...");
    u8g2.sendBuffer();
    if (!AutoConfig())
    {
      SmartConfig();
    }

这里实现主界面显示及配网过程

3. ntp 校时

 发现同学们校时有可能会卡,这里我使用三个 ntp 地址进行校时

    
// ntp server address
#define NTP1 "ntp1.aliyun.com"
#define NTP2 "pool.ntp.org"
#define NTP3 "210.72.145.44"

//ntpserver
    configTime(8 * 3600, 0, NTP1, NTP2,NTP3);
    u8g2.drawUTF8( 0, 48,"WIFI连接成功,校时成功");
    u8g2.sendBuffer();

效果很好,上电很快就完成校时

4. 气象信息获取

 

晚上找了很多资料,发现都不是很好用 ,最终发现luatos 比较好用 ,http get 过程如下 

  bool flag = false;
  ;
 if(WiFi.status() == WL_CONNECTED){
  HTTPClient http;
  Serial.print("[HTTP] begin...\n");
 // http.begin(SerUrl);
  http.begin(SerUrl1);
  int httpCode = http.GET();
      if(httpCode > 0) {
            // HTTP header has been send and Server response header has been handled
            Serial.printf("[HTTP] GET... code: %d\n", httpCode);
            // file found at server
            if(httpCode == HTTP_CODE_OK) {
                String payload = http.getString();

json解析过程如下

            deserializeJson(doc,payload);
                JsonObject obj = doc.as<JsonObject>();
                String CityName1 = obj["city"];
                CityName = CityName1;
                String Liveinfo = obj["live"];
                deserializeJson(doc1,Liveinfo);
                JsonObject obj1 = doc1.as<JsonObject>();
                String weatherNow1 = obj1["weather"];
                weatherNow  =weatherNow1;
                String tempNow1 = obj1["temperature"];
                tempNow =tempNow1+"℃";
                String WindNow1 = obj1["winddirection"];
                String WindNow2 = obj1["windpower"];
                WindNow= WindNow1+"风"+WindNow2+"级";
                String humdityNow1= obj1["humidity"];
                humdityNow =humdityNow1+"%";

                String foreinfo = obj["forecasts"][0];
                //Serial.println(foreinfo);
                deserializeJson(doc1, foreinfo);
                JsonObject obj4 = doc1.as<JsonObject>();
      
                
                String Day2Name1 = obj4["date"];
                Day2Name =obj4["date"].as<String>();

                if(obj4["dayweather"]==obj4["nightweather"])
                {
                  weather2 =obj4["dayweather"].as<String>();
                }
                else
                {
                  weather2= obj4["dayweather"].as<String>()+"~"+obj4["nightweather"].as<String>();
                }
                if(obj4["nighttemp"]==obj4["daytemp"])
                {
                  temp2 = obj4["daytemp"].as<String>() +"℃";
                }
                else
                {
                   //String temp21  = obj4["daytemp"];
                  // String temp22  =obj4["nighttemp"];
                   temp2 =obj4["daytemp"].as<String>()+"~"+obj4["nighttemp"].as<String>()+"℃";
                }
                if(obj4["daywind"] == obj4["nightwind"])
                {
                  Wind2 =obj4["daywind"].as<String>()+"风";
                }
                else
                {
                  Wind2 = obj4["daywind"].as<String>()+"~"+obj4["nightwind"].as<String>();
                }

                if(obj4["daypower"]==obj4["nightpower"])
                {
                  WindStr2 =obj4["daypower"].as<String>()+"级";
                }
                else
                {
                  WindStr2 =obj4["daypower"].as<String>()+"~"+obj4["nightpower"].as<String>()+String("级");
                }
                
                String day0data = "明天"+weather2+temp2+Wind2+WindStr2+Day2Name;
                Serial.println(day0data);
                


                String day1info = obj["forecasts"][1];
                //Serial.print(day1info);
                deserializeJson(doc1, day1info);
                JsonObject obj5 = doc1.as<JsonObject>();
                
                //weather3,temp3,Wind3,WindStr3,Day3Name;
                Day3Name =obj5["date"].as<String>();
                if(obj5["dayweather"]==obj5["nightweather"])
                {
           
                 Weather3 =obj5["dayweather"].as<String>();
                }
                else
                {
                   Weather3 =obj5["dayweather"].as<String>()+"~"+obj5["nightweather"].as<String>();
                }

                
                if(obj5["nighttemp"]==obj5["daytemp"])
                {
                  temp3 =obj5["daytemp"].as<String>()+"℃";
                }
                else
                {
                   temp3 =obj5["daytemp"].as<String>()+"~"+obj5["nighttemp"].as<String>()+"℃";
                }

                if(obj5["daywind"] == obj5["nightwind"])
                {
                  Wind3  = obj5["daywind"].as<String>()+"风";
                }
                else
                {
                  Wind3  = obj5["daywind"].as<String>() +"~"+obj5["nightwind"].as<String>();
                }

                if(obj5["daypower"]==obj5["nightpower"])
                {
                  WindStr3 =obj5["daypower"].as<String>()+"级";
                }
                else
                {
                  WindStr3 =obj5["daypower"].as<String>()+String("~")+obj5["nightpower"].as<String>()+String("级");
                }
                String day3data ="后天" +Weather3+temp3+Wind3+WindStr3+Day3Name;
                Serial.println(day3data);
                flag =true;
            }
            
        } else {
            Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
        }
        http.end();
 }
 return flag;
}

 

5. 按键响应实现  

   按键使用了EventButton库 ,用设置回调方式进行交互,不阻塞主线程

主界面实现如下

//btn1 call back curDayShow
void onBtn1Release(EventButton& eb)
{
  static String dateinfo;
  static String dayinfo;
  static String showinfo1,showinfo2;
  static String WindInfo;
  static String Weathershow;

  pageIndex = 0;
  Weathershow = CityName+"天气:"+weatherNow; 
  if(getLocalTime(&timeInfo))
  {
    dateinfo = String(timeInfo.tm_year+1900)+"-"+String(timeInfo.tm_mon+1)+"-"+String(timeInfo.tm_mday);
    if(timeInfo.tm_min<10)
    {
      dayinfo = String(timeInfo.tm_hour)+":0"+String(timeInfo.tm_min)+":";
    }
    else
    {
      dayinfo = String(timeInfo.tm_hour)+":"+String(timeInfo.tm_min)+":";
    }
    if(timeInfo.tm_sec<10)
    {
      dayinfo = dayinfo +"0"+String(timeInfo.tm_sec);
    }
    else
    {
      dayinfo = dayinfo +String(timeInfo.tm_sec);
    }
    showinfo1 = dateinfo +" "+dayinfo;
  }
  showinfo2 = "温度"+tempNow+" 湿度"+humdityNow;
  WindInfo =  "风向:" +WindNow;
  u8g2.clearBuffer(); 
  drawWeatherSymbol(0,18,weatherNow);
  u8g2.setFont(ChineseFont); 
  u8g2.drawUTF8(24,16,Weathershow.c_str());
  u8g2.drawUTF8(0,32,showinfo1.c_str());
  u8g2.drawUTF8(0,44,showinfo2.c_str());
  u8g2.drawUTF8(0,56,WindInfo.c_str());
  u8g2.sendBuffer(); 
}

默认上电后进入主界面,并通过loop 里1s 进行界面更新 

明天  后天天气显示如下 

//btn2 call back NextDayShow
void onBtn2Release(EventButton& eb)
{
  pageIndex =NextDay;
  u8g2.clearBuffer();
  static String NextDay = CityName+Day2Name+"天气";
  u8g2.drawUTF8(4,12,NextDay.c_str());
  static String nextWindStr = Wind2+" "+WindStr2;
  u8g2.drawUTF8(4,24,nextWindStr.c_str());
  u8g2.drawUTF8(24,36,weather2.c_str());
  u8g2.drawUTF8(24,48,temp2.c_str());
  u8g2.sendBuffer();
}

//btn3 callback NextNextDayShow
void onBtn3Release(EventButton& eb)
{
  pageIndex =NextNextDay;
    //Serial.print("btn3 released: ");
  //Serial.println(eb.clickCount());
  u8g2.clearBuffer();
  static String NextDay = CityName+Day3Name+"天气";
  u8g2.drawUTF8(4,12,NextDay.c_str());
  static String nextWindStr1 = Wind3+" "+WindStr3;
  u8g2.drawUTF8(4,24,nextWindStr1.c_str());
  u8g2.drawUTF8(24,36,Weather3.c_str());
  u8g2.drawUTF8(24,48,temp3.c_str());
  u8g2.sendBuffer();
}

按钮4 重新获取气象实现  

 

//btn4 callback  updateInfo
void onBtn4Release(EventButton& eb)
{
    //Serial.print("btn4 released: ");
  //Serial.println(eb.clickCount());
   pageIndex =UpdateInfo;
   u8g2.clearBuffer();
   u8g2.setFont(ChineseFont); 
   u8g2.drawUTF8(32,32,"更新天气中");
   u8g2.sendBuffer();
   if(http_get())
   {
     u8g2.drawUTF8(32,44,"更新天气成功");
   }
   else
   {
     u8g2.drawUTF8(32,44,"更新天气失败");
   }
   u8g2.sendBuffer();
   
}

模块运行状态截图如下 

FjTrfx-5WhFF1oliHIeJqDFAf8zc

 

 

5. 项目总结 

    很喜欢此次活动,在arduino 安装中踩了很多坑,不过也学习了很多,后续有时间学习下idf 音频相关的开发,感谢群里老师、同学们的指导,希望后续多办这样的活动

 

 

附件下载
esp32s2weather.ino
团队介绍
苏州攻城狮一枚
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号