And because I'm a beginner, it will not be perfect.
Update_RTC_from_NTP.ino (20.9 KB)
K5CZ:
And because I'm a beginner, it will not be perfect.
i have code i use for my RTC. here is what you do.
you have a variable:
byte ip[4];
where you store the IP address of an online NTP server
you then call the function:
GET_NTP_TIME
where the time zone for my area is -6 since i am in central America.
This function stores the NTP time in the variables SETHOUR, SETMINUTE, and SETSECONDS. you can add code so it calculates the months, days and years as well.
when you have the new time, you call
setDateDs1307
to set the date within the clock. you then can call getDateDs1307
to get the time from the clock. it works perfectly for me, but i am using a DS1307
#include <EthernetUdp.h>
#define localPort 8888 // local port to listen for UDP packets. needed for the NTP servers for time updating
#define 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
EthernetUDP Udp;// A UDP instance to let us send and receive packets over UDP
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers
void setDateDs1307(byte set_second, // 0-59
byte set_minute, // 0-59
byte set_hour, // 1-23
byte set_dayOfWeek, // 1-7
byte set_dayOfMonth, // 1-28/29/30/31
byte set_month, // 1-12
byte set_year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(set_second)); // 0 to bit 7 starts the clock
Wire.write(decToBcd(set_minute));
Wire.write(decToBcd(set_hour));
Wire.write(decToBcd(set_dayOfWeek));
Wire.write(decToBcd(set_dayOfMonth));
Wire.write(decToBcd(set_month));
Wire.write(decToBcd(set_year));
Wire.write(0x10); // sends 0x10 (hex) 00010000 (binary) to control register - turns on square wave
Wire.endTransmission();
}
// Gets the date and time from the ds1307
void getDateDs1307(byte *get_second,
byte *get_minute,
byte *get_hour,
byte *get_dayOfWeek,
byte *get_dayOfMonth,
byte *get_month,
byte *get_year)
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
// A few of these need masks because certain bits are control bits
*get_second = bcdToDec(Wire.read() & 0x7f);
*get_minute = bcdToDec(Wire.read());
*get_hour = bcdToDec(Wire.read() & 0x3f); // Need to change this if 12 hour am/pm
*get_dayOfWeek = bcdToDec(Wire.read());
*get_dayOfMonth = bcdToDec(Wire.read());
*get_month = bcdToDec(Wire.read());
*get_year = bcdToDec(Wire.read());
}
void GET_NTP_TIME(int timezone)
{
sendNTPpacket(); // send an NTP packet to a time server
//wdt_reset();
// wait to see if a reply is available
delay(1000);
wdt_reset();
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 timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, esxtract 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;
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const unsigned long seventyYears = 2208988800UL;
// subtract seventy years:
unsigned long epoch = secsSince1900 - seventyYears;
// print the hour, minute and second:
SETHOUR = int(((epoch+(timezone*3600)) % 86400)/3600);
SETMINUTE = int((epoch % 3600)/60);
SETSECONDS = int(epoch %60);
}
}
// send an NTP request to the time server at the given address
unsigned long sendNTPpacket(void)
{
// 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(ip, 123); //NTP requests are to port 123
Udp.write(packetBuffer,NTP_PACKET_SIZE);
Udp.endPacket();
}
Here is my latest version - I use this program also for testing TFT and LCD displays (and also as a LCD clock), so this makes program a little bit complicated
NTP_RTC_TFT18_LCD_v020.ino (34.1 KB)
wallaceb:
where the time zone for my area is -6 since i am in central America.
And yet you forget your fairly close Venezuelan neighbours and fail to include non-integer timezones (UTC -4:30).
I often encounter this problem, as I live in Central Australia (UTC+9:30).
K5CZ's code has the same deficiency, his is probably easier to fix with:
after line 130 add a new line with:
#define TIME_ZONE_HALF 0 /*, 1 or -1*/
then modify line 559 to:
result = secsSince1900 - 2208988800UL + TIME_ZONE_INT * SECS_PER_HOUR + TIME_ZONE_HALF * SECS_PER_HOUR / 2;
I was never deeply interested in the timezone standard, but I noticed that the time shift is sometime counted in minutes instead of hours - so now I know why.
K5CZ:
Here is my latest version - I use this program also for testing TFT and LCD displays (and also as a LCD clock), so this makes program a little bit complicated
Sorry, but I´m missing something, please can you help me,
Severity Code Description Project File Line Suppression State
Error (active) identifier "tmElements_t" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 145
Error (active) identifier "month" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 268
Error (active) identifier "makeTime" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 399
Error (active) identifier "now" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 467
Error (active) identifier "day" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 471
Error (active) identifier "month" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 472
Error (active) identifier "monthShortStr" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 474
Error (active) identifier "year" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 479
Error (active) identifier "hour" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 480
Error (active) identifier "minute" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 481
Error (active) identifier "second" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 482
Error (active) identifier "weekday" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 488
Error (active) identifier "dayStr" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 491
Error (active) identifier "dayShortStr" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 494
Error (active) identifier "setSyncProvider" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 673
Error (active) identifier "setTime" is undefined rtcntp z:\Documents\Arduino\MeteorologyWeatherStation\rtcntp\rtcntp.ino 676
K5CZ:
Here is my latest version - I use this program also for testing TFT and LCD displays (and also as a LCD clock), so this makes program a little bit complicated
Hi ! I have a question. If for any reason, you lose connectivity after having acquired ip from the dhcp, how do you prevent the update by ntp from hanging the main loop? Thanks
Hi
Some useful information here as well: Here's how to get a more accurate RTC clock set from an NTP time server