Raspberry Pi APRS Tracker

As the SD cards of my Raspberry Pi based APRS tracker died I had to rebuild it. And due to not having a backup the the config files it is documented here.

# Install/Remove Software packages

Install necessary software packages:

$ sudo apt install gpsd gpsd-clients gpsd-tools minicom ntp direwolf

Also delete unnecessary / conflicting software packages:

$ sudo apt purge modemmanager

# Disable Serial Console on GPIO Header

Edit /boot/cmdline.txt and remove the “console=serial0,115200”. Then stop and disable the corresponding services:

$ sudo systemctl stop serial-getty@ttyAMA0.service
$ sudo systemctl disable serial-getty@ttyAMA0.service

# Enable WM8731 Audio Hat

Edit /boot/config.txt and disable onboard sound and instead enable WM8731 sound chip on GPIO header:

# Disable snd_bcm2835 onboard audio
# dtparam=audio=on

# Enable WM8731 codec
dtparam=i2c_arm=on
dtparam=i2s=on
dtoverlay=i2s-mmap
dtoverlay=rpi-proto

# Change Device Name of Sound Card

To find out the device path execute udevadm monitor for sound subsystem:

$ udevadm monitor --kernel --property --subsystem-match=sound

While unloading and loading the snd_soc_rpi_proto module. Then add udev rule like:

SUBSYSTEM=="sound" DEVPATH=="/devices/platform/soc/soc:sound/sound/card0", ATTR{id}="SVX_HAT" TAG+="systemd", ENV{SYSTEMD_WANTS}="direwolf.service"

Just add an udev rule /etc/udev/rules.d/50-usbserial.rules:

SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="AH01CE6Q", SYMLINK+="gpsmouse", GROUP="dialout", MODE="0660"

GPS device will be available as /dev/gpsmouse

# Building GPSD

Apparently the shipped package version 3.22 in Debian bullseye has a problem. For some reason clients only get one fix once they connect but this position is not updated while holding the connection. Instead the position is only updated upon restart of gpsd (see [1]). This is obviously not what we want :)

So gpsd has to be compiled from source. The current version 3.25 does not suffer from this problem. So here is the script to compile the sources:

$ sudo apt purge gpsd
$ sudo apt install -y scons   libncurses-dev python-dev pps-tools git-core asciidoctor python3-matplotlib  build-essential manpages-dev pkg-config python3-distutils
$ wget http://download-mirror.savannah.gnu.org/releases/gpsd/gpsd-3.25.tar.gz
$ tar -zvxf gpsd-3.25.tar.gz
$ cd gpsd-3.25/
$ scons
$ sudo scons install
$ sudo scons udev-install

# GPSD configuration

Edit /etc/default/gpsd:

# Devices gpsd should collect to at boot time.
# They need to be read/writeable, either by user gpsd or the group dialout.
DEVICES="/dev/gpsmouse"

# Other options you want to pass to gpsd
GPSD_OPTIONS="-n -s 9600 -f 8N1"

# Automatically hot add/remove USB GPS devices via gpsdctl
USBAUTO="false"
GPS Receiver with PPS wired to DCD
GPS Receiver with PPS wired to DCD

Testing of gpsd can be done using cgps on the console:

Screenshot of cgps
Screenshot of cgps

# NTP configuration

Edit /etc/ntp.conf and comment out the internet available servers. Add:

# PPS sync 
server 127.127.22.0 prefer
fudge 127.127.22.0 time1 1 refid PPS

# GPSD sync
server 127.127.28.0
fudge 127.127.28.0 time1 0.183 flag1 1 refid GPS

This shall lead to ntp reading the time off gpsd to solve the issue that the Raspberry Pi A+ itself does not have a RTC and no internet to sync to NTP servers (see [2] and [3]). The flag1 set to 1 is important to allow time changes by NTP larger than 24h which can happen after hours of powered-off.

# Configurung direwolf

With a few hints from [4] it is easy to add gpsd connection to direwolf:

GPSD
ADEVICE plughw:0,0
CHANNEL 0
MYCALL DF2ET-9
MODEM 1200
PTT GPIO 17
DCD GPIO 4
AGWPORT 8000
KISSPORT 8001
TBEACON DELAY=0:00 EVERY=1:00 VIA=WIDE1-1,WIDE2-1 SYMBOL=car COMMENT="Florian N18 Bochum"
SMARTBEACONING 30 0:90 5 20 0:15 30 255
CBEACON DELAY=10:00 DEST=APRS EVERY=10 INFO=">https://www.florian-wolters.de/posts/raspberry-pi-aprs-tracker/"
#LOGDIR /var/log/direwolf

If smart beaconing is used there also has to be a config line TBEACON to configure symbol and message etc. Just a single SMARTBEACONING line will simply result in no positions being sent at all.

By default direwolf starts way too early in the boot process where soundcard and GPIOs are not setup or available yet. Therefore the systemd service file for direwolf has been changed so that it requires multi-user.target to be reached before starting direwolf:

[Unit]
Description=DireWolf is a software "soundcard" modem/TNC and APRS decoder
Documentation=man:direwolf
AssertPathExists=/etc/direwolf.conf
BindsTo=sys-devices-platform-soc-soc:sound-sound-card0.device
After=sys-devices-platform-soc-soc:sound-sound-card0.device multi-user.target
Requires=multi-user.target

[Service]
User=direwolf
SupplementaryGroups=dialout audio
ExecStart=/usr/bin/direwolf -c /etc/direwolf.conf

[Install]
WantedBy=multi-user.target

# Read-Only Filesystems

As the last SD card probably died by wearing in out this time the operating system was setup to work from read-only filesystem. There is a number of things to change which are documented in [5]. After that the system mounts the SD card read-only and prevents the OS from writing to the card all the time and make it immune against power-offs during write operations to the SD card.

# References

[1] https://raspberrypi.stackexchange.com/questions/136196/why-does-gpsd-not-update-a-location-past-its-first-fix
[2] https://www.rjsystems.nl/en/2100-ntpd-garmin-gps-18-lvc-gpsd.php
[3] https://raspberry.tips/raspberrypi-tutorials/raspberry-pi-uhrzeit-ueber-gps-beziehen-zeitserver
[4] https://www.marrold.co.uk/2019/04/adding-usb-gps-receiver-to-direwolf-to.html
[5] https://medium.com/@andreas.schallwig/how-to-make-your-raspberry-pi-file-system-read-only-raspbian-stretch-80c0f7be7353