
Accurate Time:
Ham radio digital modes require accurate computer time. On the other
hand, appliance computer hardware
clocks do not typically
maintain accurate time in
the absence of periodic correction. Clock adjustments are
generally
accomplished automatically via scheduled updates from an Internet time
service. But
what if Internet connectivity is not readily available, or
is prohibitively
expensive, such as when operating from a remote area, perhaps a
wilderness park? In such a situation it would be convenient to
synch the computer clock to an accurate time source that
does not depend on Internet connectivity.
When I first
thought of using Arduino as a time server I found this forum post, describing an Arduino
Mega2560 implementation of exactly the thing I wanted. The post
suggested that the sketch could be modified for a 328 board by
substituting software serial in place of the Mega’s UART-1. It occurred
to me that an adaptation for a wireless-enabled board might also be
feasible. However, I ordered an Ethernet shield, in case the wireless
idea didn’t pan out. The shield that I purchased is based on the older
W5100 chip (photo
left).
While waiting for the Ethernet shield I played with a wireless board,
but encountered some sort of problem, which I’ve
forgotten. It would likely not be difficult to adapt this concept to a
wireless board. However, instead once the Ethernet shield arrived I
went about
adapting the original published sketch for the Uno. This first
adaptation requires
only the Uno, Ethernet shield, and GPS. The sketch is here.
During development I used a free NTP Server checker from Galleon
Systems for testing (right). Later, when testing the revision to be
described below I used
another free NTP Server Tool, also from Galleon
Systems. The latter displays milliseconds in the transmit timestamp
(needed to verify the fractional second calculation that would become
part of the second revision).



// NTP since 1900/01/01
static unsigned long int numberOfSecondsSince1900Epoch(uint16_t y, uint8_t m, uint8_t d, uint8_t h, uint8_t mm, uint8_t s) {
uint16_t days = d;
for (uint8_t i = 1; i < m; ++i)
days += pgm_read_byte(daysInMonth + i - 1);
for (int x = 1970; x < y; ++x) {
if ((x % 400) == 0 {
++days;
} else if ((x % 100) == 0) {
days = days;
} else if ((x % 4) == 0) {
++days;
}
}
if (m > 2) {
if ((x % 400) == 0 {
++days;
} else if ((x % 100) == 0) {
days = days;
} else if ((x % 4) == 0) {
++days;
}
}
days += 365 * y + (y + 3) / 4 - 1;
return days*24L*3600L + h*3600L + mm*60L + s + seventyYears;
}
///////////////////////////////////////////////////////////////