Category Archives: Raspberry Pi

Hot water tank monitoring

I have electrically heated hot water in my house, and it takes ages to heat a whole tank. It heats up overnight on low cost electricity and we use it during the day. One constant frustration I have is there is no way of knowing how much hot water is left in the tank. I have to canvas my family and interrogate them on who’s had a shower or bath and how much washing up has been done. It would be so much better if I had a web page that showed the remaining hot water level in the tank !?

So, I attached temperature sensors up the side of the hot water tank and monitored them with a Raspberry Pi, of course ! 🙂

I have always wanted to use 1-wire devices in a project, and this was the perfect project. 1-wire devices make the cabling of many sensors easy as they all sit on a shared bus. You can get away with just 2 wires, a signal and a ground, as the devices can consume parasitic power from the signal line before communicating. However, to avoid any power issues and as I didn’t have a problem running more wires, I opted for three wires, power, signal and ground.

I am using the MAX31820 1-wire temperature sensors. They have a simple 3 pin transistor style package (TO-92) and there are lots of existing libraries and support for them. They’re also cheap. I decided to connect them using a ribbon cable, so I made little PCBs for them with a 4 pin header, to make the ribbon cable connection easy. I ended up using 6 way ribbon cable with 6 pin sockets, as it turns out 4 pin IDC sockets are a very difficult to find, where as 6 pin sockets are cheap as chips.

MAX31820 1-wire temperature sensor mounting PCB

MAX31820 1-wire temperature sensor mounting PCB

MAX31820 1-wire temperature sensors on small PCBs

MAX31820 1-wire temperature sensors on small PCBs

Example MAX31820 1-wire temperature sensors on small PCB attached to a ribbon cable

Example MAX31820 1-wire temperature sensors on small PCB attached to a ribbon cable

I already had a USB Adapter for 1-wire, which conveniently is supported by most of the 1-wire Raspberry Pi libraries. However, there are lots of ways of connecting 1-wire devices to a Raspberry Pi. The USB adapter is DS9490R. It takes an RJ11 plug to connect to the 1-wire bus, which also conveniently attaches to my ribbon cable. So, the solution is surprisingly neat.

The tank is pretty standard. Its covered in a insulated foam. I arbitrarily decided that 10 sensors was probably enough resolution. I marked the tank and made 10 equally spaced holes in the insulation with a pencil, then cleaned out the foam with the eraser end of the pencil, until I could see the shiny copper. I dabbed a blob of thermal paste in each hole, to assist with heat transfer from the copper tank to the temperature sensor, as I wouldn’t get direct mechanical contact. The boards and sensors just friction fitted in to the holes, and are kept in by the resistance of the foam on the boards. They are pretty snug and don’t fall out.

The cabling is simple, just attaching IDC connectors at the same regular intervals and then connecting the string of sensors to the Raspberry Pi.

Hot water tank

Hot water tank

Hot water tank with holes for temperature sensors marked

Hot water tank with holes for temperature sensors marked

Hole in the foam insulation showing the shiny copper tank

Hole in the foam insulation showing the shiny copper tank

Temperature sensor on mounting board inserted in the foam insulation

Temperature sensor on mounting board inserted in the foam insulation

Temperature sensors wired together with ribbon cable

Temperature sensors wired together with ribbon cable

Raspberry Pi connected via USB 1-wire adapter to string of sensors

Raspberry Pi connected via USB 1-wire adapter to string of sensors

Raspberry Pi connected via USB 1-wire adapter to string of sensors

Raspberry Pi connected via USB 1-wire adapter to string of sensors

Once the sensors were mounted and connected I installed OWFS (One Wire Filing System) on the Raspberry Pi which is a really easy way to read 1-wire sensors. It maps all the sensors found on the bus to a file system, so by reading the files you can read all the data and configure of all the connected sensors. Again there are loads of ways to access 1-wire devices. Using OWFS just made it easy for me. You could use Python or C, or any other myriad of languages, which all have 1-wire libraries.

Here are some instructions to install OWFS on a Raspberry Pi.

The OWFS maps the devices to a mount point. If you list the contents you get something like this :

