Quantcast
Channel: Johannes Weber – Weberblog.net
Viewing all articles
Browse latest Browse all 311

NTP Server via DCF77 on a Raspberry Pi

$
0
0

In this tutorial I will show how to set up a Raspberry Pi with a DCF77 receiver as an NTP server. Since the external radio clock via DCF77 is a stratum 0 source, the NTP server itself is stratum 1. I am showing how to connect the DCF77 module and I am listing all relevant commands as a step by step guide to install the NTP things. With this tutorial you will be able to operate your own stratum 1 NTP server. Nice DIY project. ;) However, keep in mind that you should only use it on a private playground and not on an enterprise network that should consist of high reliable NTP servers rather than DIY Raspberry Pis. Anyway, let’s go:

This article one of many blogposts within this NTP series. Please have a look!

At the time of writing (Nov 2018) I am using a Raspberry Pi 1 B (yes, the old one), kernel 4.14.71+ and Raspbian GNU/Linux 9 (stretch). I installed a few relevant packages and gave it a static IPv6 address. Legacy IP (IPv4) is not used at all, only IPv6.

1) Connecting the DCF77 Module

At first you need a DCF77 module in order to receive the radio clock from Germany. I used the “Conrad” module. It needs a pull up resistor with 3-10 kOhm between ports 2 and 4 (VCC and DCF-). Have a look at the PDFs from the Conrad store that show the port assignment, as well as this two german pages that give several hints. Long story short: use three cables:

  1. DCF77 module port 1 (GND): Pi pin 9, GND
  2. DCF77 module port 2 (VCC): Pi pin 1, +3.3 V
  3. DCF77 module port 3 (DCF+): not used
  4. DCF77 module port 4 (DCF-): Pi pin 10, RXD0 (UART)

I first soldered the cables directly to the Pi, while I later added a 3,5 mm jack to the housing of the Pi with a 2 meter cable on the DCF77 module:

2) Installing NTP w/ DCF77 Support

The first step is to install NTP with the support of DCF77. This is not the case if you’re simply doing a

sudo apt-get install ntp
. Anyway, please install the NTP server with this command first in order to have the startup scripts in place, etc. After that you need to build NTP from source (note the “–enable-RAWDCF” option) which involves the following steps:
sudo nano /etc/apt/sources.list
# uncomment the line with "deb-src"
deb-src http://raspbian.raspberrypi.org/raspbian/ stretch main contrib non-free rpi

sudo apt-get update
sudo apt-get -y build-dep ntp

# download the latest ntp: http://ntp.org/downloads.html
# in this example it was 4.2.8p12
wget http://www.eecis.udel.edu/~ntp/ntp_spool/ntp4/ntp-4.2/ntp-4.2.8p12.tar.gz
cd ntp-4.2.8p12/
# note: the following step takes some time:
./configure --enable-RAWDCF --prefix=/usr
# note: the following "make" takes even longer, especially on an old Pi 1 B
make
sudo service ntp stop
sudo make install
# to disable updating ntp via apt-get, echo the following:
echo "ntp hold" | sudo dpkg --set-selections
sudo service ntp start

(Fun fact: Since I am running my NTP server via IPv6-only meanwhile the NTP download page is IPv4-only, I had to download and copy the ntp package from another machine to the Raspberry Pi. Sigh. Yes, I know, DNS64/NAT64 would solve the problem.)

You have just installed the latest version of NTP, while “holding” the ntp package within dpkg to not overriding/downgrading it with future “apt-get update”s. You can verify this with the following: (Note the “h” in the very first column which indicates that the ntp package is on hold.)

pi@ntp1-dcf77:~ $ dpkg -l | grep ntp
hi  ntp                              1:4.2.8p10+dfsg-3+deb9u2     armhf        Network Time Protocol daemon and utility programs

Similarly you can verify the running ntp version with:

pi@ntp1-dcf77:~ $ ntpq --version
ntpq 4.2.8p12@1.3728-o Thu Nov  8 11:51:22 UTC 2018 (1)

 

3) Leveraging the Serial Port

At first you must disable the serial port of the Pi while keeping the port hardware enabled. Open

sudo raspi-config
, navigate to “5 Interface Options” -> “P6 Serial” and:
  1. Would you like a login shell to be accessible over serial? –> No
  2. Would you like the serial port hardware to be enabled? –> Yes

