一种ESP8266+OLED时间天气显示
在当今这个信息爆炸的时代,人们对于获取实时信息的需求日益增长,尤其是在时间与天气这两个与日常生活息息相关的方面。而将 ESP8266 与 OLED 显示屏相结合制作的时钟兼天气显示设备,凭借其便携性、实时性以及低成本等优势,成为了众多电子爱好者和智能家居爱好者的新宠。
一、项目背景与意义
时间是人们日常生活中不可或缺的要素,无论是工作、学习还是生活安排,准确的时间信息都至关重要。而天气状况更是影响着人们的出行计划、穿着选择以及户外活动安排等诸多方面。传统的时间显示设备如机械钟表功能单一,仅能提供时间信息;而天气预报获取方式相对繁琐,要么需要通过电视、广播等传统媒体定时收看收听,要么借助手机等移动设备联网查询,不够直观便捷。
基于此,本项目旨在利用 ESP8266 这款功能强大的 Wi - Fi 模块与 OLED 显示屏,打造一款能够同时显示时间与天气信息的智能设备。它不仅可以实时获取网络时间,确保时间的精准性,还能从网络上抓取当地的天气数据,包括温度、湿度、天气状况(晴、阴、雨、雪等)、风力风向等关键信息,并将这些信息清晰直观地呈现在 OLED 屏幕上。这样一来,用户只需一瞥屏幕,便能迅速掌握当前的时间与天气状况,极大地提高了信息获取效率,为日常生活带来诸多便利。
二、软件设计与实现
(一)网络时间获取
为了确保时间的准确性,设备需要定期从网络时间服务器获取标准时间。在软件设计中,利用 ESP8266 的网络功能,通过 NTP(Network Time Protocol,网络时间协议)客户端库,向指定的 NTP 服务器发送时间请求。NTP 服务器会返回当前的 UTC(Coordinated Universal Time,协调世界时)时间,设备接收到后,将其转换为本地时间格式,并在 OLED 屏幕上进行显示。一般情况下,设备每隔一段时间(如几分钟或十几分钟)就会自动向 NTP 服务器同步一次时间,以保证时间显示的实时性和准确性。
(二)天气数据获取
天气数据的获取是通过调用天气数据 API 实现的。目前市面上有许多提供天气数据服务的 API 接口,如心知天气、和风天气等。这些 API 接口通常会要求用户注册账号并获取一个 API 密钥(API Key),然后在软件代码中将该密钥以及需要查询的地理位置信息(如城市名称、经纬度坐标等)作为参数发送请求。服务器接收到请求后,会返回包含当地实时天气状况、温度、湿度、风力风向等详细信息的 JSON(JavaScript Object Notation,一种轻量级数据交换格式)或 XML(eXtensible Markup Language,可扩展标记语言)格式的数据。设备端的软件需要解析这些数据,提取出关键信息,并将其格式化后显示在 OLED 屏幕上。例如,将温度数据以“温度:XX℃”的格式显示,将天气状况以相应的图标(如太阳、云朵、雨滴等)和文字描述(如“晴”“多云”“小雨”等)相结合的方式呈现,使用户能够一目了然地了解当前的天气情况。
(三)显示界面设计
OLED 屏幕的显示界面设计对于用户体验至关重要。在本项目中,可以将屏幕分为多个区域,每个区域显示不同类型的信息。例如,屏幕的上方可以设置为时间显示区域,以较大的字体和醒目的颜色显示当前的时、分、秒,让用户能够迅速读取时间;屏幕的中间部分用于显示天气状况,包括天气图标、温度、湿度等关键信息,图标要形象直观,文字描述要简洁明了;屏幕的下方可以显示一些辅助信息,如日期、星期、风力风向等,为用户提供更全面的参考。此外,还可以设计一些交互式的界面元素,如当用户按下某个按键时,屏幕显示内容可以在时间显示界面与天气详细信息界面之间切换,或者在不同的天气数据展示模式(如按小时、按天等)之间切换,以满足用户不同的查看需求。
(四)代码
某宝上购买的是使用和风天气,界面较多,但下文是结合心知天气实现上图的界面,简单实用。由于篇幅有限,只放了部分代码,感兴趣的同学可以到主页下载全部的程序代码。
void display_today() //oled显示今天的天气信息
{
int years, months, days, hours, minutes, seconds, weekdays;
years = year();
months = month();
days = day();
hours = hour();
minutes = minute();
seconds = second();
weekdays = weekday();
Serial.printf("%d/%d/%d %d:%d:%d Weekday:%d\n", years, months, days, hours, minutes, seconds, weekdays);
u8g2.clearBuffer();
String currentTime = "";
if (hours < 10)
currentTime += 0;
currentTime += hours;
currentTime += ":";
if (minutes < 10)
currentTime += 0;
currentTime += minutes;
String currentDay = "";
currentDay += years;
currentDay += "-";
if (months < 10)
currentDay += 0;
currentDay += months;
currentDay += "-";
if (days < 10)
currentDay += 0;
currentDay += days;
u8g2.setFont(u8g2_font_logisoso24_tf);
u8g2.setCursor(0, 30);
u8g2.print(currentTime);
//u8g2.setFont(u8g2_font_wqy14_t_gb2312);
//u8g2.setCursor(73, 30);
//u8g2.print(seconds);
u8g2.setCursor(0, 47);
u8g2.setFont(u8g2_font_wqy14_t_gb2312);
u8g2.print(currentDay);
u8g2.setCursor(0, 63);
u8g2.print("星期");
if (weekdays == 1)
u8g2.print("日");
else if (weekdays == 2)
u8g2.print("一");
else if (weekdays == 3)
u8g2.print("二");
else if (weekdays == 4)
u8g2.print("三");
else if (weekdays == 5)
u8g2.print("四");
else if (weekdays == 6)
u8g2.print("五");
else if (weekdays == 7)
u8g2.print("六");
u8g2.sendBuffer();
u8g2.setCursor(50, 63);
u8g2.print("XX");
//分割线
u8g2.drawLine(80, 0, 80, 63);
u8g2.setFont(u8g2_font_wqy14_t_gb2312);
u8g2.setCursor(86, 60);
u8g2.print(day0.low);
u8g2.setCursor(100, 60);
u8g2.print("-");
u8g2.setCursor(105, 60);
u8g2.print(day0.high);
u8g2.setCursor(120, 60);
u8g2.print("C");
switch(day0.code_day) //将天气代码转化为天气图标和字符显示
{
case 0:
u8g2.drawXBMP( 86 , 0 , 30 , 30 , Sunny );
u8g2.setFont(u8g2_font_wqy12_t_gb2312);
u8g2.drawStr(86,40,"Sunny");
break;
case 4:
u8g2.drawXBMP( 86 , 0 , 30 , 30 , Cloudy );
u8g2.setFont(u8g2_font_wqy12_t_gb2312);
u8g2.drawStr(86,40,"Cloudy");
break;
case 9:
u8g2.drawXBMP(86 , 0 , 30 , 30 , Overcast );
u8g2.setFont(u8g2_font_wqy12_t_gb2312);
u8g2.drawStr(86,40,"Overcast");
break;
case 10:
u8g2.drawXBMP( 86 , 0, 30 , 30 , Shower );
u8g2.setFont(u8g2_font_wqy12_t_gb2312);
u8g2.drawStr(86,40,"Shower");
break;
case 11:
u8g2.drawXBMP( 86 , 0 , 30 , 30 , Thundershower );
u8g2.setFont(u8g2_font_wqy12_t_gb2312);
u8g2.drawStr(86,40,"Thundershower");
break;
case 13:
u8g2.drawXBMP( 86 , 0 , 30 , 30 , Rain_L );
u8g2.setFont(u8g2_font_wqy12_t_gb2312);
u8g2.drawStr(86,40,"Rain_L");
break;
case 14:
u8g2.drawXBMP( 86 , 0 , 30 , 30 , Rain_M );
u8g2.setFont(u8g2_font_wqy12_t_gb2312);
u8g2.drawStr(86,40,"Rain_M");
break;
case 15:
u8g2.drawXBMP( 86 , 0 , 30 , 30 , Rain_H );
u8g2.setFont(u8g2_font_wqy12_t_gb2312);
u8g2.drawStr(86,40,"Rain_H");
break;
case 30:
u8g2.drawXBMP(86 , 0 , 30, 30, Foggy );
u8g2.setFont(u8g2_font_wqy12_t_gb2312);
u8g2.drawStr(86,40,"Foggy");
break;
case 31:
u8g2.drawXBMP(86 , 30 , 30 , 30 , Haze );
u8g2.setFont(u8g2_font_wqy12_t_gb2312);
u8g2.drawStr(86,40,"Haze");
break;
}
u8g2.sendBuffer();
}
五、项目应用与拓展
实际应用场景
这款 ESP8266+OLED 时间天气显示设备具有广泛的应用场景。在家庭环境中,可以将其放置在客厅、卧室、厨房等各个房间,方便家庭成员随时查看时间与天气情况,合理安排日常活动。例如,在早晨起床时,通过查看设备上的天气预报,决定是否需要增添衣物或携带雨具;在准备外出时,快速了解当前的天气状况,选择合适的出行方式。在办公场所,将其摆放在办公桌上,员工在工作间隙也可以方便查看。