root@raspberrypi:# cd /mnt/1wire/
root@raspberrypi:/mnt/1wire# ls -la
total 4
drwxr-xr-x 1 root root 4096 Nov  4 16:17 .
drwxr-xr-x 3 root root 4096 Mar  3  2015 ..
drwxrwxrwx 1 root root 4096 Mar 20 19:46 28.0BA759050000
drwxrwxrwx 1 root root 4096 Mar 20 19:46 28.168F59050000
drwxrwxrwx 1 root root 4096 Mar 20 19:46 28.229659050000
drwxrwxrwx 1 root root 4096 Mar 20 19:46 28.33A559050000
drwxrwxrwx 1 root root 4096 Mar 20 19:46 28.49B159050000
drwxrwxrwx 1 root root 4096 Mar 20 19:46 28.849459050000
drwxrwxrwx 1 root root 4096 Mar 20 19:46 28.AAB059050000
drwxrwxrwx 1 root root 4096 Mar 20 19:46 28.BBA459050000
drwxrwxrwx 1 root root 4096 Mar 20 19:46 28.C8AA59050000
drwxrwxrwx 1 root root 4096 Mar 20 19:46 28.E6B059050000
drwxrwxrwx 1 root root 4096 Mar 20 19:46 81.E1E324000000
drwxr-xr-x 1 root root 4096 Nov  4 16:17 alarm
drwxr-xr-x 1 root root 4096 Nov  4 16:17 bus.0
drwxr-xr-x 1 root root 4096 Nov  4 16:17 settings
drwxrwxrwx 1 root root 4096 Mar 20 19:46 simultaneous
drwxr-xr-x 1 root root 4096 Nov  4 16:17 statistics
drwxr-xr-x 1 root root 4096 Nov  4 16:17 structure
drwxr-xr-x 1 root root 4096 Nov  4 16:17 system
drwxr-xr-x 1 root root 4096 Nov  4 16:17 uncached

In each directory you can read either the cached or uncached version of the data, plus other details about the device.

root@raspberrypi:/mnt/1wire/28.0BA759050000# ls -la
total 0
drwxrwxrwx 1 root root 4096 Mar 20 19:46 .
drwxr-xr-x 1 root root 4096 Nov  4 16:17 ..
-r--r--r-- 1 root root   16 Nov  4 16:17 address
-rw-rw-rw- 1 root root  256 Nov  4 16:17 alias
-r--r--r-- 1 root root    2 Nov  4 16:17 crc8
drwxrwxrwx 1 root root 4096 Mar 20 19:46 errata
-r--r--r-- 1 root root    2 Nov  4 16:17 family
-r--r--r-- 1 root root   12 Nov  4 16:17 fasttemp
-r--r--r-- 1 root root   12 Nov  4 16:17 id
-r--r--r-- 1 root root   16 Nov  4 16:17 locator
-r--r--r-- 1 root root    1 Mar 20 19:46 power
-r--r--r-- 1 root root   16 Nov  4 16:17 r_address
-r--r--r-- 1 root root   12 Nov  4 16:17 r_id
-r--r--r-- 1 root root   16 Nov  4 16:17 r_locator
-r--r--r-- 1 root root    9 Mar 20 19:46 scratchpad
-r--r--r-- 1 root root   12 Nov  4 16:17 temperature
-r--r--r-- 1 root root   12 Nov  4 16:17 temperature10
-r--r--r-- 1 root root   12 Nov  4 16:17 temperature11
-r--r--r-- 1 root root   12 Nov  4 16:17 temperature12
-r--r--r-- 1 root root   12 Nov  4 16:17 temperature9
-rw-rw-rw- 1 root root   12 Mar 20 19:46 temphigh
-rw-rw-rw- 1 root root   12 Mar 20 19:46 templow
-r--r--r-- 1 root root   32 Nov  4 16:17 type

root@raspberrypi:/mnt/1wire/28.0BA759050000# cat address 
280BA759050000FA

root@raspberrypi:/mnt/1wire/28.0BA759050000# cat family 
28

root@raspberrypi:/mnt/1wire/28.0BA759050000# cat temperature
51.375

root@raspberrypi:/mnt/1wire/28.0BA759050000#

