内容介绍
内容介绍
实现项目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 音频相关的开发,感谢群里老师、同学们的指导,希望后续多办这样的活动
附件下载
esp32s2weather.ino
团队介绍
苏州攻城狮一枚
评论
0 / 100
查看更多
猜你喜欢
基于ESP32-S2实现本地气象台/温度计本项目基于ESP32-S2模块,联网后通过http协议访问“知心天气”获得本地气象数据和温度并在模块上的OLED屏上对获得的数据进行显示,展示本地时间、温度和气象信息,实现一个简单的本地气象台/温度计.
A律13折线
1322
基于ESP32-S2实现本地气象计本项目使用ESP32-S2以及arduino框架,由于本地无气象传感器,因此采用腾讯位置服务的IP定位、“心知”天气获取当地天气的思路实现气象数据的获取,再通过ntp网络授时完成时间同步,最后使用U8g2显示。
zeki
1120
制作FPGA电子琴1. 存储一段音乐,并可以进行音乐播放,
2. 可以自己通过板上的按键进行弹奏,支持两个按键同时按下(和弦)并且声音不能失真,板上的按键只有13个,可以通过有上方的“上“、”下”两个按键对音程进行扩展
john
1135