这里的esp8266选用D1 mini开发板,DS1302加I2C转接模块。首先上效果图。
接着上代码。
/* ---By www.yizu.org---
Connect
D1 mini I2C_LCD
5V VCC
GND GND
D2 SDA
D1 SCL
D1 mini DS1302
3V3 VCC
GND GND
D6 CLK
D7 DAT
D8 RST
*/
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <LiquidCrystal_I2C.h>
#include <TimeLib.h>
#include <Arduino.h>
#include <DS1302.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
//设置NTPClient
#define NTP_OFFSET 60 * 60 * 8 // 时区偏移量
#define NTP_ADDRESS "ntp1.aliyun.com" // NTP服务器
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, NTP_ADDRESS, NTP_OFFSET);
//设置时钟模块
DS1302 rtc(15,13,12);
//设置校对时间间隔(单位秒)
#define CALIBRATION_INTERVAL 60
unsigned long t_stamp=0;
unsigned long t_stamp2=0;
//设置WIFI账号密码
const char* ssid = "wifi";
const char* password = "123456789";
//显示字符
#if defined(ARDUINO) && ARDUINO >= 100
#define printByte(args) write(args);
#else
#define printByte(args) print(args,BYTE);
#endif
//要显示的特殊字符
//uint8_t nian[8] = {0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,};//年
//uint8_t yue[8] = {0x0f,0x09,0x0f,0x09,0x0f,0x09,0x0b,0x11,};//月
//uint8_t ri[8] = {0x1F,0x11,0x11,0x1F,0x11,0x11,0x1F,0x00,};//日
uint8_t dian[8] = {0x02,0x05,0x02,0x00,0x00,0x00,0x00,0x00,};//点
uint8_t dianC[8] ={0x00,0x17,0x08,0x08,0x08,0x08,0x07,0x00,};//温度单位
uint8_t wificon[8] ={0x00,0x0E,0x11,0x04,0x0A,0x00,0x04,0x00,};//WIFI链接
uint8_t wificon2[8]={0x00,0x11,0x0A,0x04,0x0A,0x11,0x00,0x00,};//断网
const char * days[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"} ;
//连接WIFI
void connectToWiFi()
{
Serial.println("");
Serial.print("Connecting to ");
Serial.print(ssid);
WiFi.begin(ssid, password);
Serial.println("");
Serial.print("Connected to WiFi at ");
Serial.print(WiFi.localIP());
Serial.println("");
unsigned int count = 0;
while ((count < 10 ) & (WiFi.status() != WL_CONNECTED)) {
delay(500);
Serial.print(".");
count ++;
}
}
//显示WIFI连接状态
void showWifiStatus()
{
lcd.setCursor(11, 0);
if(WiFi.status() == WL_CONNECTED)
{
lcd.write(byte(5));
}
else
{
lcd.write(byte(6));
}
}
//校对时间
void correctionTime()
{
time_t tnow=now();
if(t_stamp==0||tnow-t_stamp>=10)//每10秒校对系统时钟
{
Serial.println("");
Serial.print(rtc.getTimeStr());
Serial.print(" Correction the time.");
if(WiFi.status() == WL_CONNECTED&&(t_stamp2==0||tnow-t_stamp2>=CALIBRATION_INTERVAL))
{
if(timeClient.update())
{
unsigned long t=timeClient.getEpochTime();
//设置系统时间
setTime(t);
Serial.println("");
Serial.print("SysTime=NTP:");
Serial.printf("%02d:%02d:%02d",hour(t), minute(t), second(t));
//设置RTC时钟
if(rtc.peek(0)==88)
{
rtc.writeProtect(false);
rtc.setDOW(weekday(t)+1);
rtc.setTime(hour(t), minute(t), second(t));
rtc.setDate(day(t), month(t), year(t));
rtc.writeProtect(true);
}
}
else
{
if(rtc.peek(0)==88)
{
//设置系统时间
Time t=rtc.getTime();
setTime(t.hour,t.min,t.sec,t.date,t.mon,t.year);
Serial.println("");
Serial.print("SysTime=RTC:");
Serial.printf("%02d:%02d:%02d",t.hour,t.min,t.sec);
}
}
t_stamp2=now();
}
else
{
if(rtc.peek(0)==88)
{
//设置系统时间
Time t=rtc.getTime();
setTime(t.hour,t.min,t.sec,t.date,t.mon,t.year);
Serial.println("");
Serial.print("SysTime=RTC:");
Serial.printf("%02d:%02d:%02d",t.hour,t.min,t.sec);
}
}
t_stamp=now();
}
}
void setup()
{
Serial.begin(115200);
lcd.init();// 初始化lcd
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Starting...");
lcd.setCursor(0, 1);
lcd.print("Please wait.");
//联网
connectToWiFi();
//初始化NTPClient
timeClient.begin();
//开启时钟
if(rtc.peek(0)!=88)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("System reseted!");
rtc.writeProtect(false);
rtc.halt(false);
rtc.poke(0,88);//写入启动标记
rtc.writeProtect(true);
delay(1000);
}
//对时
correctionTime();
lcd.clear();
}
void loop()
{
correctionTime();
// 打印到屏幕
//lcd.createChar(1, nian);
//lcd.createChar(2, yue);
//lcd.createChar(3, ri);
lcd.createChar(4, dianC);
lcd.createChar(5, wificon);
lcd.createChar(6, wificon2);
time_t t=now();
lcd.setCursor(0, 0);
//lcd.printf("%04d",year(t));
//lcd.write(byte(1));
//lcd.printf("%02d",month(t));
//lcd.write(byte(2));
//lcd.printf("%02d",day(t));
//lcd.write(byte(3));
lcd.printf("%04d-%02d-%02d",year(t),month(t),day(t));
lcd.setCursor(9, 1);
lcd.print(days[weekday(t)-1]);
lcd.setCursor(0, 1);
lcd.printf("%02d:%02d:%02d",hour(t),minute(t),second(t));
lcd.setCursor(13, 0);
lcd.print("30");//显示温度,暂未加入该功能
lcd.write(byte(4));
lcd.setCursor(13, 1);
lcd.print("25%");//显示湿度,暂未加入该功能
showWifiStatus();
}
DS1302模块的库下载自http://www.rinkydinkelectronics.com/library.php?id=5,其他库均可在Arduino IDE中搜索下载。
此段代码可以做到没有网络,或者去掉DS1302时都可正常运行。代码中,每隔10秒系统与DS1302模块校对时间,每隔60秒与NTP服务器校对时间,可以按需修改即可。屏幕上显示了一个WIFI连接的图标,WIFI断开时会显示一个“X”。