I run a shell script every 5 minutes to read the latest data from all the sensors and store it in a text file.

> cat /root/scripts/logtemp.sh 

#!/bin/sh
date | tr -d '\n' >> /home/pi/templog.txt
echo -n ',' >> /home/pi/templog.txt
cat /mnt/1wire/28.E6B059050000/temperature >> /home/pi/templog.txt
echo -n ',' >> /home/pi/templog.txt
cat /mnt/1wire/28.0BA759050000/temperature >> /home/pi/templog.txt
echo -n ',' >> /home/pi/templog.txt
cat /mnt/1wire/28.49B159050000/temperature >> /home/pi/templog.txt
echo -n ',' >> /home/pi/templog.txt
cat /mnt/1wire/28.168F59050000/temperature >> /home/pi/templog.txt
echo -n ',' >> /home/pi/templog.txt
cat /mnt/1wire/28.C8AA59050000/temperature >> /home/pi/templog.txt
echo -n ',' >> /home/pi/templog.txt
cat /mnt/1wire/28.33A559050000/temperature >> /home/pi/templog.txt
echo -n ',' >> /home/pi/templog.txt
cat /mnt/1wire/28.849459050000/temperature >> /home/pi/templog.txt
echo -n ',' >> /home/pi/templog.txt
cat /mnt/1wire/28.BBA459050000/temperature >> /home/pi/templog.txt
echo -n ',' >> /home/pi/templog.txt
cat /mnt/1wire/28.229659050000/temperature >> /home/pi/templog.txt
echo -n ',' >> /home/pi/templog.txt
cat /mnt/1wire/28.AAB059050000/temperature >> /home/pi/templog.txt
echo ',END' >> /home/pi/templog.txt

I then use this data from a simple web page written in Python to display the latest temperatures in the tank. I decided 35 degrees Celsius is “cold”. If the water is below this I show it as blue (Cold), if its above this I show it as red (Hot). This is open to future expansion where I can fade the colour from red to blue depending on the temperature, more red for hot, more blue for cold, rather than a single colour, but that’s for another day.

> cat hotwater.py 

#!/usr/bin/env python
import cgi
import cgitb
cgitb.enable()

form = cgi.FieldStorage()

print 'Content-type: text/html\n\n'
print '<html><head></head><body>'

fn = '/home/pi/templog-latest.txt'
f = open(fn, 'r')
t = f.readline()
f.close()

temps = t.split(',')

o = ''

if form.getvalue("up","true") == 'true':
        up = True
else:
        up = False

for temp in temps:
        if len(temp) > 8:
                d = temp +"<br>"
        elif len(temp) < 2:
                if up:
                        o = o +'<tr><td bgcolor="#00FF00" align="center"></td></tr>'
                else:
                        o = '<tr><td bgcolor="#00FF00" align="center"></td></tr>'+ o
        elif temp.strip('\n') == 'END':
                z = 1
        else :
                n = int(float(temp))
                if n > 35:
                        if up:
                                o = o +'<tr><td bgcolor="#FF0000" align="center">'+ str(n) +'</td></tr>'
                        else:
                                o = '<tr><td bgcolor="#FF0000" align="center">'+ str(n) +'</td></tr>'+ o
                else:
                        if up:
                                o = o +'<tr><td bgcolor="#0000FF" align="center">'+ str(n) +'</td></tr>'
                        else:
                                o = '<tr><td bgcolor="#0000FF" align="center">'+ str(n) +'</td></tr>'+ o

print d +'<table width=150>'+ o +'</table>'
print '</body></html>'

I can access the web page from anywhere in my house, on my mobile phone, and it instantly shows the quantity of hot water left in the tank, plus each of the 10 individual temperature readings from the sensors. The query string parameter in the web page script reverses the order of the sensor readings in the tank. “up=false” or with no query string, is the default setting, where the temperatures are shown in the correct order, with the hottest water “floating” at the top of the tank. The alternate view, is for users who don’t want a view based on physics, and would rather the visualise a tank full of hot water emptying from the bottom. In this view the hot water is seen at the bottom, slowly draining away to empty. Not scientifically correct, but easier to explain to my 8 year old. Either way the bookmark is saved with the appropriate query string parameter, and everyone in my house can now tell how much hot water is left, before they get in the shower. No more showers suddenly going cold half way through.

