Jump to content

Orange Pi Zero NTP Stratum 1 PPS GPS Server with Armbian OS, Hardware and Software Tutorial

Recommended Posts

Orange Pi Zero NTP Stratum 1 PPS GPS Server with Armbian OS.
Link to the Tutorial - http://schwartzel.eu3.org/ntp-stratum1.html

This tutorial uses a 3.3V capable GPS module with PPS output - TOPGNSS GN-701 (u-blox 7) but other similar modules should work.

This tutorial is for the Orange Pi Zero, but will probably work for other boards.


I couldn't easily do a comprehensive hardware and software tutorial on this forum, so I've published it on my web server and linked from here and attached a PDF.
Link to the Tutorial - http://schwartzel.eu3.org/ntp-stratum1.html

Tutorial PDF

If you spot any typo's or errors please let me know.


Link to comment
Share on other sites

Donate and support the project!

Just add the server to your NTP client as you would any other NTP server.
If you are using the Windows 10 OS then you can use the built in client.
Open Control Panel
Go to Clock, Language, and Region
Click the icon Date and Time
Open the tab named Internet Time
Click the button named Change settings
Tick Synchronize with internet time server
Fill in the IP of your NTP server

Click OK.

Link to comment
Share on other sites

Hi @Elektrický,

Nice tutorial, worked great for me. Bought a cheap GPS module:



And a pinheader to solder onto the OrangePi Zero board itself.



The only thing I had to change was to swap the RX/TX wires, as a straight connection did not work for my GPS board.




I did not have any success getting PPS to work through the USB connection (works as ttyACM). I had to use the GPIO dtb overlay and electrical connection as per your tut.

gpsd in action:



ntp[sec] in action:



Thanks a lot!



p.s. I still have to figure out why I needed this :thumbup:

Link to comment
Share on other sites

Hi @djurny, nice.  I'm glad that you liked my tutorial.

Re: "p.s. I still have to figure out why I needed this" :lol:
I have the same issue, but I like building things and I like the idea of having really accurate time.

I donated one to a friend in South Africa.  They have rolling power cuts which takes out the internet for several hours at a time.
He has a good UPS and some IoT devices that don't have real time clocks so they don't initialise properly without NTP time and he didn't have a suitable backup NTP server.   Technical overkill, but still a very economic solution to his problem.


Link to comment
Share on other sites

A few months back I came across something interesting on David Taylor's web site.
A shell script to control the temperature of a SBC using the heat generated by the CPU.

Of course if your clock oscillator is integrated into the CPU then this is a way to control it's temperature and theoretically get more accurate time.
I tried this and it worked really well with a few tweaks.  I liked it so scripted it as a service.
I'm getting a maximum offset of less than +-20 micro seconds


#!/usr/bin/env python
# ntpheat.sh
# generate some heat!
# Run ntpheat in the background.
# It will try to stabilize the CPU temperature at 54C by default.

# Sometimes one copy of ntpheat can use 100% of one CPU and
# still not heat up your Pi as much as you want.  The temptation
# is to add more insulation to your Pi, but then it will overshoot
# your target temperature if your load factor goes high.
# The solution is to run more than one copy of ntpheat.  This is
# easy to do with the -c option.
# To run 3 copies of ntpheat: ntpheat -c 3

import argparse
import hashlib
import os
import sys
import time

# Work with argvars
parser = argparse.ArgumentParser(description="make heat")
parser.add_argument('-c', '--copies',
                    help="Number of copies to run.  Default is 1",
parser.add_argument('-t', '--temp',
                    help="Temperature to hold.  Default is 57.0",
parser.add_argument('-w', '--wait',
                    help="Set delay time in seconds, default is 0.1",
args = parser.parse_args()

args.copies[0] -= 1
while args.copies[0]:
    args.copies[0] -= 1
    pid = os.fork()
    if pid:
        # I am the fork

zone0 = '/sys/class/thermal/thermal_zone0/temp'
cnt = 0

m = hashlib.md5()
temp = 0
max_cnt = args.wait[0] * 100000
# on a RasPi 3 the temp steps seem to be about 0.537 to 0.539C
temp_gate = args.target_temp[0]

while True:
    # on a RasPi 3, 200,000 of the m.update() can be one second
    delta = temp_gate - temp
    if  0 < delta:
        # heat it up
        m.update("Time is an illusion. Lunchtime doubly so.")  
        cnt = max_cnt
        # cools off slower than it heats up.
        # undocumented Python 'feature', no sleep less than 1 milli Sec
        sleep = args.wait[0] * 10.0 * -delta
        if 0.001 > sleep:
            sleep = 0.001

    cnt += 1
    # read the temperature every max_cnt
    if max_cnt < cnt:
        cnt = 0

        zone_data = open(zone0, 'r')
        for line in zone_data:
            temp = float(line) / 1000


The service file: ntpheat.service - if you don't know how to set up a systemd service then go here https://wiki.debian.org/systemd/Services







I should add:  To make the CPU based temperature control work, there must be no CPU intensive processes at all.  This means disabling any cron jobs that load the CPU or forcing them to use less CPU over a longer period.
To do this you need cgroup-tools

#spread out heating caused by scheduled maintenance on NTP server
#get package
sudo apt-get install -y cgroup-tools

#create a cpu group called cpulimit
sudo cgcreate -g cpu:/cpulimit

#set cpulimit group limit to 100000uS out of 1000000uS (= 10% of CPU cycles)
sudo cgset -r cpu.cfs_period_us=1000000 cpulimit
sudo cgset -r cpu.cfs_quota_us=100000 cpulimit

#check settings
sudo cgget -g cpu:cpulimit

#to limit your process start it as follows - sudo cgexec -g cpu:cpulimit YOUR_COMMAND

You can use this to run CPU intensive jobs at 10%
To reconfigure some cron jobs:

@daily root cgexec -g cpu:cpulimit /usr/lib/armbian/armbian-apt-updates

Some cron jobs run scripts:

#for some cron scripts:
   cgexec -g cpu:cpulimit apt-show-versions -i 
   cgexec -g cpu:cpulimit exec /usr/lib/sysstat/sa2 -A

Apt xapian index is a hog...  limit it to 5%

#create a cpu group called cpulimit5 (for 5% CPU)
sudo cgcreate -g cpu:/cpulimit5

#set cpulimit group limit to 25000uS out of 500000uS (= 5% of CPU cycles) for bad process.
sudo cgset -r cpu.cfs_period_us=500000 cpulimit5
sudo cgset -r cpu.cfs_quota_us=25000 cpulimit5

/etc/cron.weekly/apt-xapian-index - comment out all except top line and replace with
   cgexec -g cpu:cpulimit5 /usr/sbin/update-apt-xapian-index


Link to comment
Share on other sites

Just another observation...  On one website that I came across, they recommended bubble wrap as an insulator around the board (don't do this).

CPU temperature control works better without extra insulation on my Orange Pi zero in it's plastic case.  I tested it and found that a maximum offset of less than +-20 micro seconds without insulation went up to +-24 micro seconds with insulation.  My conclusion is that the board needs to be able to passively shed heat quickly (as well as heat up quickly).

If your board is in an area with large ambient temperature variations then my guess is that some kind of insulation around a small "tweaked" volume of air acting as a temperature damper will probably work better than insulation directly on the board.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Create New...