I have downloaded the latest time Library. Unfortunately it used the "bytewise UDP" functions to retrieve the time. So I modified a few sketches to simplify things.
This sketch will use the "standard" udp library to read a time server, update the DS1307 RTC, and the display the clock -- it uses the Time Library.
This was tested on a Mega2560, the Ethernet shield and with all the "standard" version 22 libraries.
In a later post in this series I will show the updated libraries - hopefully whoever maintains the librairies will consider adding the code to access the Square Wave Oscillator on the chip..
The next sketch will be a simple routine to simply sync the software clock in the Time Library with the RTC clock -- without updating to NTP server.
You should be able to copy this code into a sketch and update your Clock.
DON"T FORGET! If you want use the SQW output on the clock you somehow need to supply a voltage (and current) to the pin. I just tied a 3.9K resistor to 5Volts, then to the pin. You could also use a digital pin on the Arduino and set the Pull Up resistor to high (supplying a voltage and current) then of course you set the pin to read... The real use of the oscillator is of course to tie it to an External Interrupt and use it to time reading from a analog pin, for example, and then use the clock to stamp the output when you send data to a PC or store the Data on the SD card (on the Ethernet shield).
Hope this all makes sense and is useful to people...
/*
* Modified by D Robinson Feb 09, 2011
*******************************
* Time_NTP_UDP_DS1307.pde
* Example showing time sync to NTP time source for V022 of Compiler and Time Libray
*
* This sketch uses the Ethenet library with the current UDP library. **** Note ****
*
* Also, the time is retrieved from the NTP Packet, then used to update the DS1307 RTC
* The DS1307 RTC is then used to synchronize the clock in the Time Library.
* Now that the clock is synched, you can just use a simpler RTC/Time Lib synch to retrieve
* the time e.g. now() in your sketches.
* Considering the drift on the DS1307 RTC you should probably synch every day or two.
* If you add the new libraries you can also access the square wave generator through set2(time, sqvalue)
* See the setup function below for an example...
* You only need to run this occasionally to sync to network time standards.
***************************************************************************
*/
#include <Time.h>
#include <SPI.h>
#include <Ethernet.h>
#include <Udp.h>
#include <WProgram.h>;
#include <Wire.h>
#include <DS1307RTC.h>
/*
*
* You may need to modify the Udp library to allow enough space in the buffers for the NTP packets.
* Open up UdpBytewse.h and set the following buffers to 64 bytes:
* #define UDP_TX_PACKET_MAX_SIZE 64
* #define UDP_RX_PACKET_MAX_SIZE 64
*/
byte mac[] = {
0x90, 0xA2, 0xDA, 0x00, 0x27, 0x7A };
byte ip[] = {
192,168,0,80 };
unsigned int localPort = 8888; // local port to listen for UDP packets
byte SNTP_server_IP[] = { 192, 43, 244, 18}; // time.nist.gov
// byte SNTP_server_IP[] = { 132,246,11,227}; // time.chu.nrc.ca weird time 64ms RT time
//byte SNTP_server_IP[] = { 130,149,17,21}; // ntps1-0.cs.tu-berlin.de
//byte SNTP_server_IP[] = { 192,53,103,108}; // ptbtime1.ptb.de
time_t prevDisplay = 0; // when the digital clock was displayed
time_t yy;
uint8_t zz;
unsigned long xx;
long HoursOffset = -5;
long SecondsInMinute = 60;
long MinutesInHour =60;
long timeZoneOffset; // set this to the offset in seconds to your local time;
long correctionfactor = 1;
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
void setup()
{
Serial.begin(9600);
Ethernet.begin(mac,ip);
Udp.begin(localPort);
Serial.println("waiting for sync -- tzo");
timeZoneOffset = (HoursOffset * MinutesInHour * SecondsInMinute);
// no delays in this group...
yy= getNtpTime();
zz= 0x91;
/* RTC.set2 adds the Square Wave Generator setup
0x90 sets to one blip a second
0x91 sets the oscilator to a 4,096 KHz Square Wave
0x92 sets the oscillator to a 8,192 KHz Sq. Wv.
0x93 sets the oscillator to a 32768 KHz Sq. Wv. (XTAL Frequncy)
*/
// RTC.set2(yy,zz); // use this function with the modified libraries to set RTC
RTC.set(yy); //use this function with unmodified libraries to Set RTC
/* Now that we have set RTC with the NTP signal -- we can sych the software timer
using setSyncProvider.
This will allow us to turn off the Arduino, and the load other programs
which only need to sync to the RTC -- and don't have to update to an
NTP server -- unless you want the most accurate time.
If you believe the clock is drifiting -- run this program as appropriate
or include the functionality on you program.
*/
setSyncProvider(RTC.get);
while(timeStatus()== timeNotSet); // wait until the time is set by the sync provider
}
void loop()
{
if( now() != prevDisplay) //update the display only if the time has changed
{
prevDisplay = now();
digitalClockDisplay();
}
}
void digitalClockDisplay(){
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
Serial.println();
}
void printDigits(int digits){
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
/*-------- NTP code ----------*/
unsigned long getNtpTime()
{
sendNTPpacket(SNTP_server_IP);
delay(1000);// this delay is required...
if ( Udp.available() ) {
Udp.readPacket(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;
// now convert NTP time into everyday time:
const unsigned long seventy_years = 2208988800UL; // subtract seventy years:
unsigned long epoch = secsSince1900 - seventy_years;
epoch = epoch + timeZoneOffset + correctionfactor; //do this here or we get apparent over/under flow
return epoch;
}
return 0; // return 0 if unable to get the time
}
unsigned long sendNTPpacket(byte *address)
{
// set all bytes in the buffer to 0
Serial.println("Sending packet to server...");
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.sendPacket( packetBuffer,NTP_PACKET_SIZE, address, 123); //NTP requests are to port 123
}