Hot water monitoring web page. This shows the tank about half full of hot water. The top of the tank at 45 degrees. The bottom of the tank at 16.

Hot water monitoring web page. This shows the tank about half full of hot water. The top of the tank at 45 degrees. The bottom of the tank at 16.

 

Raspberry Pi – Stratum 1 NTP Server

This blog is mostly about robots, but not exclusively. 🙂

I needed an NTP server at home, as my security cameras were drifting out of sync. So, I thought I’d create a Stratum 1 NTP Server, with a Raspberry Pi and a GPS receiver.

There are lots of guides on the web, so I just followed the instructions, but it was very easy, once you understand the basics. There are two ways to synchronise the time on the Raspberry Pi to a GPS receiver. The first is just to use the GPS NMEA data to get the time. With a 1 Hz update, you have be accurate to about a second. However, some GPS receivers provide a pulse-per-second output, that provides a digital signal every second that can be attached to a hardware interrupt and this can be accurate to a microsecond.

Nearly all the instructions I used came from here :

I did a couple of other things too, as I had trouble keeping my Raspberry Pi’s running for longer than 3 months on an SD card. After 3 months of being continuously on, I usually got SD card corruption and the server died. I decided to switch this Raspberry Pi to use a USB flash drive to the filing system, and the SD card, just to boot.

The instructions for using a USB flash filing system are here :

I did this first, then configured the GPS / NTP. For this post, I’ll ignore the USB configuration, and it’s not relevant to the GPS / NTP install. It’s up to you if you need it. I’ve heard of lots of people that have run a Raspberry Pi for over a year on an SD card without any issues, and others who have had the same issues as me, with no more than a few months without file system corruption.

The first thing to do is connect the GPS receiver to the RPi. I used an Adafriut Ultimate GPS breakout board.  It has lots of useful features; it’s cheap, it’s easy to connect as it has 0.1” headers, it has a PPS output, it’s 3.3v and it has an external aerial mount.

Adafruit Ultimate GPS Breakout Board

Adafruit Ultimate GPS Breakout Board

The only problem I found with these GPS units is I couldn’t find a way to permanently change the baud rate. If you set the baud rate on the GPS receiver, the setting doesn’t survive a power cycle. If anyone knows how to do this, let me know. Even in production I am running the GPS at 9600 baud. I would have preferred to run it at a faster rate, which would give better accuracy as the NMEA data can be processed faster. But seeing as the clock is set using the PPS, its not a major issue.

I used a Slice of Pi prototype board to make it easy to connect the GPS to the Raspberry Pi. The wiring is straight forward, 3.3v and Gnd, Tx & Rx, and the PPS connected to GPIO pin 8.

Slice of Pi prototype board

Slice of Pi prototype board

I also have a Power Over Ethernet switch, so I added a PoE power adapter, so the Raspberry Pi would have minimal wiring. I bought a plastic box from Maplins and mounted the PoE adapter, RPi, GPS and external GPS connector all in the box. The box had a clear plastic lid, which also means you can see the RPi in action.

Power Over Ethernet adapter

Power Over Ethernet adapter

Assembled Raspberry Pi NTP Server

Assembled Raspberry Pi NTP Server

Assembled Raspberry Pi NTP Server in case with PoE

Assembled Raspberry Pi NTP Server in case with PoE

Once the hardware was attached, the software configuration follows the instruction linked above.

1. Disable serial comms on the console. We need it for the GPS.

Disable console output to serial

sudo vi /boot/cmdline.txt

find this :

dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

and edit it to this :

dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

Disable the login prompt

sudo vi /etc/inittab

find the line near the end

T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

add # to comment it out.

#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

2. Configure Static IP

I need my NTP server to have a static IP

If you use DHCP, remove “ntp-servers” from the “request” line in /etc/dhcp/dhclient.conf

Remove /var/lib/ntp/ntp.conf.dhcp if present

sudo vi /etc/network/interfaces

Edit the following entry:

iface eth0 inet dhcp

Change it to (using your local network settings):

