Go Down

Topic: Arduino Ethernet Client - NTP Time Sync (Read 5501 times) previous topic - next topic

nathanas

Hey arduiners!

I am trying to sync my program with internet time, but unfortunately the library "Time.h" has some bugs.
The NTP ime example doesn;t work as well as every other code on the net cause of arduino version compatibility issues.

Can someon post here a working simple sketch of getting time from a server?

Thanks in advance,
   Nick Athanasoulas

PaulS

Quote
the library "Time.h" has some bugs.

No, it has some incompatibility issues with 1.0+, all of which are solvable.


nathanas

Dear PaulS,
   I managed to read time but I need a better sketch so I can have date displayed too.
I also need DST (auto GMT change) everytime the GMT changes in my country.
I am willing to make the code with some help.
But is there a server that sends the local time in my country? But I want to read it as NTp...
Do you know anything to point at me, so maybe I work things out?

Nick Athanasoulas

Code: [Select]

/*
Udp NTP Client with DNS

I updated the example code to use DNS resolution from the Arduino 1.0 IDE

Basically tries to use the load-balanced NTP servers which are
  "magically" returned from DNS queries on pool.ntp.org
If DNS fails, fall back to the hardcoded IP address
  for time.nist.gov

bearpaw7 (github), 01DEC2011

This code is also in the public domain.
*/

/*

Udp NTP Client

Get the time from a Network Time Protocol (NTP) time server
Demonstrates use of UDP sendPacket and ReceivePacket
For more on NTP time servers and the messages needed to communicate with them,
see http://en.wikipedia.org/wiki/Network_Time_Protocol

created 4 Sep 2010
by Michael Margolis
modified 17 Sep 2010
by Tom Igoe

This code is in the public domain.

*/

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include "Dns.h"

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {  0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD};
unsigned int localPort = 80; // local port to listen for UDP packets
IPAddress timeServer(193,92,150,3); // time.nist.gov NTP server (fallback)
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
const char* host = "nsath.forthnet.gr"; // Use random servers through DNS

// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
DNSClient Dns;
IPAddress rem_add;

void setup()
{
Serial.begin(9600);

// start Ethernet and UDP
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
while(true);
}
Udp.begin(localPort);
Dns.begin(Ethernet.dnsServerIP() );
}

void loop()
{
if(Dns.getHostByName(host, rem_add) == 1 ){
Serial.println("DNS resolve...");
Serial.print(host);
Serial.print("  = ");
Serial.println(rem_add);
sendNTPpacket(rem_add);
}else{
Serial.print("DNS fail...");
Serial.print("time.nist.gov = ");
Serial.println(timeServer); // fallback
sendNTPpacket(timeServer); // send an NTP packet to a time server
}
delay(1000); // wait to see if a reply is available
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;
Serial.print("Seconds since Jan 1 1900 = " );
Serial.println(secsSince1900);

// now convert NTP time into everyday time:
Serial.print("Unix time = ");
// 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 Unix time:
Serial.println(epoch);

// print the hour, minute and second:
Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT)
Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
Serial.print(':');
if ( ((epoch % 3600) / 60) < 10 ) {
// In the first 10 minutes of each hour, we'll want a leading '0'
Serial.print('0');
}
Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
Serial.print(':');
if ( (epoch % 60) < 10 ) {
// In the first 10 seconds of each minute, we'll want a leading '0'
Serial.print('0');
}
Serial.println(epoch %60); // print the second
}
// wait ten seconds before asking for the time again
delay(10000);
Serial.println(" ");
}

// send an NTP request to the time server at the given address
unsigned long 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();
}


PaulS

Quote
But is there a server that sends the local time in my country?

No. All time servers report time in Greenwich mean time. You need to adjust for your local time.

That code does something. You want it to do something. How are those two somethings different?

nathanas

Its a lot of trouble to make the seconds into date according to the different days each year and some times the leap years.
I also have to customize the sketch to be able to auto-select the GMT time zone according to the date.
I maybe capture date data from another server/site and compare those ones.


PaulS

Quote
Its a lot of trouble to make the seconds into date according to the different days each year and some times the leap years.

I don't see why. There is, in the Time library, a function to set the time based on the number of seconds sine Jan. 1, 1970. That would be the value in epoch in the code you posted. Once you have done that, you simply call year(), month(), day(), hour(), minute(), and second().

There is a function to adjust the time. Set the time based on Greenwich mean time. Then, call adjustTime() with the offset for your local time, and let it deal with the fact that you don't live in Greenland.

nathanas

I'll look into it. If I make it through I'll post the code. I've laready added code for GMT +/- time zones 2&3 because I am from Greece.
It's easy to adapt to any zone.

shiu748

Can someone please advise how to make the date and time library to work on Arduino 1.0.1 as it gives some bug when trying to compile.

PaulS

Quote
Can someone please advise how to make the date and time library to work on Arduino 1.0.1 as it gives some bug when trying to compile.

No problem. See that search bar? Use it to search for the other 50 bazillion times the question has been asked and answered.

Or search for the specific error message. I'm certain that you didn't get the Italian version of the compiler that just waves its hands and says "I can't do that".

Hi, I was just working on the same thing for a few days. What I wanted is almost the same thing. Local Timezone, Date & Time and so on. Heres my code (I also included the Timezone-Library to handle the offset to NTP-UTC Time). Since I am using the 'older' Ethernet Shield with the W5100 Chip (wich has a bug), I have inserted subroutines to activate ethernet or the SD-Card. If an SD-Card is inserted at startup (when Ethernet.begin(mac) Function is called) it will fail with a DHCP-Failure, if SD-Card SS-Pin is not set to HIGH.

See my code in the attachement  8)

K5CZ

Arduino Uno R3, Arduino Mega 2560 R3, Ethermega (R3), and some Ethernet Shields (R3), Chronodots, TMP36 sensors, DS18B20 sensors, LCDs/TFTs, RS232C to learn and play...

Thanks K5CZ, as you can see I am still a beginner and this was my first working code for getting NTP-Time. I have made a few DS1307 programs, but since I don't have the correct crystal oscillator with 12.5pf my RTC is extremly inaccurate. It is a 32'768 Mhz, but not the correct pf. In order to keep my RTC accurate I attached a DCF-77 Receiver but I don't receive a signal everywhere in the house. Thats why I was making a testprogram to figure out how I can compare the RTC-Time with NTP. Thanks a lot for the link. I will verify my code again. I am always willing to learn new and better ways of coding AVR's.

Regards dragonfly

K5CZ

I'm still a beginner too :-) I posted my latest version of the program in the topic above.
Arduino Uno R3, Arduino Mega 2560 R3, Ethermega (R3), and some Ethernet Shields (R3), Chronodots, TMP36 sensors, DS18B20 sensors, LCDs/TFTs, RS232C to learn and play...

Go Up