followed by a reboot when exiting raspi-config.

A very basic test with “screen” should indicate some output, though completely useless:

pi@ntp1-dcf77:~ $ sudo screen /dev/ttyAMA0 9600
����
Ctrl+a \ y

Add the user “ntp” (which runs the ntp daemon) to the “tty” group in order to have access to the tty console. Verify it with the second command shown below:

pi@ntp1-dcf77:~ $ sudo adduser ntp tty
Adding user `ntp' to group `tty' ...
Adding user ntp to group tty
Done.

pi@ntp1-dcf77:~ $ cat /etc/group | grep tty
tty:x:5:ntp

In order to have a symbolic link to /dev/refclock-0 (which is needed by NTP later), add the following three lines to the init script from NTP, while commenting out the latter three lines

sudo nano /etc/init.d/ntp
 :
if [ ! -L /dev/refclock-0 ]; then
        ln -s /dev/ttyAMA0 /dev/refclock-0
fi

#if [ -e /var/lib/ntp/ntp.conf.dhcp ]; then
#       NTPD_OPTS="$NTPD_OPTS -c /var/lib/ntp/ntp.conf.dhcp"
#fi

Reload the systemctl and restart the NTP process:

sudo systemctl daemon-reload
sudo service ntp restart

Verify that the symbolic link is present:

pi@ntp1-dcf77:/etc/init.d $ ls /dev/ref*
/dev/refclock-0

Now you need to use driver number 8 from the NTP software in “mode 5” for the Conrad DCF77 module. That is: Open the ntp configuration file: 

sudo nano /etc/ntp.conf
and add your “server” aka DCF77 module in the following way:
server 127.127.8.0 mode 5 prefer

I have commented out the default “pool 0.debian.pool.ntp.org iburst” lines but entered a few IPv6 enabled servers as well, though without the “prefer” option:

#http://support.ntp.org/bin/view/Servers/PublicTimeServer000388
server ntp.probe-networks.de
#http://support.ntp.org/bin/view/Servers/PublicTimeServer001352
server time.hueske-edv.de
#http://support.ntp.org/bin/view/Servers/PublicTimeServer000840
server ntp2.301-moved.de
#http://support.ntp.org/bin/view/Servers/PublicTimeServer001363
server ntp.fanlin.de

Finally, restart the NTP daemon:

sudo service ntp restart
.

Now, in theory, the DCF77 receiver should work, but only if you have a good radio signal and quality and correct angle of the antenna, which was not the case in my scenario at the first time. Use “ntpq -p” to print a list of NTP servers that are in use. As you can see in this example, the “GENERIC(0) .DCFa.” server (first line) was never reached so far:

pi@ntp1-dcf77:~ $ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 GENERIC(0)      .DCFa.           0 l    -   64    0    0.000    0.000   0.000
 ptbtime2.ptb.de .PTB.            1 u   57   64  377    9.207    4.270   4.483
*ns2.probe-netwo 192.53.103.108   2 u    2   64  377    2.553    3.727   4.777
-2a01:4f8:201:41 131.188.3.221    2 u   57   64  377   16.104   -2.650   2.955
+2a02:a00:1009:6 40.179.132.91    2 u    9   64  377    6.683   -0.115   2.329
+2001:4ba0:ffa4: 51.254.155.97    2 u   11   64  377    5.818   -4.302   3.673

Have a look at the syslog messages. If they list something like this, you don’t have a good signal quality, while the receiver at least works in general: ;)

pi@ntp1-dcf77:~ $ tail /var/log/syslog | grep ntpd
Nov  8 16:05:59 ntp1-dcf77 ntpd[500]: parse: convert_rawdcf: INCOMPLETE DATA - time code only has 3 bits
Nov  8 16:06:04 ntp1-dcf77 ntpd[500]: parse: convert_rawdcf: INCOMPLETE DATA - time code only has 6 bits
Nov  8 16:06:08 ntp1-dcf77 ntpd[500]: parse: convert_rawdcf: INCOMPLETE DATA - time code only has 5 bits
Nov  8 16:07:00 ntp1-dcf77 ntpd[500]: parse: convert_rawdcf: INCOMPLETE DATA - time code only has 12 bits
Nov  8 16:07:04 ntp1-dcf77 ntpd[500]: parse: convert_rawdcf: INCOMPLETE DATA - time code only has 3 bits
Nov  8 16:07:07 ntp1-dcf77 ntpd[500]: parse: convert_rawdcf: INCOMPLETE DATA - time code only has 4 bits
Nov  8 16:07:18 ntp1-dcf77 ntpd[500]: parse: convert_rawdcf: INCOMPLETE DATA - time code only has 12 bits
Nov  8 16:07:24 ntp1-dcf77 ntpd[500]: parse: convert_rawdcf: INCOMPLETE DATA - time code only has 7 bits
Nov  8 16:07:55 ntp1-dcf77 ntpd[500]: parse: convert_rawdcf: INCOMPLETE DATA - time code only has 32 bits
Nov  8 16:08:00 ntp1-dcf77 ntpd[500]: parse: convert_rawdcf: INCOMPLETE DATA - time code only has 6 bits