iface eth0 inet static
address 10.1.0.128
netmask 255.255.255.0
gateway 10.1.0.1
network 10.1.0.0
broadcast 10.1.0.255

reboot…

At this point you should see the GPS NMEA data coming from the serial port. Test it like this :

sudo cat /dev/ttyAMA0

If you dont see NMEA data, go back and check your wiring and baud settings.

3. Install gpsd

sudo apt-get install gpsd gpsd-clients python-gps
sudo gpsd /dev/ttyAMA0 -F /var/run/gpsd.sock

test it recieves GPS data :

sudo cgps –s

+-------------------------------------------++---------------------------------+
|    Time:       2014-07-07T22:34:15.000Z   ||PRN:   Elev:  Azim:  SNR:  Used: |
|    Latitude:    51.501114 N               ||  20    73    246    32      Y   |
|    Longitude:   -0.142448 W               ||   1    72    117    44      Y   |
|    Altitude:   99.8 m                     ||  32    61    068    51      Y   |
|    Speed:      0.0 kph                    ||  11    45    142    38      Y   |
|    Heading:    67.1 deg (true)            ||  17    43    296    21      Y   |
|    Climb:      0.0 m/min                  ||  33    29    199    00      Y   |
|    Status:     3D FIX (10 secs)           ||  23    28    180    00      Y   |
|    Longitude Err:   +/- 4 m               ||   4    20    294    28      Y   |
|    Latitude Err:    +/- 3 m               ||  31    12    085    42      N   |
|    Altitude Err:    +/- 9 m               ||  14    11    035    17      N   |
|    Course Err:      n/a                   ||  28    08    250    00      N   |
|    Speed Err:       +/- 31 kph            ||  13    02    191    00      N   |
|    Time offset:     0.662                 ||  19    01    161    00      N   |
+-------------------------------------------++---------------------------------+

4. Configure gpsd to auto start

sudo dpkg-reconfigure gpsd

The configuration program will ask you a series of questions :

Start gpsd automatically? Yes
Should gpsd handle attached USB GPS receivers automatically? No
Device the GPS receiver is attached to: /dev/ttyAMA0
Options to gpsd: -n
gpsd control socket path: /var/run/gpsd.sock

reboot…

sudo cgps –s

You should get the same output as before. This shows everything is starting up correctly on boot.

5. Configure NTP

Make a backup of the ntp.conf file. Edit the conf file.

sudo cp /etc/ntp.conf /etc/ntp.old.conf
sudo vi /etc/ntp.conf

Remove the IP access restrictions

Comment out :

restrict -4 default kod notrap nomodify nopeer noquery

#restrict -4 default kod notrap nomodify nopeer noquery

Configure NTP to use the UK NTP pool servers.
I’m in the UK. If you’re not, pick the most local pool to you.

Replace:

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

With:

pool uk.pool.ntp.org iburst

Add the local NTP server from your ISP.

server ntp.eclipse.co.uk iburst

Restart NTP and check its working.

sudo /etc/init.d/ntp restart
sudo ntpq -p -n

     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*213.249.130.101 10.100.94.8      2 u    3   64  377  120.208   37.434  53.254
+87.124.126.49   195.66.241.3     2 u   10   64  377   32.008   -8.111  99.007
 82.219.4.30     .INIT.          16 u    - 1024    0    0.000    0.000   0.000
 217.10.144.130  .INIT.          16 u    - 1024    0    0.000    0.000   0.000
-151.230.30.222  103.7.151.4      2 u   25   64  377   47.016    0.743  98.865

Basic NTP is now working, but without GPS. Even without GPS, its still accurate to about 37ms.

6. Add the GPS configuration to NTP

Edit ntp.conf

sudo vi /etc/ntp.conf

add :

# Server from shared memory provided by gpsd
server 127.127.28.0 minpoll 4 maxpoll 4
fudge  127.127.28.0 time1 0.000 refid GPS

Restart NTP and check its working.

sudo /etc/init.d/ntp restart
sudo ntpq -p -n

     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*127.127.28.0    .GPS.            0 l    7   16  377    0.000   -353.23 15.024
