For LTX 2023, I built a timing platform centered around Timebeat's Timecard mini.
The time card's GPS modem is used to acquire the precise time using GPS or GNSS satellites, and that time is then displayed on a tiny 1.3" TFT connected through the Raspberry Pi GPIO pins.
A Blinkstick Nano shows different colors and patterns depending on what time it is. It will help me split up time during a live stream into 5 minute segments, so Chris (from Crosstalk Solutions) and I can keep the stream moving along during the busy day at LTX 2023, raising money for the ITDRC.
Watch the video: GPS and a Raspberry Pi over PCI—the new Time Card mini!
Timebeat maintains their own software that integrates PPS output from the U-blox GPS/GNSS module into PTP/PPS inputs and outputs on the Raspberry Pi CM4. The timebeat
service is configured via /etc/timebeat/timebeat.yml
, and to make sure time is served up through GPS only, you will need to edit that file.
- Edit the timebeat config file:
/etc/timebeat/timebeat.yml
- Comment out the
pps
input config example on interfaceeth0
in theprimary_clocks
section. - Copy the
timecard-mini
protocol item into the top of theprimary_clocks
section. - Restart the timebeat service:
sudo systemctl restart timebeat
If you want to use gpsd
instead:
- Stop and disable the
timebeat
service:sudo systemctl stop timebeat && sudo systemctl disable timebeat
- Make sure
console=serial0,115200
is not inside the file/boot/cmdline.txt
(if so, delete that portion, which sets upttyS0
/serial0
as a UART, then reboot the Pi before proceeding). - Install
gpsd
:sudo apt install -y gpsd
- Edit the
gpsd
config file:sudo nano /etc/default/gpsd
- Change the
DEVICES
line to:DEVICES="/dev/ttyS0"
and save (Ctrl + O, Ctrl + X) - Restart the
gpsd
service:sudo systemctl restart gpsd
- Run
gpsmon
to make sure the GPS module is found—it should show up in theDEVICES
output, and after a while, once GPS satellites are found, you should see TODO.
Once gpsd
is running and configured, you need to set the system to use the GPS module as a time source. The GPS module needs to output PPS (Pulse Per Second) for this to work, and luckily, the U-blox should. However, it won't until the receiver gets a GPS fix (and this can take a while sometimes, especially if you don't have a clear view of the sky).
You can stop gpsd
and run ppscheck /dev/ttyS0
to monitor for PPS's, or just wait (and use gpsmon
while gpsd
is running—it should also show PPS's).
Setting up NTP or Chrony to use gpsd
for PPS input is not covered here. I'll do that at some point in the future.
For quick visual indication of how much time remains in 5-minute segments during an LTX livestream, I have a Blinkstick Nano plugged into the USB-A port on the Timecard mini.
(Note: I used a PiTray mini for the eeprom flashing. Procedures to program the CM4 eeprom using usbboot vary by CM4 IO board model, but typically you would disable the eMMC Boot option, whether via dip switch or jumper.)
- Plug the CM4 into a PiTray mini.
- Ensure the eMMC Boot switch is 'OFF'
- Plug the PiTray mini into your computer.
- Follow these steps to flash the eeprom of the CM4 using
usbboot
. - When it comes time to edit the
boot.conf
file, add the following line to the end of the file, and save it, before running./update-pieeprom.sh
. - After the update is complete, unplug the CM4 and plug it back into the Timecard mini.
The Pypi blickstick
package has a few bugs currently, but you will still use it for the Python script that will display time on the LED.
-
Install
pyusb
:sudo pip3 install pyusb
-
Install
blinkstick
:sudo pip3 install blinkstick
-
Copy the
blinkstick/
directory into/opt
-
Create a systemd unit for
blinktime.py
:sudo nano /lib/systemd/system/blinktime.service
-
Inside, put:
[Unit] Description=blinktime Wants=network.target After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 blinktime.py WorkingDirectory=/opt/blinkstick Restart=always [Install] WantedBy=multi-user.target
-
Reload systemctl:
sudo systemctl daemon-reload
-
Enable the service:
sudo systemctl enable blinktime.service
-
Start the service:
sudo systemctl start blinktime
If you connect an Adafruit mini PiTFT HAT to the Rasbperry Pi GPIO header, you can display the current time and GPS status on a handy little screen.
Hardware-wise, to clear the sandwich stack of all the Time Card boards, I had to purchase a GPIO stacking female header kit.
For software setup, you need to copy over the wopr
code, then set it to run on boot. And yes, wopr
is a reference to the game countdown display on the War Games WOPR computer.
sudo apt install -y python3-pip fonts-dejavu python3-pil python3-numpy
sudo pip3 install --upgrade adafruit-python-shell
wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/raspi-blinka.py
sudo python3 raspi-blinka.py
Reboot, then:
sudo pip3 install adafruit-circuitpython-rgb-display
sudo pip3 install --upgrade --force-reinstall spidev
This script was tested along with Timebeat's Multi-constellation GPS / GNSS module, specifically the U-blox LEA-M8F variant.
There is a script that checks on the GPS status and writes to a file in /tmp/gps-status
either 'A' (GPS is locked) or 'V' (GPS is not locked / acquiring).
This script is used by the WOPR script to display GPS status information.
-
Copy the
gps/
directory into/opt
on the Raspberry Pi. -
Create a systemd unit for
gpslock-timebeat.py
:sudo nano /lib/systemd/system/gpslock.service
-
Inside, put:
[Unit] Description=gpslock Wants=network.target After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 gpslock-timebeat.py WorkingDirectory=/opt/gps Restart=always [Install] WantedBy=multi-user.target
-
Reload systemctl:
sudo systemctl daemon-reload
-
Enable the service:
sudo systemctl enable gpslock.service
-
Start the service:
sudo systemctl start gpslock
If you are not running Timebeat, you can directly access the serial port to get GPS data using the gpslock.py
script—just copy that script into the /opt/gps
folder, and update the ExecStart
statement to point to it.
-
Copy the
wopr/
directory into/opt
on the Rasbperry Pi. -
Create a systemd unit for
wopr.py
:sudo nano /lib/systemd/system/wopr.service
-
Inside, put:
[Unit] Description=WOPR Wants=network.target After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 wopr.py WorkingDirectory=/opt/wopr Restart=always [Install] WantedBy=multi-user.target
-
Reload systemctl:
sudo systemctl daemon-reload
-
Enable the service:
sudo systemctl enable wopr.service
-
Start the service:
sudo systemctl start wopr
MIT
This project was built in 2023 for LTX Expo by Jeff Geerling.