Note that the DCF77 receiver must point orthogonal with its longer side to Mainflingen, Germany, which is south-east of Frankfurt. (Fun fact: Since I am living just a few kilometers in the north of Frankfurt, my actual direction of the receiver must not show to Frankfurt directly, but more precisely to Mainflingen. However, for almost everyone else the receiver must simply “look” into Frankfurt.) Furthermore, you must omit any interfering/disturbing sources such as switching power supplies or the like in the room where your receiver resides. At its best, the receiver is placed outside a building (waterproof, lightning protection!), which is not that easy at all. In addition I came across some weird observations, since my signal quality was way better as I turned the antenna just a few degrees in one direction. TL;DR: If you’re lacking signal quality, try a few different positions of your antenna. Be creative. ;)

If you have a good signal strength and quality, the ntpq -p output should look like this, in which the “GENERIC(0) .DCFa.” source has a reach of 377 while the * symbol indicates, that it is used as the system peer:

pi@ntp1-dcf77:~ $ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*GENERIC(0)      .DCFa.           0 l   35   64  377    0.000   -0.019   0.346
+2003:de:2016:33 .PPS.            1 s   34   64  376    6.445    0.496   5.006
 ptbtime2.ptb.de .PTB.            1 u   23   64  377   16.437    1.195   3.226
+ns2.probe-netwo 124.216.164.14   2 u    6   64  377    9.554    1.594   2.322
-2a01:4f8:201:41 192.53.103.108   2 u   30   64  377   23.610   -3.326   4.884
-2a02:a00:1009:6 192.53.103.108   2 u    9   64  377   13.279    1.295   5.938
-2001:4ba0:ffa4: 130.149.17.21    2 u   47   64  377   17.065    1.689   7.871

 

4) Adjusting the Fudgetime

You need to adjust the fudgetime of the DCF77 receiver which is the compensation of the offset from the radio clock to the “real” time. That is: You need to compare the time received from your DCF77 module to some other working NTP sources. The offset should be minimal after that.

Without any “fudgetime” options in your ntp.conf file, the “RAW DCF77 CODE (Conrad DCF77 receiver module)”, as it is called by NTP, has a built-in fudgetime1 of 292.000 ms. You can see this with “ntpq -c cv”, since it “displays a list of clock variables for those associations supporting a reference clock”:

pi@ntp1-dcf77:~ $ ntpq -c cv
associd=0 status=0020 2 events, clk_unspec,
device="RAW DCF77 CODE (Conrad DCF77 receiver module)",
timecode="-####----####-#---M-S1-----4p-2---2p-2---2--41---1---81---P",
poll=33, noreply=0, badformat=2, baddata=0, fudgetime1=292.000,
stratum=0, refid=DCFa, flags=0,
refclock_time="dfa1a0fa.00000000  Thu, Nov 22 2018 21:41:14.000",
refclock_status="TIME CODE; (LEAP INDICATION; CALLBIT)",
refclock_format="RAW DCF77 Timecode",
refclock_states="*NOMINAL: 00:29:02 (88.06%); BAD FORMAT: 00:03:56 (11.93%); running time: 00:32:58"

After some time running NTP you will see either this, in which all other NTP servers have a comparable but huge offset (in this situation about 590 ms, while the DCFa receiver is not used due to the “x” in the first column):

pi@ntp1-dcf77:~ $ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
xGENERIC(0)      .DCFa.           0 l   52   64   37    0.000   -0.792   2.046
-2003:de:2016:33 .PPS.            1 s   48   64   36    7.255  591.525   3.128
 ptbtime2.ptb.de .PTB.            1 u   41   64   37   15.637  590.647   1.982