-213.249.130.101 10.100.94.8      2 u   62   64  377   52.603   -3.554  77.753
-87.124.126.49   195.66.241.3     2 u    6   64  377   42.207   -5.468  78.352
 82.219.4.30     .INIT.          16 u    - 1024    0    0.000    0.000   0.000
 217.10.144.130  .INIT.          16 u    - 1024    0    0.000    0.000   0.000
+151.230.30.222  103.7.151.4      2 u   16   64  377   47.016    0.743  58.425

Adjust the time1 fudge offset to compensate for drift. The GPS NMEA input is taking about 350ms to process.

fudge  127.127.28.0 time1 0.350 refid GPS

Restart NTP and check again. The GPS inout should be more accurate. (now only 11ms out)

     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*127.127.28.0    .GPS.            0 l    3   16  377    0.000   11.721  38.208
+213.249.130.101 10.100.94.8      2 u   33   64  377   72.434    1.227  98.033
-87.124.126.49   195.66.241.3     2 u   48   64  377   50.215   -0.824  76.877
 82.219.4.30     .INIT.          16 u    - 1024    0    0.000    0.000   0.000
 217.10.144.130  .INIT.          16 u    - 1024    0    0.000    0.000   0.000
-151.230.30.222  103.7.151.4      2 u   56   64  377   48.522    0.481  50.334

7. Install user mode PPS module

For more details see : http://vanheusden.com/time/rpi_gpio_ntp/

sudo wget http://vanheusden.com/time/rpi_gpio_ntp/rpi_gpio_ntp-1.3.tgz
sudo tar -zxvf rpi_gpio_ntp-1.3.tgz
sudo cat rpi_gpio_ntp-1.3/readme.txt

Read the instructions. You must build and install the program:

sudo cd rpi_gpio_ntp-1.3
sudo make install

You probably want to let rpi_gpio_ntp start at boot.

To do so, edit /etc/rc.local

sudo vi /etc/rc.local

and add the following line (BEFORE the “exit 0” statement and AFTER the “#!/bin/sh” line):

/usr/local/bin/rpi_gpio_ntp -N 1 -g 8

This assumes that the PPS signal of the GPS is connected to GPIO pin 8 which is physical pin 24.

reboot…

8. Add the PPS configuration to NTP

Edit ntp.conf

sudo vi /etc/ntp.conf

add :

# Server from PPS module 
server 127.127.28.1 minpoll 4 maxpoll 4 prefer
fudge  127.127.28.1 refid PPS

Restart NTP and check its working.

sudo /etc/init.d/ntp restart
sudo ntpq -p -n

     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
+127.127.28.0    .GPS.            0 l   15   16  377    0.000   65.031  38.403
*127.127.28.1    .PPS.            0 l   14   16  377    0.000    0.001   0.006
x213.249.130.101 10.100.94.8      2 u   12   64  377   79.034   16.835  82.844
+87.124.126.49   195.66.241.3     2 u   26   64  377   28.945    1.316  42.948
 82.219.4.30     .INIT.          16 u    - 1024    0    0.000    0.000   0.000
 217.10.144.130  .INIT.          16 u    - 1024    0    0.000    0.000   0.000
-151.230.30.222  103.7.151.4      2 u   39   64  377   36.126    2.120  57.079

This shows the Raspberry Pi system clock is accurate to 1us !!

My final ntp.conf file :

driftfile /var/lib/ntp/ntp.drift

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

# Server from shared memory provided by gpsd
server 127.127.28.0 minpoll 4 maxpoll 4
fudge  127.127.28.0 time1 0.550 refid GPS

# Server from PPS module 
server 127.127.28.1 minpoll 4 maxpoll 4 prefer
fudge  127.127.28.1 refid PPS

# You do need to talk to an NTP server or two (or three).
server ntp.eclipse.co.uk iburst

# pool.ntp.org maps to about 1000 low-stratum NTP servers.  Your server will
# pick a different set every time it starts up.  Please consider joining the
# pool: 
pool uk.pool.ntp.org iburst

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

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

The final NTP Server installed in my garage, with an external GPS aerial on the roof.

Assembled Raspberry Pi NTP Server in case with PoE

Assembled Raspberry Pi NTP Server in case with PoE