How to build a portable STRATUM 1 NTP Server

20141102_155715The Raspberry Pi B 512 MB connected to my “old” Aspire One with a crossover cable

If you need precise and accurate time for your projects while sampling a digital record or doing something that need precise timestamps you can use a  Raspberry Pi with the Adafruit Breakout GPS module to build a stratum 1 NTP server for your projects. What is a Stratum 1?

The basic definition of a stratum-1 time server is that it be directly linked (not over a network path) to a reliable source of UTC time such as GPS, WWV, or CDMA transmissions.

Let’s see how to build one!

Materials that you will need

  1.  Raspberry Pi Model B Revision 2 512MB
  2.  8Gb MicroSD/SD Card
  3.  A modified version of Debian Wheezy
  4.  Adafruit Breakout GPS module

Thanks to David Taylor   ( http://www.satsignal.eu/davids.html )  on  how to build up the kernel-modded  image ,i then discovered later  you can even  download a perfect Debian Wheezy image  from this site without modify the kernel yourself :  it has everything you need (NTP server configurations and PPS Kernel – RX GPIO signals for NMEA and  NTPD,  GPSD ec..) ( http://ntpi.openchaos.org/downloads/ntpi-pps-2013-04-12.zip ) .

OK i’ll go quick to the point. First take your image with your kernel settled for NTP and PPS and flash it into a micro SD card. In this way you will accomplish almost 80% of the job done. Once you have your image set , you can try it on the Raspberry (the HDMI  is available, SSH too on port 22) enter with username pi and password raspberry. If works just fine , you login and everything seems operational then it’s time to connect the GPS module to the boards’s GPIOs pins . You will have to connect it in this way

20141104_205015Connect the Board 5v (GPIO 02) to the VIN pin of the GPS.The Raspberry works at 3.3v not 5v so be careful to never  put 5v current in the headers pins! You can of course power the Adafruit GPS module with both since the PPS output is on 3.3v, also it’s even better to use the 5v to reduce the load on the 3.3 V regulator on the Raspberry Pi board. Then connect the GROUND , the RX GPIO pin to the GPS TX and PPS pins like in the image. (you don’t need to use the TX pin on the board  since we are just reading the GPS NMEA output from the UART).You can solder everything if you need or use  cables with tape for testing So now we should be ready to set up our server.

The server configuration file is located in /etc/ntp.conf file. I’ll copy here my personal configuration file to explain lines:

# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help

driftfile /var/lib/ntp/ntp.drift


# Enable this if you want statistics to be logged.
statsdir /var/lib/ntpstats/

statistics loopstats peerstats clockstats
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable
filegen clockstats file clockstats type day enable


# Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for
# details. The web page <http://support.ntp.org/bin/view/Support/AccessRestrictions>
# might also be helpful.
#
# Note that "restrict" applies to both servers and clients, so a configuration
# that might be intended to block requests from certain clients could also end
# up blocking replies from your own upstream servers.

# By default, exchange time with everybody, but don't allow configuration.
restrict -4 default kod notrap nomodify nopeer
restrict -6 default kod notrap nomodify nopeer

# Local users may interrogate the ntp server more closely.
restrict 127.0.0.1
restrict ::1

# pps-gpio on /dev/pps0
server 127.127.22.0 minpoll 4 maxpoll 4
fudge 127.127.22.0 flag3 1 refid PPS # enable kernel PLL/FLL clock discipline

# gpsd shared memory clock
server 127.127.28.0 minpoll 4 maxpoll 4 iburst true prefer # PPS requires at least one preferred peer
fudge 127.127.28.0 time1 +0.51 refid GPS # coarse processing delay offset

server ntp1.ptb.de prefer # another stable preferred peer

server 0.pool.ntp.org iburst
server 1.pool.ntp.org iburst
server 2.pool.ntp.org iburst
server 3.pool.ntp.org iburst

Let’s start to analyze its most important parts:

driftfile /var/lib/ntp/ntp.drift

Each hour NTP will save some data into the ntp.drift file. If you open/cat the file you will notice a number: for example -2.979 . These are PPM or Part per million and is the current difference drift of the quartz crystal of your motherboard. The basic formula to calculate it in ms is -2.979*86.4 ( 1PPM = 1 PPM = 1 part per million = 1 microsecond per second = 3.6ms per hour = 86.4ms per day ) that is -257.385 ms slow (if minus , if plus is faster) compared to the sys_peer source.

statistics loopstats peerstats clockstats
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable
filegen clockstats file clockstats type day enable

These file are NTP statistics overview. We’ll see later how to manage these data and put them on a graph to monitor our server.

restrict -4 default kod notrap nomodify nopeer
restrict -6 default kod notrap nomodify nopeer

Security restrictions:  -4  apply to ipv4 and -6 to ipv6 kodSend a kiss-o’-death (KoD) packet if the limited flag is present and a packet violates the rate limits established by the discard command. KoD packets are themselves rate limited for each source address separately. If the kod flag is used in a restriction which does not have the limited flag, no KoD responses will result. NOTRAP Decline to provide mode 6 control message trap service to matching hosts. The trap service is a subsystem of the ntpdc control message protocol which is intended for use by remote event logging programs. NOMODIFY  Deny ntpq and ntpdc queries which attempt to modify the state of the server (i.e., run time reconfiguration). Queries which return information are permitted. NOPEER Deny packets that might mobilize an association unless authenticated. This includes broadcast, symmetric-active and manycast server packets when a configured association does not exist. Note that this flag does not apply to packets that do not attempt to mobilize an association. 

# pps-gpio on /dev/pps0
server 127.127.22.0 minpoll 4 maxpoll 4
fudge 127.127.22.0 flag3 1 refid PPS # enable kernel PLL/FLL clock discipline

This is the kernel-gpio signal received as pps0 on  GPIO – PPS pin (see header picture on top). Minpoll – Maxpoll at 4 creates 16 seconds ntpd poll reading , flag3 1 : Controls the kernel PPS discipline: 0 for disable (default), 1 for enable.

# gpsd shared memory clock
server 127.127.28.0 minpoll 4 maxpoll 4 iburst true prefer # PPS requires at least one preferred peer
fudge 127.127.28.0 time1 +0.51 refid GPS # coarse processing delay offset

The address used by gpsd to read NMEA data from the GPS Breakout to the GPIO Header of the Raspberry. Since UART signal has widely known offset problem, we just make the ntpd algorithm to belive in this data since we have a 1PPS kernel reference signal for the precise microsecond offset. (iburst, true and prefer) . The other thing we shall consider is to calculate the offset of the UART. You can use a time1 +0.000 at the beginning then when the offset become more stable try to make a ntpq -np command and see how much offset do you have. (mine was about -510.00 milliseconds  but it’s still unstable) Check out also your UART – GPIO rx speed. Raspberrt usually has 9600 boud default . check with : ( should be ttyAMA0 )

root@ntpi:/dev# stty -F ttyAMA0
speed 9600 baud; line = 0;
intr = <undef>; quit = <undef>; erase = <undef>; kill = <undef>; eof = <undef>; start = <undef>; stop = <undef>; susp = <undef>; rprnt = <undef>; werase = <undef>; lnext = <undef>; flush = <undef>;
min = 1; time = 0;
-brkint -icrnl -imaxbel
-opost -onlcr
-isig -icanon -iexten -echo -echoe -echok -echoctl -echoke

If everything is working you should see this output :

ntpq1

As you can see we have a PPS with an offset of 0.002 microseconds that is used for reference and we are using NMEA GPS data input from UART. (you can check the NMEA output too with #cat /dev/ttyAMA0 ). For a complete description of ntpq query please check the official documentation at http://doc.ntp.org/4.1.0/ntpq.htm

First results as Stratum 1 in LAN and WAN environments.

 Ntp saves two different kind of files in a directory of your choice (in this case /var/lib/ntpstats) and automatically zip them day by day. Be careful on the Raspberry to just activate this option when you need to monitor them. You can use MRTG software or NTP Plotter. I’m using this last one you can find a copy here http://www.satsignal.eu/software/NTPplotter.zip

This are the results of few hours in a normal day just after the first activation :

Raspberry Pi B 512 Mb , Kernel PPS Sync with Adafruit GPS Breakout Module – Offset Time Graph in μs

offsetNormally I’ve got a stratum 1 offset of 1 microseconds with a jitter of 2 microseconds as server.I’m actually testing my server in my LAN and in WAN environment connected to another server at the SID monitoring station, located to the other side of the city of Turin. I’m using a normal ADSL Gb Ethernet  at home for the server, which is of course bad for a WAN env.. ( you can find more information on it here : http://sidmonitor.rf.gd/systems/index.html the server in Sidmonitor is using FreeBSD 9.2 and use NTP as client.  )

LAN client Test with another server in my home synchronized to the Raspberry :

lanThe server is running Ubuntu with 3.13.0-39 Kernel is an old IBM xseries 335. .DELT. is the Raspberry NTP ID , as you can see NTP easily chooses that source because is the fastest stratum 1 available. In my internal LAN I’ve got a delay  of 3.347 milliseconds and an offset of -0.453 milliseconds which is just bad but not too much for my busy LAN and my little Cisco  Router (the server is in WI-FI).

Then I’ve tried to sync the FreeBSD one to the other side if the city and this is the result of ntpq -np query  :

wan

The public IP is covered for security reason. As you can see DELT Raspberry NTP server is working and operational, compared to the NIST and ACTS is of course much more fast since those atomic clocks are in the US, not here in Europe and NTP algorithm has just selected  .DELT. as preferred time server for the stratum 1 offset/jitter offer . Much more fun since now  synchronize all Sidmonitor  data upload and mirroring with a Raspberry!

Performances

offsetgps

As Stratum 1 with a 60$ receiver and a Raspberry, under best conditions of GPS satellites reception, I’ve got results around 500-450 nanoseconds,( 0.045 micro-secs in the picture above) which i think it’s a good result for a cheap NTP server. Will be possible to go below 40 nanoseconds?We’ll see!

10 thoughts on “How to build a portable STRATUM 1 NTP Server

  1. Buon pomeriggio, mi associo ai complimenti eventuali per questo blog sul tempo UTC e sul protocollo NTP.
    A casa ho due piccoli “lamponi” model 2 equipaggiati con scheda add-on gps proprio per realizzare due server di strato 1 ntp.

    Marco.

    Like

      1. That would be excellent! I have comeback to this project several times since the beginning of the year, and each time I run into different issues than before. The gaps in my progress do not help me proceed any faster.

        I started with an RPi3/Jessie which presented its unique issues with wifi and Bluetooth. Then I switched to an RPi2, but I was unable to boot Wheezy. I’ve more recently discovered that the newest Jessie presents issues with the serial bus.

        I should get an RPiB+ today which should work with Wheezy. For the GPS, I’m using the Adafruit Ultimate GPS Hat. Hopefully, using hardware and software that others have used successfully will help me with most of my issues.

        Thanks again.

        Tom

        Like

      2. That would be excellent! I have comeback to this project several times since the beginning of the year, and each time I run into different issues than before. The gaps in my progress do not help me proceed any faster.

        I started with an RPi3/Jessie which presented its unique issues with wifi and Bluetooth. Then I switched to an RPi2, but I was unable to boot Wheezy. I’ve more recently discovered that the newest Jessie presents issues with the serial bus.

        I should get an RPiB+ today which should work with Wheezy. For the GPS, I’m using the Adafruit Ultimate GPS Hat. Hopefully, using hardware and software that others have used successfully will help me with most of my issues.

        Thanks again.

        Tom

        Like

  2. Hi Tom,

    Thanks for taking the time to provide this awesome guide. I have everything up and running and can successfully read the PPS from the GPS module. Unfortunately when I run the ntpq -np command the PPS IP has an ‘X’ beside it opposed to an ‘o’. Any suggestions on how to fix this?

    Thanks again.

    Like

    1. Fabrizio is the one you should be thanking; I’m just a visitor myself.

      I’m not exactly sure why you are experiencing this issue, but I will try to help.

      Read here:
      http://support.ntp.org/bin/view/Support/ConfiguringAtomRefclocks

      Also, this helped me tremendously throughout this process:

      http://www.satsignal.eu/ntp/Raspberry-Pi-quickstart.html

      Everything below comes from the above link.

      Specifically, confirm the following:

      1. Run this “lsmod | grep pps”

      Output should be similar to:

      pps_gpio 2529 1
      pps_core 7943 2 pps_gpio

      2. Verify PPS is running (though I think you have done this):

      Run this “dmesg | grep pps”

      Output should be similar to:

      [ 0.000000] Kernel command line: dma.dmachans=0x7f35 bcm2708_fb.fbwidth=656 bcm2708_fb.fbheight=416 bcm2708.boardrev=0x10 bcm2708.serial=0x1a25ea38 smsc95xx.macaddr=B8:27:EB:25:EA:38 bcm2708_fb.fbswap=1 bcm2708.disk_led_gpio=47 bcm2708.disk_led_active_low=0 sdhci-bcm2708.emmc_clock_freq=250000000 vc_mem.mem_base=0x1ec00000 vc_mem.mem_size=0x20000000 dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
      [ 0.029423] bcm2708: GPIO 18 setup as pps-gpio device
      [ 10.159940] pps_core: LinuxPPS API ver. 1 registered
      [ 10.161448] pps_core: Software ver. 5.3.6 – Copyright 2005-2007 Rodolfo Giometti
      [ 10.172015] pps pps0: new PPS source pps-gpio.18
      [ 10.173557] pps pps0: Registered IRQ 188 as PPS source

      Note that with the Raspberry Pi 2, or with more recent versions of Raspbian, you may see:

      [ 10.172015] pps pps0: new PPS source pps-gpio.-1

      Then run this “sudo ppstest /dev/pps0”

      Output should be similar to:

      trying PPS source “/dev/pps0”
      found PPS source “/dev/pps0”
      ok, found 1 source(s), now start fetching data…
      source 0 – assert 1418933982.9980424, sequence: 970 – clear 0.0000000, sequence: 0
      source 0 – assert 1418933983.9980454, sequence: 971 – clear 0.0000000, sequence: 0

      (Press CTRL+C to quit).

      If all of this checks out, refer to the section entitled “Enabling PPS/ATOM support in NTPD” at the satsignal website link provided above.

      Like

Leave a comment