2017/05/14
NTP Server Synchronized LCD DS1307 RTC Clock
Requirements:
1. Arduino Uno R3
2. RTC (DS1307) Sensor Shield
3. W5100 Ethernet Shield
4. LCD Keypad Shield
Schetch:
/*
* NTPSynchronizedRTC20170514.ino
*/
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <Time.h>
#include <Wire.h>
#include <DS1307RTC.h> // a basic DS1307 library that returns time as a time_t
#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,4,5,6,7);
char dayOfWeek[9][4] = {"", "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
time_t t;
int displayAtSecond;
// timeZoneOffset = (Time Zone) * 3600L eg. (+8) * 3600L = 28800L for Taipei, Taiwan
const long timeZoneOffset = 28800L;
// sync to NTP server every "ntpSyncInterval" seconds, set to 1 hour or more to be reasonable
unsigned long ntpSyncInterval = 3600;
// adjust the sync latency with computer NTP client in seconds
unsigned long syncLatency = 0;
// Enter a MAC address for your controller bellow.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
unsigned int localPort = 8888; // local port to listen for UDP packets
IPAddress timeServer(192, 168, 1, 123); // LAN NTP server
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[NTP_PACKET_SIZE]; // buffer to hold incoming and outgoing packets
// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
// keep track of how long ago we updated the NTP server
unsigned long ntpLastUpdate = 0;
void setup() {
Serial.begin(115200);
lcd.begin(16,2);
lcd.print("*cheaphousetek*");
lcd.setCursor(0,1);
setSyncProvider(RTC.get); // the function to get the time from the RTC
if(timeStatus()!= timeSet)
lcd.print("Unable to sync");
else
lcd.print("Sync system time ");
displayAtSecond = second();
delay(2000);
lcd.clear();
// start Ethernet and UDP
if (Ethernet.begin(mac) == 0) {
lcd.setCursor(0,1);
lcd.print("DHCP failed");
for (;;);
}
Udp.begin(localPort);
}
void loop()
{
if ((now() - ntpLastUpdate) >= ntpSyncInterval) {
ntpSyncDS1307();
// clear seconds displayed once a second when sync is needed, cause seconds blink to notify checking the network status
lcd.setCursor(9, 1);
lcd.print(" ");
}
// for LCD shield to disp date, day of the week, time and temperature once a second
t = now();
if (displayAtSecond != second(t)) {
digitalClockDisplay();
displayAtSecond = second(t);
}
}
void digitalClockDisplay(){
// digital clock display of the time
dateDisplay();
weekdayDisplay();
timeDisplay();
// display seconds since last NTP update
lcd.setCursor(9, 1);
lcd.print(now()-ntpLastUpdate);
// Serial.print(now());
// Serial.print(" ");
// Serial.println(ntpLastUpdate);
}
void dateDisplay() {
lcd.setCursor(0,0);
lcd.print(year(t));
lcd.print('-');
if (month(t) < 10) {
lcd.print('0');
}
lcd.print(month(t));
lcd.print('-');
if (day(t) < 10) {
lcd.print('0');
}
lcd.print(day(t));
// lcd.print(' ');
}
void weekdayDisplay() {
lcd.setCursor(11,0);
lcd.print(dayOfWeek[weekday()]);
}
void timeDisplay() {
lcd.setCursor(0,1);
if (hour(t) < 10) {
lcd.print('0');
}
lcd.print(hour(t));
lcd.print(':');
if (minute(t) < 10) {
lcd.print('0');
}
lcd.print(minute(t));
lcd.print(':');
if (second(t) < 10) {
lcd.print('0');
}
lcd.print(second(t));
// lcd.print(' ');
}
void ntpSyncDS1307() {
sendNTPpacket(timeServer); // send an NTP packet to a time server
// wait to see if a replay is available
delay(100);
if (Udp.parsePacket()) {
// We've received a packet, read the data from it
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
// the timstamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, extract the two words:
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900)
unsigned long secsSince1900 = highWord << 16 | lowWord;
// now convert NTP time into everyday time:
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const unsigned long seventyYears = 2208988800L;
// substract seventy years:
unsigned long epoch = secsSince1900 - seventyYears + timeZoneOffset + syncLatency;
setTime(epoch);
RTC.set(epoch);
ntpLastUpdate = now();
// clear seconds displayed once ntp sync succeeded
lcd.setCursor(9, 1);
lcd.print(" ");
}
}
// 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 clodk
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);
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
Subscribe to:
Posts (Atom)