/*NTP ESP-8266 Clock By Sebouh
Please Use the Provided Librarerires
For Compiling USE Arduino IDE 1.6.5
*/
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WiFi
#include <DNSServer.h> //https://github.com/esp8266/Arduino/tree/master/libraries/DNSServer
#include <ESP8266WebServer.h> //https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WebServer
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <TimeLib.h> //https://github.com/PaulStoffregen/Time
#include <Timezone.h> //https://github.com/JChristensen/Timezone
#include <LedControl.h> // https://github.com/wayoda/LedControl/releases MAX7219 7 segment driver
/*For ESP-01 Don't Change GPIO Values
// GPIO0= DIN pin, GPIO1 = CLK pin, GPIO 2 = LOAD pin
LedControl lc = LedControl(0, 1, 2, 1)
//Reset Button Connected On GPIO3 and Ground
int inPin = 3;
*/
char* weekdays[] = { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" };
const char compile_date[] = __DATE__ " " __TIME__ " " __FILE__;
// HOSTNAME for OTA update
#define HOSTNAME "ESP8266-OTA-"
//For ESP-07 Tested GPIO Values
// EasyESP or NodeMCU Pin D8 to DIN, D7 to Clk, D6 to LOAD, no.of devices is 1
LedControl lc = LedControl(D8, D7, D6, 2);
// the GPIO number For The "Reset" Push Button Switch Pin For ESp-07 Tested
int inPin = 5;
//Edit These Lines According To Your Timezone and Daylight Saving Time
//TimeZone Settings Details https://github.com/JChristensen/Timezone
TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; //Central European Time (Frankfurt, Paris)
TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; //Central European Time (Frankfurt, Paris)
Timezone CE(CEST, CET);
//Pointer To The Time Change Rule, Use to Get The TZ Abbrev
TimeChangeRule *tcr;
time_t utc, local;
// time_t utc ;
//NTP Server http://tf.nist.gov/tf-cgi/servers.cgi
static const char ntpServerName[] = "de.pool.ntp.org";
WiFiUDP Udp;
// Local Port to Listen For UDP Packets
uint16_t localPort;
int devices;
bool Flag;
// ------------------------------------------------------------------------------------------
// Setup Details
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println(compile_date);
//we have already set the number of devices when we created the LedControl
devices = lc.getDeviceCount();
//we have to init all devices in a loop
for (int address = 0; address < devices; address++) {
/*The MAX72XX is in power-saving mode on startup*/
lc.shutdown(address, false);
/* Set the brightness to a medium values */
lc.setIntensity(address, 5);
/* and clear the display */
lc.clearDisplay(address);
}
//Display <StArt>
lc.setRow(0, 6, 0x5b);
lc.setRow(0, 5, 0x0f);
lc.setRow(0, 4, 0x77);
lc.setRow(0, 3, 0x05);
lc.setRow(0, 2, 0x0f);
delay(500);
// Switch Type
pinMode(inPin, INPUT_PULLUP);
//WiFiManager
//Local intialization.
WiFiManager wifiManager;
//AP Configuration
wifiManager.setAPCallback(configModeCallback);
//Exit After Config Instead of connecting
wifiManager.setBreakAfterConfig(true);
//Reset Settings - If Button Pressed
if (digitalRead(inPin) == LOW) {
//Display <Reset>
lc.clearDisplay(0);
lc.setRow(0, 6, 0x05);
lc.setRow(0, 5, 0x4f);
lc.setRow(0, 4, 0x5b);
lc.setRow(0, 3, 0x6f);
lc.setRow(0, 2, 0x0f);
delay(5000);
wifiManager.resetSettings();
//ESP.reset();
ESP.restart();
}
/*
Tries to connect to last known settings
if it does not connect it starts an access point with the specified name
here "AutoConnectAP" without password (uncomment below line and comment
next line if password required)
and goes into a blocking loop awaiting configuration
*/
//If You Require Password For Your NTP Clock
// if (!wifiManager.autoConnect("NTP Clock", "password"))
//If You Dont Require Password For Your NTP Clock
if (!wifiManager.autoConnect("NTP-Clock")) {
delay(3000);
ESP.reset();
delay(5000);
}
//Display <Connect> Once Connected to AP
lc.setRow(0, 7, 0x4e);
lc.setRow(0, 6, 0x1d);
lc.setRow(0, 5, 0x15);
lc.setRow(0, 4, 0x15);
lc.setChar(0, 3, 'E', false);
lc.setRow(0, 2, 0x0d);
lc.setRow(0, 1, 0x0f);
Serial.println("Connect");
delay(3000);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
char result[255];
sprintf(result, "WebServer ready at %1d.%1d.%1d.%1d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]);
Serial.println();
Serial.println(result);
// Seed Random With vVlues Unique To This Device
uint8_t macAddr[6];
WiFi.macAddress(macAddr);
uint32_t seed1 =
(macAddr[5] << 24) | (macAddr[4] << 16) |
(macAddr[3] << 8) | macAddr[2];
// randomSeed(WiFi.localIP() + seed1 + micros());
randomSeed(seed1 + micros());
localPort = 8888;
localPort = random(1024, 65535);
Udp.begin(localPort);
setSyncProvider(getNtpTime);
//Set Sync Intervals
setSyncInterval(5 * 60);
}
void loop() {
// when the digital clock was displayed
static time_t prevDisplay = 0;
timeStatus_t ts = timeStatus();
utc = now();
switch (ts) {
case timeNeedsSync:
Serial.println("timeNeedsSync");
case timeSet:
//update the display only if time has changed
if (now() != prevDisplay) {
prevDisplay = now();
digitalClockDisplay();
tmElements_t tm;
breakTime(now(), tm);
//If Time Needs Sync Display a "-" On Last Digit
if (ts == timeNeedsSync) {
// lc.setChar(0, 1, '-', false);
lc.setChar(0, 2, '_', false);
}
//else {
//lc.setDigit(0, 2, (second() % 10), false);
// }
}
break;
case timeNotSet:
//Display <No Sync> If Time Not Displayed
lc.clearDisplay(0);
lc.setRow(0, 7, 0x15);
lc.setRow(0, 6, 0x1d);
lc.setRow(0, 4, 0x5b);
lc.setRow(0, 3, 0x3b);
lc.setRow(0, 2, 0x15);
lc.setRow(0, 1, 0x0d);
Serial.println("No Sync");
now();
delay(3000);
ESP.restart();
}
}
//#####################################################
unsigned int HexToBCD(unsigned int number)
{
unsigned char i = 0;
unsigned int k = 0;
while (number)
{
k = (k) | ((number % 10) << i * 4);
number = number / 10;
i++;
}
return (k);
}
void digitalClockDisplay() {
tmElements_t tm;
char *dayOfWeek;
breakTime(now(), tm);
lc.clearDisplay(0);
// Start with left digit
int H = int(hour(CE.toLocal(utc, &tcr)) / 10);
if (H == 0) {
lc.setChar(0, 7, ' ', false);
} else {
lc.setDigit(0, 7, H, false);
}
lc.setDigit(0, 6, (hour(CE.toLocal(utc, &tcr)) % 10), false);
lc.setChar(0, 5, '-', false);
lc.setDigit(0, 4, (minute() / 10), false);
lc.setDigit(0, 3, (minute() % 10), false);
lc.setChar(0, 2, '-', false);
lc.setDigit(0, 1, int(second() / 10), false);
lc.setDigit(0, 0, (second() % 10), false);
int D = int(day(CE.toLocal(utc, &tcr)) / 10);
if (D == 0) {
lc.setChar(1, 7, ' ', false);
} else {
lc.setDigit(1, 7, D, false);
}
lc.setDigit(1, 6, (day(CE.toLocal(utc, &tcr)) % 10), true);
int M = int(month(CE.toLocal(utc, &tcr)) / 10);
if (M == 0) {
lc.setChar(1, 5, ' ', false);
} else {
lc.setDigit(1, 5, M, false);
}
lc.setDigit(1, 4, (month(CE.toLocal(utc, &tcr)) % 10), true);
unsigned int count_one;
count_one = HexToBCD(year(CE.toLocal(utc, &tcr)));
lc.setDigit(1, 3, ((count_one >> 12) & 0x0F), false);
lc.setDigit(1, 2, ((count_one >> 8) & 0x0F), false);
lc.setDigit(1, 1, ((count_one >> 4) & 0x0F), false);
lc.setDigit(1, 0, (count_one & 0x0F), false);
utc = now();
local = CE.toLocal(utc, &tcr);
printTime(local, tcr -> abbrev);
}
// ----------------------------------------------
// Function to print time with time zone
// ----------------------------------------------
void printTime(time_t t, char *tz)
{
char cb [128];
sprintf(cb, "%s, %02d.%02d.%04d %02d:%02d:%02d %s", (weekdays[weekday(t) - 1]), day(t), month(t), year(t), hour(t), minute(t), second(t), tz ) ;
Serial.println(cb);
}
/*-------- NTP code ----------*/
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
time_t getNtpTime()
{
IPAddress timeServerIP; // time.nist.gov NTP server address
while (Udp.parsePacket() > 0) ; // discard any previously received packets
Serial.print(F("Transmit NTP Request "));
//get a random server from the pool
WiFi.hostByName(ntpServerName, timeServerIP);
Serial.println(timeServerIP);
sendNTPpacket(timeServerIP);
uint32_t beginWait = millis();
while ((millis() - beginWait) < 1500) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
return secsSince1900 - 2208988800UL;
}
}
return 0; // return 0 if unable to get the time
}
// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
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;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
Udp.beginPacket(address, 123); //NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
//To Display <Setup> if not connected to AP
void configModeCallback (WiFiManager *myWiFiManager) {
lc.clearDisplay(0);
lc.setRow(0, 7, 0x5b);
lc.setChar(0, 6, 'E', false);
lc.setRow(0, 5, 0x0f);
lc.setRow(0, 4, 0x03e);
lc.setChar(0, 3, 'P', false);
delay(2000);
}
Comments