NittyGritty icon

NTP_WiFi_Clock.ino

NittyGritty | PRO | 01/16/22 09:45:34 AM UTC | 0 ⭐ | 1312 👁️ | Never ⏰ | []
C++ |

10.7 KB

|

None

|

0 👍

/

0 👎

/*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