Adding a FreeBSD NTP server based on an GPS 18 LVC device
Introduction
I have been interested in precise timekeeping for a long time,
and have run the excellent NTP
software on my PCs for several years. Recently, I have worked with Martin Burnicki
of Meinberg on improving the performance
of NTP in the Windows environment, however I remained envious of the reported
precision of GPS systems with microsecond accuracies. When the low-cost
Garmin GSP 18 LVC became available, quite a few people reported using this
device with UNIX systems, and this triggered me into purchasing a GPS 18 LVC to
see what I could do with it. Initial tests with just the serial 4800 baud
NMEA output using Windows were disappointing. Whilst the device worked,
the accuracy and jitter were no better than could be achieved with a broadband
Internet connection and servers from the NTP
pool. Realising that I had a spare old 133MHz PC, and hearing that
UNIX could run on such a system, I decided to rise to the challenge. This
note is the result!
Hardware
PC Hardware
1995 PC with 133MHz Pentium processor, 48MB memory, and 10GB
ATA disk. Two serial ports (although one would be enough in this application).
Top of the line kit in 1995!
GPS Hardware
 |
I used the Garmin GPS 18
LVC, which has a cable connection you can wire
into your own system. It needs 5V power at 60mA.
It should be
mounted where it has a clear view of at least 50% of the sky - ideally the whole
sky. I tried mine on a window ledge but the more recent windows we had
fitted in 2005 do not seem to be transparent to the microwave signals.
The
GPS is now on a small bracket just outside the window, with the thin aluminium
bracket being shaped so that it is clamped by the window. The unit
is secured to the bracket by a single screw in the base. The cable
comes through the window and is clamped by the rubber sealing strips -
they don't seem to do too much harm. Whilst this worked initially,
on 2006 Sep 22 I moved the GPS so that it now has a somewhat fuller view of the sky.
PDF - GPS 18
data sheet -
GPS
18
technical specifications
|
How do I know how many GPS satellites are visible?
An oddity
During the initial tests of the GPS 18 LVC, after I had made
up the RS-232 connector, I discovered that the Garmin supplied software would
not connect to the device, even though the correct "sentences" could
be seen via a terminal emulator. I didn't understand why this was the
case, and so I wrote a small program to send the command string to switch the
device to 19200 baud (or 4800 baud). Once I'd done that, the Garmin
program worked OK. Perhaps this is a common problem, as Tony Hoyle
reported:
Tony: "I got hold of one of these, and after much mucking around, it seems to work. (it's defaulted to startup in binary
mode and no linux drivers can understand that, so you have to switch it into NMEA using the Windows config program, then switch binary mode off
using a command from the spec sheet... the second step doesn't seem to be documented elsewhere)."
Me: "My GPS 18 LVC powered up in the correct mode (I think), but the Windows
control program wouldn't talk to it. HyperTerminal saw the sentences correctly, though!
I wrote a small piece of software to switch it to 19200 baud, and back to 4800 baud, and it's OK now."
Tony: "Mine was the other way around - the Windows control program could see it
but all hyperterminal (or minicom) could see was binary junk. Had to switch it manually using $PGRMC1... you first get the windows program to
enable text mode (forcing 'enable NMEA mode' does this) then quit it and start
minicom, and issue a $PGRMC1 with 1 as the second digit (disable binary phase)."
Initial setup
For a long while after I first started the GPS it didn't
report a sensible position. I suspect it was taking a long time to read
the almanac, and then to find the correct satellites. It did eventually
sort itself out, but only after about 30 minutes of exposure to a good fraction
of clear sky.
The unit is quite a bit less sensitive than my other GPS,
which has an add-on active antenna.
An attempted tweak
On 2006 June 06, I attempted to set the GPS 18 LVC into 2D
mode, which means that it assumes a fixed height and would only need three
satellites for a complete fix (as my sensor can only see half the sky).
This is done via the $PGRMC statement, setting the first value to "2",
and the second to the sensor height in metres. I will see if this makes
any difference (I'm also unsure if the command "stuck"). I don't
think this made any difference, as I believe it only affects the initial
acquisition.
Moving the GPS 18 LVC
The opportunity recent arose to put the unit on the slope of
the roof, which would mean that it only saw satellites above 25º elevation, but
over a 360º degree arc of the sky. This does appear better than the
previous 180º arc of about 5º elevation. No longer do I see spikes of
invalid GPS data (due to too few satellites), and now the winter is approaching
the central heating transients are, perhaps, the worst errors!
Interconnection
The Garmin has a 5V power requirement, which I met from a 7805
and a 12V regulated supply already to hand. You could, instead, take the
5V from a USB port (see: Terje
Mathisens' post)
The Garmin TX, RX and ground data connections go to DB-9 RX,
TX and ground connections.
The Garmin yellow PPS (pulse per second) line is connected to the DB-9 DCD (pin
1). Mine is also connected to a LED via a 3.3K resistor so that there is a
visual indication of the PPS signal. I still see over 4V on of the PPS
line. Update: the LED was a little dark, so I changed the resistor to 1.5K
and replaced the LED with a special low-current (2mA) one from Maplins.
Now easily seen in daylight - I await being dazzled at night!
DB-9 Name LVC connection
pin
1 Data Carrier Detect PPS thin yellow
2 Receive Data TXD thin white
3 Transmit Data RCV thin green
4 Data Terminal Ready
5 Signal Ground GND thin black
Power Connections
+5V thick red
0V thick black

Software
Software installation
It seems to be acknowledged that FreeBSD is currently the best
operating system for accurate time keeping, so that's what installed having no
other particular preference. It is also possible to use the same hardware
with Linux 2.6, and Philip M White has described
how to do this.
The FreeBSD formal documentation is here.
You can download the BSD 5.4 ISO disk images from here.
This is the version which I heard that other people use, and it has worked fine
for me. I can't comment from experience if newer versions are any better.
You can use the IsoBuster
program to extract the floppy disk images from the ISO.
You use the fdimage
program to make floppy disks to boot from if, like me, your CD-ROM doesn't
boot. There is a boot floppy, and two Kernel floppies. There's a
fourth fixit floppy, but I didn't appear to need that. When
choosing the type of distribution, be sure to install the
source so that you can re-compile the Kernel.
It seems that I could have saved myself a lot of time by using
Smart Boot Manager. Geoff Rhodes writes:
"I notice that you were unable to boot from CD-ROM, so I thought you might be
interested in Smart Boot Manager. I got this several years ago (then as part of Ranish
Partition Manager, I think) and it allows me to boot from
CD- ROM on my 486, either by installing it onto the HDD, or more usually having SBM
on a floppy. I got really fed up with the time it took to use the floppy install method for W2K etc and this solves it quite neatly!
"It looks like SBM is now here:
http://btmgr.sourceforge.net/about.html or http://btmgr.webframe.org/"
FreeBSD Unix commands
- to shutdown: shutdown -p now (power
down); shutdown -r now (reboot)
- to restart ntpd: /etc/rc.d/ntpd restart
- to logout: logout
- to choose the time-zone, and whether the BIOS clock works
in UTC or local time, see the tzsetup
command.
System software configuration
- To allow remote login via Telnet, need to uncomment the
telnet entry in inet.conf. Telnet is only recommended for a small
local system with no direct connection to the Internet.
- To allow root to login via telnet, need to add the word
"secure" to the ttyp0 entry in /etc/ttys. Be careful if you
enable this option!
- A handy, free terminal emulator with VT100 etc.
capabilities will make editing files easier if you have to work remotely
from the FreeBSD box, and I've used Tera
Term. Of course, you need to edit the files allowing remote access
locally first!
System software customisation
Need to add one line to the Kernel configuration:
options PPS_SYNC
and recompile
the Kernel. On my 133MHz/48MB system this can take several hours.
Note the configuration suggestions below before you recompile the kernel.
Harlan Stenn comments:
Assuming an x86 box, you need to create a file - e.g. /usr/src/sys/i386/conf/PPS
- and put the following in it:
#
# PPS -- Generic kernel configuration file for FreeBSD/i386 PPS
#
include GENERIC
ident PPS-GENERIC
options PPS_SYNC
and then add the following line to /etc/make.conf:
KERNCONF= PPS GENERIC
(Assuming you want to "cd /usr/src" and "make buildkernel
installkernel") to build
both kernels and only install the PPS kernel). (Later: I do this if I want both the GENERIC
and PPS kernels built, but the first one in the list is the one that gets installed).)
Kevin Oberman comments:
"The idea Harlan Stenn is putting forth is to create a very short kernel
config file named PPS containing only those three lines. That way, if you upgrade, any changes in GENERIC will automagically be
folded in. I would change one thing. I would change the name of the config file to match the
IDENT. It makes it easier to keep track of things."
Harlan Stenn continues: I also add the lines:
link cuaa1 refclock-0
link cuaa1 pps0
to the end of /etc/devfs.conf, and *sometimes* it looks like those links are
not created soon enough in the boot sequence, but it's sporadic and I have
not had time to chase it down yet.
Per Hedeland comments:
Well, using PPS_SYNC shouldn't be *required* to use the PPS signal on
FreeBSD - what it does is make the kernel discipline the local clock directly from the PPS signal, but FreeBSD also supports the PPSAPI, to
let ntpd collect the timestamps from the PPS signal. It should be possible to use this via the ATOM driver.
I haven't personally verified any of this though (hence the "should"s) - and I guess PPS_SYNC may give
better results, but it could be interesting to try both variants.
Dag-Erling Smørgrav noted on the NTP-Timekeepers list:
The device name changed from cuaa to cuad in later
versions.
There is some interesting information about configuring a single-board
computer to do this job here:
NTP configuration
NTP is configured by the file /etc/ntp.conf. My simple version
contains:
# ntp.conf
#
#
driftfile /etc/ntp.drift
#
# The servers for sanity
#
server 0.uk.pool.ntp.org iburst
server 1.uk.pool.ntp.org iburst
server 2.uk.pool.ntp.org iburst
server ntp2.mcc.ac.uk iburst
#
# The GPS receiver on COM1 at 4800 baud
#
# mode 1 = use $GPRMC statements
# time1 = trimming offset
# flag3 1 = enable Kernel PPS discipline
#
server 127.127.20.1 mode 1 prefer
fudge 127.127.20.1 time1 0.000 flag3 1 refid PPS
#
What does the fudge line do?
The fudge command allows me to adjust certain parameters of the
specified server. In this case, I alter:
- the reference ID to the string "PPS"
- flag 3 to the value 1, enabling the kernel PPS discipline
- the time offset to 0.000 seconds
The latter adjustment does nothing, but had my pulses been the
opposite polarity to the ones I actually have, the NTP software might have
locked to the trailing edge of the pulse 200ms after the leading edge, and
rather than change that in hardware I could have set time1 to +0.200 (or
whatever) to get the correct time.
Useful NTP commands
- To show the upstream systems: ntpq -p
- To show the state of the kernel: ntpdc -c kern
Showing before and after PPS_SYNC enabled in the Kernel
|
|
E:\>ntpdc -c kern pixie
pll offset: -3.75634 s
pll frequency: 45.503 ppm
maximum error: 0.485818 s
estimated error: 0.002825 s
status: 2001
pll time constant: 7
precision: 1e-006 s
frequency tolerance: 496 ppm
|
|
pixie# ntpdc -c kern
pll offset: -6.7e-08 s
pll frequency: 45.479 ppm
maximum error: 0.232597 s
estimated error: 0.001668 s
status: 2107 pll ppsfreq ppstime ppssignal nano
pll time constant: 6
precision: 1e-09 s
frequency tolerance: 496 ppm
pps frequency: 45.479 ppm
pps stability: 0.130 ppm
pps jitter: 1.183e-06 s
calibration interval: 128 s
calibration cycles: 23
jitter exceeded: 13
stability exceeded: 0
calibration errors: 1
|
How well does it work?

(click this image for summary history plots)
Here is a graph showing the offset from UTC reported by the
PC, with 20µs added so that the offset is positive. (An ideal timekeeper
would be a straight line at 20µs). As the offset value reported by NTPQ
is only accurate to 1µs, increasing the plotted time resolution would not
provide more information. Please remember that this is a lowly 133MHz
processor system! How I make these plots.
Performance history. All
NTP plots.
So far, with NTP, my experience in terms of the accuracy
achieved appears to be something like this. There are two levels of
accuracy, one with Windows or FreeBSD of the order of 10 - 20ms, and one with
the FreeBSD kernel PPS modification providing microsecond accuracies.
(There is also a nano modification to the UNIX kernels, but I don't quite know
what that does as yet).
- Multiple Internet sources to Windows NT/XP clients,
excursions of the order of 10 - 20ms caused mainly by diurnal temperature
variations. The time constant on the NTP correction loop grows quite
long to minimise NTP network traffic and load on NTP servers, and the lookup
interval typically grows to 1024s. This long time constant allows some
drift.
- Serial GPS source to Windows NT/XP. At the default
setting, 4800 baud, each bit occupies 0.2ms, and the uncertainty with which
the GPS sends out the data, and the operating system can report the time the
data was received, result in a somewhat higher short term jitter, and no
better daily drift than with multiple Internet sources. It's possible
that the jitter would be less with a UNIX system, but I've not tested that.
- PPS source to FreeBSD, with PPS_SYNC support in the
kernel. Even on a lowly 133MHz PC, with a GPS antenna seeing less than
half of the sky, 10µs jitter is achieved. It's too early to report
long-term drift - judge for yourself by clicking the graph above.
System configuration updates require to run NTP
- To start ntpd every time, add to /etc/rc.conf
ntpd_enable="YES"
- To point the pseudo GPS1 device to the
actual serial port, add to /etc/rc.local
ln -s /dev/cuaa0 /dev/gps1
Startup sequence after reboot - a set of ntpq -p reports
pixie# ntpq -p
remote refid
st t when poll reach delay offset jitter
==============================================================================
194.153.168.75
.STEP. 16 u
989 64 0 0.000
0.000 4000.00
213.205.157.156
.STEP. 16 u
418 64 0 0.000
0.000 4000.00
ns0.exa-network 130.88.202.49 3 u
9 64 1 2874.71 1421.71
0.015
kryten.alphazed
.STEP. 16 u
832 64 0 0.000
0.000 4000.00
utserv.mcc.ac.u 194.81.227.227 2 u 10
64 1 2868.76 1417.38 0.015
GPS_NMEA(1)
.PPS. 0
l 15 64 0
0.000 0.000 4000.00
pixie# ntpq -p
remote refid
st t when poll reach delay offset jitter
==============================================================================
194.153.168.75
.STEP. 16 u
1010 64 0
0.000 0.000 4000.00
213.205.157.156
.STEP. 16 u
439 64 0 0.000
0.000 4000.00
ns0.exa-network 130.88.202.49 3 u
30 64 1 2874.71 1421.71
0.015
kryten.alphazed
.STEP. 16 u
852 64 0 0.000
0.000 4000.00
utserv.mcc.ac.u 194.81.227.227 2 u 30
64 1 2868.76 1417.38 0.015
GPS_NMEA(1)
.PPS. 0
l 35 64 0
0.000 0.000 4000.00
pixie# ntpq -p
remote refid
st t when poll reach delay offset jitter
==============================================================================
*194.153.168.75 195.66.241.10 2 u
20 64 1 20.722
-4.448 2.257
+213.205.157.156 130.149.17.21 2 u 19
64 1 27.903 -5.345 8.284
ns0.exa-network 130.88.202.49 3 u
35 64 3 32.045 0.346
1421.36
+kryten.alphazed 129.69.1.153 2 u
19 64 1 22.097
-4.337 2.564
utserv.mcc.ac.u 194.81.227.227 2 u 34
64 3 27.331 -3.080 1420.46
GPS_NMEA(1)
.PPS. 0
l 37 64 1
0.000 -7.169 0.015
pixie# ntpq -p
remote refid
st t when poll reach delay offset jitter
==============================================================================
*194.153.168.75 195.66.241.10 2 u
33 64 3 20.722
-4.448 3.898
+213.205.157.156 130.149.17.21 2 u 35
64 3 27.903 -5.345 8.538
ns0.exa-network 130.88.202.49 3 u 51
128 7 32.045 0.346
7.119
+kryten.alphazed 129.69.1.153 2 u
32 64 3 22.097
-4.337 3.483
utserv.mcc.ac.u 194.81.227.227 2 u 49
128 7 27.331 -3.080 8.172
GPS_NMEA(1)
.PPS. 0
l 47 64 3
0.000 -0.624 6.545
pixie# ntpq -p
remote refid
st t when poll reach delay offset jitter
==============================================================================
*194.153.168.75 195.66.241.10 2 u
16 64 7 21.446
-0.818 3.593
+213.205.157.156 130.149.17.21 2 u 15
64 7 27.903 -5.345 9.062
ns0.exa-network 130.88.202.49 3 u 97
128 7 32.045 0.346
7.119
+kryten.alphazed 129.69.1.153 2 u
13 64 7 22.097
-4.337 5.230
utserv.mcc.ac.u 194.81.227.227 2 u 96
128 7 27.331 -3.080 8.172
GPS_NMEA(1)
.PPS. 0
l 28 64 7
0.000 -0.058 5.044
pixie# ntpq -p
remote refid
st t when poll reach delay offset jitter
==============================================================================
+194.153.168.75 195.66.241.10 2 u
8 64 17 21.446
-0.818 4.854
+213.205.157.156 130.149.17.21 2 u
6 64 17 28.349
0.523 5.450
ns0.exa-network 130.88.202.49 3 u 27
256 17 32.045 0.346 7.903
+kryten.alphazed 129.69.1.153 2 u
7 64 17 21.891
2.511 4.282
+utserv.mcc.ac.u 194.81.227.227 2 u 24
256 17 27.331 -3.080 8.057
*GPS_NMEA(1)
.PPS. 0
l 20 64 17
0.000 -0.007 4.150
pixie# ntpq -p
remote refid
st t when poll reach delay offset jitter
==============================================================================
+194.153.168.75 195.66.241.3 2 u
16 64 37 21.446
-0.818 4.893
+213.205.157.156 130.149.17.21 2 u 14
64 37 26.764 1.313 4.579
ns0.exa-network 130.88.202.49 3 u 101
256 17 32.045 0.346 7.903
+kryten.alphazed 129.69.1.153 2 u
81 64 36 21.891
2.511 4.282
-utserv.mcc.ac.u 194.81.227.227 2 u 98
256 17 27.331 -3.080 8.057
*GPS_NMEA(1)
.PPS. 0
l 31 64 37
0.000 -0.005 3.595
pixie# ntpq -p
remote refid
st t when poll reach delay offset jitter
==============================================================================
+194.153.168.75 195.66.241.3 2 u
61 64 77 21.446
-0.818 6.598
+213.205.157.156 130.149.17.21 2 u 57
64 77 26.764 1.313 4.050
ns0.exa-network 130.88.202.49 3 u 210
256 17 32.045 0.346 7.903
+kryten.alphazed 129.69.1.153 2 u
60 64 75 21.792
2.579 3.447
-utserv.mcc.ac.u 194.81.227.227 2 u 207 256
17 27.331 -3.080 8.057
*GPS_NMEA(1)
.PPS. 0
l 11 64 177
0.000 0.003 2.939
Acknowledgements
I received much help from the kind folk in the comp.protocols.time.ntp newsgroup including
Terje
Mathisen, John Pettitt and Harlan Stenn. Thanks, guys!
|