So I know we need a RTC to keep time correctly but can it be done using just code and NTP? Also if not any idea on what I need to build one?
I have included the code for my clock as I would really appreciate some feedback. My clock seemed to be ok it got an IP via DHCP then got the time via NTP but over time it ends up behind about an hour... So not very good...
Any help would be very appreciated.
/*
* NIXI CLOCK - DHCP & NTP
*
* NIXI CODE REMOVED
*
*/
// Includes
#include <Time.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <SPI.h>
/****************************************************************************************************/
// *** Ethernet MAC Address
static byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x9B, 0xC1 };
// *** NTP Server Address
static IPAddress timeServer(10, 100, 150, 1);
// *** Time Zone
const int timeZone = -7; // Pacific Daylight Time (USA)
// *** DST Offset Toggle
const int timeDST = 1; // 1 = DST ON / 0 = DST OFF
// *** Misc Settings
const int NTP_PACKET_SIZE = 48; // NTP Packet Size
byte packetBuffer[NTP_PACKET_SIZE]; // NTP Buffer
time_t prevDisplay = 0; // NTP Status
const int ntpsync = 7200; // NTP Sync Interval
/****************************************************************************************************/
// DHCP Buffer
char ipbuf[21];
// DHCP Array
union IPAddressConverter {
uint32_t ipInteger;
uint8_t ipArray[4];
};
unsigned long dlastnow; // DHCP Renew
const int dhcplease = 7200; // DHCP Lease Time - 2 Hours
EthernetClient client; // Create Ethernet Instance
EthernetUDP Udp; // Create UDP Instance
/****************************************************************************************************/
void setup()
{
// ** Boot Serial Interface
Serial.begin(9600); // Create Serial Interface Monitor
// ** Boot Ethernet Interface
Ethernet.begin(mac); // Assign MAC to NIC
// ** Wait for Settings to Apply
delay(500);
Udp.begin(8888); // Set UDP Port to 8888
setSyncProvider(getNtpTime); // Fetch NTP Data
setSyncInterval(ntpsync); // NTP Sync Timer
setTime(hour() + timeDST,minute(),second(),day(),month(),year()); // Store NTP Data
}
void loop()
{
if (timeStatus() != timeNotSet) // Initialize on Time Change
{
if (now() != prevDisplay)
{
prevDisplay = now();
//NixiTubeDisplay();
SerialClockDisplay();
}
if (hour() == 16 && minute() == 20) // 4:20 PM GREEN!
{
// Output Effect Here
} else if (hour() == 16 && minute() == 21) {
// Output Effect Here
}
if (hour() == 03 && minute() == 00) // 3:00 AM RED!
{
// Output Effect Here
} else if (hour() == 04 && minute() == 00) {
// Output Effect Here
}
if (now() - dlastnow > dhcplease) dhcprenew(); // Initialize DHCP
}
}
// Print Data to Serial Interface
void SerialClockDisplay(){
Serial.print("Time / Date: ");
printDigits(hour());
Serial.print(":");
printDigits(minute());
Serial.print(":");
printDigits(second());
Serial.print(" ");
printDigits(day());
Serial.print(".");
printDigits(month());
Serial.print(".");
Serial.println(year());
Serial.println(ipbuf);
}
// Print Data to Nixi Tube Display
void NixiTubeDisplay(){
// Nixi Code Here
}
void printDigits(int digits)
{
if(digits < 10) Serial.print('0');
Serial.print(digits);
}
time_t getNtpTime()
{
while (Udp.parsePacket() > 0) ;
sendNTPpacket(timeServer);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500)
{
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE)
{
Udp.read(packetBuffer, NTP_PACKET_SIZE);
unsigned long secsSince1900;
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 + timeZone * SECS_PER_HOUR;
}
}
return 0;
}
// NTP Request Transmission
void sendNTPpacket(IPAddress &address)
{
memset(packetBuffer, 0, NTP_PACKET_SIZE); // NTP Packet Buffer
// NTP Packet Payload
packetBuffer[0] = 0b11100011;
packetBuffer[1] = 0;
packetBuffer[2] = 6;
packetBuffer[3] = 0xEC;
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
// Send Payload to NTP Server Port 123
Udp.beginPacket(address, 123);
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
void dhcprenew()
{
Ethernet.maintain();
IPAddressConverter ipAddress;
ipAddress.ipInteger = Ethernet.localIP();
sprintf(ipbuf, "IP: %d.%d.%d.%d", ipAddress.ipArray[0], ipAddress.ipArray[1], ipAddress.ipArray[2], ipAddress.ipArray[3]);
dlastnow=now();
}