GPS-based NTP Server
Arduino Uno based NTP Server

Arduino in router client list     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.

WIZnet W5100 chip    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).

    The GPS used in the above-cited Arduino Mega project was a u-blox NEO 6M. I planned to use the NEO M8N, which in my previous experience acquires a fix more rapidly and under less-favorable conditions than the 6M.

NTP Server Checker    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).

    At first, the timestamp returned by the Arduino server was off by a day. This turned out to be a bug in the leap year calculation. Once that error was corrected, the server returned the correct date/time from the GPS. I tested many times with the Galleon Systems free checker before working up the nerve to update a real computer from the Arduino NTP server. For this first computer test I decided to start with the Raspberry Pi. If testing somehow screwed it up, the Pi would be easy to restore. The first step was to edit the file /etc/ntp.conf, commenting-out the four default Debian NTP servers and substituting the IP address of the Arduino Ethernet shield (a private local area network address). Step 2 was to reboot, which automatically obtains time from the server. I discovered this fact by monitoring hits to the Arduino server via its serial com channel. Raspberry Pi doesn’t have a hardware clock. If Pi didn’t connect to NTP on startup it would be necessary to set the clock interactively! The third step in the Pi clock update test was redundant, i.e. to force an update through sudo service ntp restart. Each hit was recorded on the server side, by enabling a conditional debug code segment. All this is documented in the sketch itself.

    I was hesitant to try updating the Windows time clock, as I imagined a screw-up in Windows time might have been harder to undo. Eventually though I worked up the nerve to try it. Nothing happened—Windows time did not update. The answer was first found in this article, and then later in others as well. It is necessary to stop the time service and then add the Arduino NTP server as a trusted server (illustration below). As the title bar indicates, PowerShell was run as Administrator. (It would be the same for the Windows command shell.) After making this change, the LAN NTP server shows up in the list of trusted time servers, and can be used to update Windows time. This procedure is illustrated in the demo video link at the bottom of this write-up. (In case it matters, the Windows version for this test was Windows 7.)

Configure NTP server in Windows

    It bothered me that the server only responded on the second. As designed, the original sketch checked for an incoming UDP packet after each one second tick of the GPS clock. Packets had to wait between ticks. This delay was observable at the client end. In other words, updating from was typically faster than updating from the local area network server. NIST was nearly instantaneous, while the latter averaged around a half second delay.  I thought the polling was backwards, that UDP should be checked all the time. Trouble was that even if a packet were detected immediately, it would still be necessary to wait for the GPS on-the-second time mark. The solution that occurred to me was unnecessarily complex, and in a way flawed, but I will describe it anyway.

GPS-based Arduino NTP server with Real-Time Clock
Real-time clock version

    In another article I have described the DS3231 oscillator chip. This IC is based on a temperature compensated 32 KHz crystal oscillator. The idea was that the DS3231 could be synched to the GPS periodically, say once an hour, and would provide time on demand whenever a UDP packet was received. Instead of reporting zeros for the fractional part of second, the NTP server would report the time to milliseconds accuracy. Well, the first problem to manifest after I’d thrown a DS3231 into the mix was that the DS3231
real-time clock does not report milliseconds! The Arduino itself does have a milliseconds counter that records elapsed time from startup. It would be possible to use that counter, setting an application-level milliseconds counter to zero on each GPS update. But then why do we need a real-time clock?

Wiring Diagram (Fritzing)
Wiring Diagram contributed by Tomasz Patelski

    Having already wired in the oscillator and incorporated code for getting its time, etc. I decided to go ahead and implement the scheme described. In this sketch, NTP is polled continuously and fractional time is returned immediately, using the GPS-synced RTC for seconds, and the Arduino milliseconds counter for fractional seconds. The Galleon Systems tool was used to test fractional seconds, as illustrated below and in the demo video.

NTP server (left) and test client (right)

    The significance of the highlighted timestamp in the above illustration is that I was unsure whether the decimal part was being correctly encoded as an unsigned int32 until the same value was exhibited in the client side display.

    Notwithstanding the rather awkward conglomerate of time sources I fully expected this NTP server to update Windows, just as the first simpler one had done—It did not. Troubleshooting revealed that the problem was fractional seconds. If the fraction was anything except zero, Windows would timeout, displaying the message, “An error occurred while Windows was synchronizing with <IP address>.
The server receives the Windows packet and replies, but Windows seems not to understand the reply format. To be sure that nothing else about the revision mattered, I created a conditional #define FOR_WINDOWS, which if true would zero-out milliseconds and if false would return the full decimal value for time. When true, Windows would accept the reply packet and process it normally. However, that bothered me as well, because the server was now reporting an incorrect time. Whereas with the first sketch the server was replying on the second, when 0 was the true value for milliseconds (or very nearly so).

    I went back to RFC 5905 to see if maybe something important was missing or invalid in the reply packet, but the fields that follow the 32-bit fractional seconds field are designated as optional, and are not populated in the 48-bit Arduino-generated packet that Windows accepts. I also read Microsoft documentation about Windows time service and tools. It was interesting to learn that the guaranteed time is not very accurate. That is because different computers have more-or-less accurate hardware clocks, while setting and synchronizing them is basically up to the user. In any event, reading about Windows time did not lead to an explanation for the fractional seconds anomaly. If I find the answer from further investigation, then of course I will post it here.

    Demo: Arduino GPS NTP Server

Projects Home


Project descriptions on this page are intended for entertainment only. The author makes no claim as to the accuracy or completeness of the information presented. In no event will the author be liable for any damages, lost effort, inability to carry out a similar project, or to reproduce a claimed result, or anything else relating to a decision to use the information on this page.