2020-07-21
esp8266网络时钟
#include <TimeLib.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <SPI.h>
#include <DYWiFiConfig.h>
#include <U8g2lib.h>
//若屏幕使用SH1106,只需把SSD1306改为SH1106即可
U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=/4, / dc=/5, / reset=/3);
//U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, / reset=/ U8X8_PIN_NONE);
//8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, / reset=/ U8X8_PIN_NONE, / clock=/ 4, / data=*/ 5); //D-duino
DYWiFiConfig wificonfig;
ESP8266WebServer webserver(80);
#define DEF_WIFI_SSID
#define DEF_WIWI_PASSWORD “12345678”
#define AP_NAME “ESP8266” //dev
void wificb(int c)
{
Serial.print("=-=-=-=-");
Serial.println©;
}
static const char ntpServerName[] = “ntp1.aliyun.com”; //NTP服务器,阿里云
const int timeZone = 8; //时区,北京时间为+8
WiFiUDP Udp;
unsigned int localPort = 8888; // 用于侦听UDP数据包的本地端口
time_t getNtpTime();
void sendNTPpacket(IPAddress& address);
void oledClockDisplay();
void sendCommand(int command, int value);
void initdisplay();
boolean isNTPConnected = false;
const unsigned char xing[] U8X8_PROGMEM = {
0x00, 0x00, 0xF8, 0x0F, 0x08, 0x08, 0xF8, 0x0F, 0x08, 0x08, 0xF8, 0x0F, 0x80, 0x00, 0x88, 0x00,
0xF8, 0x1F, 0x84, 0x00, 0x82, 0x00, 0xF8, 0x0F, 0x80, 0x00, 0x80, 0x00, 0xFE, 0x3F, 0x00, 0x00
}; /星/
const unsigned char liu[] U8X8_PROGMEM = {
0x40, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00,
0x20, 0x02, 0x20, 0x04, 0x10, 0x08, 0x10, 0x10, 0x08, 0x10, 0x04, 0x20, 0x02, 0x20, 0x00, 0x00
}; /六/
void setup()
{
Serial.begin(115200);
while (!Serial)
continue;
Serial.println(“NTP Clock oled version v1.1”);
Serial.println(“Designed by flyAkari”);
initdisplay();
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_unifont_t_chinese2);
u8g2.setCursor(0, 14);
u8g2.print(“Waiting for WiFi”);
u8g2.setCursor(0, 30);
u8g2.print(“connection…”);
u8g2.setCursor(0, 47);
u8g2.print(“zfq0620”);
u8g2.setCursor(0, 64);
u8g2.print(“192.168.4.1”);
u8g2.sendBuffer();
Serial.println(“OLED Ready”);
Serial.print(“Connecting WiFi…”);
wificonfig.begin(&webserver, “/”);
DYWIFICONFIG_STRUCT defaultConfig = wificonfig.createConfig();
strcpy(defaultConfig.SSID, DEF_WIFI_SSID);
strcpy(defaultConfig.SSID_PASSWORD, DEF_WIWI_PASSWORD);
strcpy(defaultConfig.HOSTNAME, AP_NAME);
strcpy(defaultConfig.APNAME, AP_NAME);
wificonfig.setDefaultConfig(defaultConfig);
wificonfig.enableAP();
while (WiFi.status() != WL_CONNECTED)
{
wificonfig.handle(); //若不需要Web后台,可以注释掉此行
//Serial.println(“Waiting for Connection…”);
}
Serial.println("");
Serial.println(“WiFi connected”);
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println(“Starting UDP”);
Udp.begin(localPort);
Serial.print("Local port: ");
Serial.println(Udp.localPort());
Serial.println(“waiting for sync”);
setSyncProvider(getNtpTime);
setSyncInterval(30); //每300秒同步一次时间
isNTPConnected = true;
}
time_t prevDisplay = 0; //当时钟已经显示
void loop()
{
if (timeStatus() != timeNotSet)
{
if (now() != prevDisplay)
{ //时间改变时更新显示
prevDisplay = now();
oledClockDisplay();
}
}
wificonfig.handle(); //若不需要Web后台,可以注释掉此行
}
void initdisplay()
{
u8g2.begin();
u8g2.enableUTF8Print();
}
void oledClockDisplay()
{
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();
u8g2.setFont(u8g2_font_unifont_t_chinese2);
u8g2.setCursor(0, 14);
if (isNTPConnected)
u8g2.print(“当前时间 (UTC+8)”);
else
u8g2.print(“无网络!”); //如果上次对时失败,则会显示无网络
String currentTime = “”;
if (hours < 10)
currentTime += 0;
currentTime += hours;
currentTime += “:”;
if (minutes < 10)
currentTime += 0;
currentTime += minutes;
currentTime += “:”;
if (seconds < 10)
currentTime += 0;
currentTime += seconds;
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_tr);
u8g2.setCursor(0, 44);
u8g2.print(currentTime);
u8g2.setCursor(0, 61);
u8g2.setFont(u8g2_font_unifont_t_chinese2);
u8g2.print(currentDay);
u8g2.drawXBM(80, 48, 16, 16, xing);
u8g2.setCursor(95, 62);
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.drawXBM(111, 49, 16, 16, liu);
u8g2.sendBuffer();
}
/-------- NTP 代码 ----------/
const int NTP_PACKET_SIZE = 48; // NTP时间在消息的前48个字节里
byte packetBuffer[NTP_PACKET_SIZE]; // 输入输出包的缓冲区
time_t getNtpTime()
{
IPAddress ntpServerIP; // NTP服务器的地址
while (Udp.parsePacket() > 0); // 丢弃以前接收的任何数据包
Serial.println(“Transmit NTP Request”);
// 从池中获取随机服务器
WiFi.hostByName(ntpServerName, ntpServerIP);
Serial.print(ntpServerName);
Serial.print(": ");
Serial.println(ntpServerIP);
sendNTPpacket(ntpServerIP);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500)
{
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE)
{
Serial.println(“Receive NTP Response”);
isNTPConnected = true;
Udp.read(packetBuffer, NTP_PACKET_SIZE); // 将数据包读取到缓冲区
unsigned long secsSince1900;
// 将从位置40开始的四个字节转换为长整型,只取前32位整数部分
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
Serial.println(secsSince1900);
Serial.println(secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR);
return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
}
}
Serial.println(“No NTP Response ????”); //无NTP响应
isNTPConnected = false;
return 0; //如果未得到时间则返回0
}
// 向给定地址的时间服务器发送NTP请求
void sendNTPpacket(IPAddress& address)
{
memset(packetBuffer, 0, NTP_PACKET_SIZE);
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
Udp.beginPacket(address, 123); //NTP需要使用的UDP端口号为123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}