+ns2.probe-netwo 124.216.164.14   2 u   43   64   37    9.333  591.296   1.737
+2a01:4f8:201:41 131.188.3.221    2 u   45   64   37   24.371  586.926   3.137
*2a02:a00:1009:6 205.46.178.169   2 u   44   64   37   12.479  592.152   7.343
 2001:4ba0:ffa4: .STEP.          16 u    -   64    0    0.000    0.000   0.000

or this, in which all other NTP servers have a low offset, while the DCFa receiver has one with a much higher negative value (while still not used):

pi@ntp1-dcf77:~ $ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
xGENERIC(0)      .DCFa.           0 l    5   64   77    0.000  -593.24   1.561
-2003:de:2016:33 .PPS.            1 s   60   64   73    7.738   -0.359   0.778
 ptbtime2.ptb.de .PTB.            1 u   64   64   77   16.143    0.222   1.091
+ns2.probe-netwo 124.216.164.14   2 u   61   64   77    9.862    0.471   0.862
+2a01:4f8:201:41 192.53.103.108   2 u   61   64   77   23.879   -4.579   0.615
*2a02:a00:1009:6 205.46.178.169   2 u   63   64   77   12.489   -0.316   1.477
 2001:4ba0:ffa4: .STEP.          16 u    -  256    0    0.000    0.000   0.000

–> Now you need to adjust the fudgetime1 to compensate this difference. In my case, since the pre-configured fudgetime was 292 ms while my offset of the DCF77 receiver was about -592 ms (hence needed an even higher compensation), I had to add a fudgetime1 of 292 + 592 = 884. Open the configuration file again:

sudo nano /etc/ntp.conf
and add the following below your “server 127.127.8.0 […]” line:
fudge 127.127.8.0 time1 0.884

Followed by a restart of NTP:

sudo service ntp restart
.

A couple of minutes later you should have very small offsets among all NTP servers, the external ones as well as your DCFa receiver:

pi@ntp1-dcf77:~ $ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*GENERIC(0)      .DCFa.           0 l   63   64  377    0.000   -0.451   0.857
-2003:de:2016:33 .PPS.            1 s   47   64  175    7.557    0.539   2.272
 ptbtime2.ptb.de .PTB.            1 u   49   64  377   15.739    1.224   0.850
+ns2.probe-netwo 124.216.164.14   2 u   42   64  377    8.975    1.550   0.757
-2a01:4f8:201:41 192.53.103.108   2 u   52   64  377   24.224   -4.928   2.822
+2a02:a00:1009:6 40.33.41.76      2 u   49   64  377   12.530   -0.400   2.792
 2001:4ba0:ffa4: .INIT.          16 u    -  128    0    0.000    0.000   0.000

Very good! You’re almost done.

5) Reducing Ethernet Latency

One hint from David Taylor about reducing the Ethernet latency on a Pi: Adding an option to the single line in

sudo nano /boot/cmdline.txt
that states:
smsc95xx.turbo_mode=N
(reboot needed). This reduces the “delay” as shown in the “ntpq -p” output. I used two Raspberry Pis connected via a single switch, first time without the option, second with the option set by both. The delay between those NTP servers decreased from about 0.916 ms to 0.632 ms. Nice.
# BEFORE
pi@ntp1-dcf77:~ $ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 GENERIC(0)      .DCFa.           0 l    -   64    0    0.000    0.000   0.000
*2003:de:2016:33 .PPS.            1 s   28   64  377    0.916    1.125   0.759
 ptbtime2.ptb.de .PTB.            1 u   26   64  377    9.782    1.081   0.419

# AFTER
pi@ntp1-dcf77:~ $ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 GENERIC(0)      .DCFa.           0 l    -   64    0    0.000    0.000   0.000
*2003:de:2016:33 .PPS.            1 s   24   64  377    0.632    0.120   0.737
 ptbtime2.ptb.de .PTB.            1 u   35   64  377    9.444    1.592   0.554

That’s it for now. Cheers! If you have any suggestions, please write a comment.

Links

This post used several information from a couple of (german) articles and posts:

Featured image “dcf77 module-stapel” by ledmaster33 is licensed under CC BY-NC 2.0.


Viewing all articles
Browse latest Browse all 311

Trending Articles