内容介绍
内容介绍
实现项目6 制作一个本地气象台/温度计
整体框图如下:
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();
   
}
模块运行状态截图如下
5. 项目总结
很喜欢此次活动,在arduino 安装中踩了很多坑,不过也学习了很多,后续有时间学习下idf 音频相关的开发,感谢群里老师、同学们的指导,希望后续多办这样的活动
软硬件
元器件
ESP32-S2-MINI-1
2.4GHz WiFi (802.11 b/g/n) 模组, 内置ESP32S2系列芯片,Xtensa® 单核32位LX7微处理器, 内置芯片叠封4MB flash,可叠封2MB PSRAM, 37个GPIO,丰富的外设, 板载PCB天线或外部天线连接器
附件下载
esp32s2weather.ino
团队介绍
苏州攻城狮一枚
评论
0 / 100
查看更多
猜你喜欢
基于ESP32-S2实现本地气象台/温度计本项目基于ESP32-S2模块,联网后通过http协议访问“知心天气”获得本地气象数据和温度并在模块上的OLED屏上对获得的数据进行显示,展示本地时间、温度和气象信息,实现一个简单的本地气象台/温度计.
A律13折线
2091
基于ESP32-S2实现本地气象计本项目使用ESP32-S2以及arduino框架,由于本地无气象传感器,因此采用腾讯位置服务的IP定位、“心知”天气获取当地天气的思路实现气象数据的获取,再通过ntp网络授时完成时间同步,最后使用U8g2显示。
zeki
1775
制作FPGA电子琴1. 存储一段音乐,并可以进行音乐播放,
2. 可以自己通过板上的按键进行弹奏,支持两个按键同时按下(和弦)并且声音不能失真,板上的按键只有13个,可以通过有上方的“上“、”下”两个按键对音程进行扩展
john
1961