ESP8266天气时钟-SSD1306oled显示屏
分享一个代码,是B站上一个up主分享的,太菜的我只是搬运稍加修改一下就费了半天劲。在这里记录一下,免得以后找不到了。
up主的视频页面:https://www.bilibili.com/video/BV1dT4y1c7uV?from=search&seid=4324927137025240016
但我推荐参考我下面的教程,因为那个视频没有任何教学介绍,可参考的只有附的GitHub代码地址。
那就开始吧
首先接线:**看不懂u8g2库的我差点连接线都不会
ESP8266 | SSD1306OLED |
---|---|
3.3V | VCC |
GND | GND |
D1 | SCL |
D2 | SDA |
用到的几个库(只列举arduino IDE库管理器中搜不到的):
WiFiManager库:https://wwa.lanzous.com/ibBlTe9jaif
Seniverse库:https://wwa.lanzous.com/irrqvdns63i
还有2个小问题:
1.如果你要用的8266板之前写过带有WiFi信息的程序,那么此程序中的WiFimanager库配网功能将不会起作用,esp8266会自动连接闪存文件系统里里面保存的之前的WiFi连接信息,想要它起作用的话,要先清除掉之前的WiFi信息。只需要先写入以下程序即可:
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
void setup() {
Serial.begin(9600);
// 建立WiFiManager对象
WiFiManager wifiManager;
// 清除ESP8266所存储的WiFi连接信息以便测试WiFiManager工作效果
wifiManager.resetSettings();
Serial.println("ESP8266 WiFi Settings Cleared");
}
void loop() {}
2.第二个小问题就是在写入这个完整程序的时候可能会出现内存不够而写入失败报错的情况,例如:
我找到的解决办法是先写入一个小的示例程序,这样就会把之前开发板里面的程序抹除掉,释放内存。然后在写入最后的完整程序,可能会有别的解决办法,但是我还不太了解,可以用下面这个(arduino IDE示例里面的):
int led = 9; // the PWM pin the LED is attached to
int brightness = 0; // how bright the LED is
int fadeAmount = 5; // how many points to fade the LED by
// the setup routine runs once when you press reset:
void setup() {
// declare pin 9 to be an output:
pinMode(led, OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
// set the brightness of pin 9:
analogWrite(led, brightness);
// change the brightness for next time through the loop:
brightness = brightness + fadeAmount;
// reverse the direction of the fading at the ends of the fade:
if (brightness <= 0 || brightness >= 255) {
fadeAmount = -fadeAmount;
}
// wait for 30 milliseconds to see the dimming effect
delay(30);
}
程序里面有一个地方需要修改成你的密钥和你所在的城市。城市直接写你想写的城市的拼音代替掉我的程序里面的beijing即可,密钥的话需要注册一个心知天气账号,注册之后点击右上角控制台
,再点击我的免费产品,然后使下图红框中的私钥可见之后复制替换点程序中的******即可(参考步骤图见下)
最后写入下面这个程序就应该没问题了。
写入程序以后,如果你的esp8266开发板是一个未用过的新开发板,或者你按照我最开始的步骤清除了esp8266开发板中的WiFi连接信息,那么我们就需要对写入下面程序的的开发板进行配网。(看似变得麻烦了,但是这样可以使得在新的WiFi环境中不用重新编辑程序烧录即可连接新的WiFi)
具体步骤:
用你的手机连接一个WiFi热点,这个WiFi热点是你的esp8266产生的,热点的名称取决于下面程序最后一行wifiManager.autoConnect("AutoConnectAP");
括号里引号里面的名字,像这个程序你不更改直接写入的话你要找的热点名称就是就是AutoConnectAP,点击并连接它,会弹出一个认证页面(这里未汉化,英文的页面),你可以参考下面汉化过的图片进行WiFi配置连接,在进一步弹出的页面中输入你家的WiFi名称和密码然后点击右上角对号保存就可以了
完整程序:
#include <ESP8266WiFi.h>
#include <ESP8266_Seniverse.h>
#include <U8g2lib.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <WiFiManager.h>
#define rst 2
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0 , rst);
// weather
const String weathers[] = {"晴", "晴", "晴", "晴", "多云", "晴间多云", "晴间多云", "大部多云", "大部多云", "阴",
"阵雨", "雷阵雨", "雷雨冰雹", "小雨", "中雨", "大雨", "暴雨", "大暴雨", "特大暴雨",
"冻雨", "雨夹雪", "阵雪", "小雪", "中雪", "大雪", "暴雪", "浮尘", "扬沙", "沙尘暴",
"强沙暴", "雾", "霾", "风", "大风", "飓风", "热带风暴", "龙卷风", "冷", "热", "未知"
};
const unsigned char mi[] U8X8_PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xF0, 0xFF, 0xFF, 0x1F, 0x80, 0x3F, 0xFC, 0xF0, 0xFF, 0xFF, 0x7F, 0x80,
0x3F, 0xFC, 0xF0, 0xFF, 0xFF, 0xFF, 0x80, 0x3F, 0xFC, 0xF0, 0xFF, 0xFF, 0xFF, 0x81, 0x3F, 0xFC, 0xF0, 0xFF, 0xFF, 0xFF, 0x81, 0x3F, 0xFC, 0xF0, 0xFF, 0xFF, 0xFF, 0x83, 0x3F, 0xFC, 0xF0, 0x07,
0x00, 0xFC, 0x83, 0x3F, 0xFC, 0xF0, 0x07, 0x00, 0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x07, 0x00, 0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x07, 0x00, 0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x07, 0x3F, 0xF8, 0x83, 0x3F,
0xFC, 0xF0, 0x87, 0x3F, 0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x87, 0x3F, 0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x87, 0x3F, 0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x87, 0x3F, 0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x87, 0x3F,
0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x87, 0x3F, 0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x87, 0x3F, 0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x87, 0x3F, 0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x87, 0x3F, 0xF8, 0x83, 0x3F, 0xFC,
0xF0, 0x87, 0x3F, 0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x87, 0x3F, 0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x87, 0x3F, 0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x87, 0x3F, 0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x87, 0x3F, 0xF8,
0x83, 0x3F, 0xFC, 0xF0, 0x87, 0x3F, 0xF8, 0x83, 0x3F, 0xFC, 0xF0, 0x87, 0x3F, 0xF8, 0x83, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC
};
String reqUserKey = "*********";// 你的心知天气私钥
String reqLocation = "beijing";// 你的城市(拼音)
String reqUnit = "c";// 摄氏/华氏
WeatherNow weatherNow;
Forecast forecast;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "ntp1.aliyun.com", 60 * 60 * 8, 30 * 60 * 1000);
int times = 0;
void setup() {
Serial.begin(9600);
u8g2.begin();
u8g2.enableUTF8Print();
u8g2.clearBuffer();
u8g2.drawXBMP( 39 , 0 , 50 , 50, mi );
u8g2.setFont(u8g2_font_wqy12_t_gb2312);
u8g2.setCursor(20, 60);
u8g2.print("小米为发烧而生");
u8g2.sendBuffer();
delay(850);
connectWiFi();// 连接wifi
// 配置心知天气请求信息
weatherNow.config(reqUserKey, reqLocation, reqUnit);
forecast.config(reqUserKey, reqLocation, reqUnit);
timeClient.begin();
}
void loop() {
u8g2.clearBuffer();// 清空显示设备内部缓冲区
u8g2.setFont(u8g2_font_wqy12_t_gb2312);
//天气
if (weatherNow.update() && forecast.update()) { // 更新天气信息
//今天的天气、温度
u8g2.setCursor(43, 12);
String str1 = weathers[weatherNow.getWeatherCode()] + " " + weatherNow.getDegree() + "℃(今天)";
u8g2.print(str1);
//明天的天气、温度范围
u8g2.setCursor(43, 27);
str1 = weathers[forecast.getDayCode(1)] + " " + forecast.getLow(1) + "-" + forecast.getHigh(1) + "℃";
u8g2.print(str1);
//后天的天气、温度范围
u8g2.setCursor(43, 42);
str1 = weathers[forecast.getDayCode(2)] + " " + forecast.getLow(2) + "-" + forecast.getHigh(2) + "℃";
u8g2.print(str1);
} else {// 更新失败
//u8g2.setCursor(53, 61);
//u8g2.print(">_<...网络慢");
}
//时间
u8g2.setFont(u8g2_font_wqy16_t_gb2312);
if (timeClient.update()) {
u8g2.setCursor(53, 61);
String time = timeClient.getFormattedTime().substring(0, 5);
u8g2.print(time);
} else {
//u8g2.setCursor(53, 61);
//u8g2.print(">_<...网络慢");
}
u8g2.setFont(u8g2_font_unifont_t_symbols); //先设置字体字集
if (times == 0) {
u8g2.drawGlyph(13, 18, 0x2603);
u8g2.drawGlyph(13, 38, 0x2615);
u8g2.drawGlyph(15, 58, 0x2600);
times = 1;
} else if (times == 1) {
u8g2.drawGlyph(13, 18, 0x23f0);
u8g2.drawGlyph(13, 38, 0x23f3);
u8g2.drawGlyph(15, 58, 0x2614);
times = 2;
} else {
u8g2.drawGlyph(13, 18, 0x2618);
u8g2.drawGlyph(13, 38, 0x2619);
u8g2.drawGlyph(15, 58, 0x2606);
times = 0;
}
u8g2.sendBuffer();// 显示缓冲区内容
delay(10000);
}
// 连接WiFi
void connectWiFi() {
// 建立WiFiManager对象
WiFiManager wifiManager;
// 自动连接WiFi。以下语句的参数是连接ESP8266时的WiFi名称
wifiManager.autoConnect("AutoConnectAP");
}
运行效果见下图(刚开始会有一个小米标志的图像,配网成功获取到数据以后就是下面的正常状态了):