Setting up a Horus Binary Chase‐Car Raspberry Pi - projecthorus/chasemapper GitHub Wiki
Last Updated: 2026-06-12
These are some rough notes I put together while building up a Raspberry Pi for use by a visitor who was wanting to chase a balloon launch flying a Horus Binary tracking payload. They describe the steps required in setting up a Raspberry Pi from scratch with both ChaseMapper and the horusdemodlib decoder.
Warning: Newer versions of raspbian may have issues switching between WiFi networks.
- Raspberry Pi 3B or newer
- A RPi 3B or newer will work fine. Get a case for it!
- Watch out with the newer higher-power units, as these can overheat.
- Also make sure whatever unit you buy will work on the WiFi band your hotspot uses! Some RPi's won't do 5GHz WiFi.
- RTLSDR
- I generally use the RTLSDR v3 units.
- There are also good kits of RTLSDRs and antennas available on Amazon (e.g. "Nooelec RTL-SDR v5 Bundle")
- Antenna for 434 MHz
- Lots of options to choose from here. I'd suggest something with lower gain like a 1/4-wave. Too high gain and you may have trouble receiving signals from very high elevations.
- Commercial antennas from Diamond, e.g. the MR77 are suitable. Get the version with the SMA connector.
- Even cheapie 1/4-wave magmounts from Aliexpress can be good enough for this!
- USB GPS Receiver
- Some kind of power supply for your RPi
- Various USB battery banks will work. Make sure you have some idea of how long they will last!
- Alternative you could run it from your car, but be careful that it doesn't power off when you turn your car off!
- A 3G/4G/5G WiFi hotspot for your RPi to connect to for internet access.
- A tablet computer or some other computer (7" or bigger screen recommended) to display the ChaseMapper webpage.
- I used the Raspberry Pi Imager
- I used the Raspbian 64-bit Lite OS (available from the Operating system selection, under "Raspberry Pi OS (Other)". If you are running a older RPi (RPi 3 or older) then you will need to use a 32-bit image.
- Within the Imager options (gear icon) I also configured:
- Enabled SSH, and set the user to
piand password toraspberry. - Enabled WiFi, and configured my home wifi network. Note that the RPi 3 only does 2.4 GHz WiFi, but newer versions should also do 5 GHz.
- Set the hostname to
chasebox(so I can spot the RPi easily on my DHCP server)
- Enabled SSH, and set the user to
- I then wrote the image to a 64GB Sandisk High Endurance MicroSD Card.
- Found the RPi's IP address from my local DHCP server info.
- SSH'd into the RPi from another machine (
ssh pi@ip-address). If you're lucky then hostname lookup might work and you can usessh [email protected]
You could do all the following setup by plugging in a screen and keyboard, but since we're not going to have that available in the car, I find it best to log in via SSH.
Update APT repositories and upgrade any out-of-date packages:
sudo apt-get update
sudo apt-get upgradeInstall the packages we need for HorusBinary:
sudo apt-get install cmake build-essential libusb-1.0-0-dev git python3-venv python3-pip python3-dev python3-cffi libffi-dev sox bc rtl-sdrInstall docker (which we need for Chasemapper):
If you are running Raspbian/Debian Trixie, the Raspbian-provided version of docker works fine, and you can install this with:
sudo apt-get install docker.io
If running an older distribution (Debian/Raspbian bookworm or older), we recommend installing the latest version of docker using their convenience script:
sudo apt-get remove docker-engine docker docker.io docker-ce docker-ce-cli docker-compose-plugin
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.shSetup some permissions required for the pi user to be able to access serial ports, docker, and the RTLSDR:
sudo usermod -aG docker $(whoami)
sudo usermod -aG dialout $(whoami)
sudo wget -O /etc/udev/rules.d/20-rtlsdr.rules https://raw.githubusercontent.com/osmocom/rtl-sdr/master/rtl-sdr.rulesPlug in the RTLSDR and the GPS receiver, and reboot (sudo reboot).
SSH back into the RPi.
Test the RTLSDR using rtl_test. Ctrl-C to stop the testing.
$ rtl_test
Found 1 device(s):
0: Nooelec, NESDR SMArt v5, SN: 00000001
Using device 0: Generic RTL2832U OEM
Detached kernel driver
Found Rafael Micro R820T tuner
Supported gain values (29): 0.0 0.9 1.4 2.7 3.7 7.7 8.7 12.5 14.4 15.7 16.6 19.7 20.7 22.9 25.4 28.0 29.7 32.8 33.8 36.4 37.2 38.6 40.2 42.1 43.4 43.9 44.5 48.0 49.6
[R82XX] PLL not locked!
Sampling at 2048000 S/s.
Info: This tool will continuously read from the device, and report if
samples get lost. If you observe no further output, everything is fine.
Reading samples in async mode...
Allocating 15 zero-copy buffers
lost at least 76 bytes
^CSignal caught, exiting!
User cancel, exiting...Test the GPS output using cat /dev/ttyACM0:
$ cat /dev/ttyACM0
$GPRMC,013316.00,A,3443.00000,S,13841.00000,E,0.089,,250424,,,D*67
$GPVTG,,T,,M,0.089,N,0.164,K,D*24
$GPGGA,013316.00,3443.00000,S,13841.00000,E,2,07,1.54,103.1,M,-2.8,M,,0000*5A
$GPGSA,A,3,03,21,02,31,04,16,28,,,,,,2.98,1.54,2.56*09
$GPGSV,3,1,10,02,35,339,38,03,70,193,43,04,54,245,36,06,05,213,25*73
$GPGSV,3,2,10,16,15,046,26,21,24,353,38,26,27,080,19,28,20,138,29*7F
$GPGSV,3,3,10,31,50,127,38,50,48,340,38*75
... Ctrl-C to exit.Setup the required directories with:
mkdir -p ~/chasemapper/log_files
mkdir -p ~/Maps
curl -o ~/chasemapper/horusmapper.cfg https://raw.githubusercontent.com/projecthorus/chasemapper/master/horusmapper.cfg.exampleEdit the horusmapper.cfg file with nano ~/chasemapper/horusmapper.cfg. I changed:
-
default_profileto 2 (which is the Horus Binary profile) - In the
[serial]section changedgps_portto/dev/ttyACM0 - In the
[predictor]section, changedmodel_downloadtopython3 -m cusfpredict.gfs --lat=-33 --lon=139 --latdelta=10 --londelta=10 -f 24 -m 0p50 -o gfs(which is appropriate for the Adelaide area) - In the
[offline_maps]section, settile_server_enabledtoTrue - In the
[offline_maps]section, comment out thetile_server_paththat points to/home/pi/Maps, and uncomment the one lower down pointing to/opt/chasemapper/Maps - In the
[habitat]section, sethabitat_calltoCHASEBOX
You can grab a modified horusmapper.cfg file with the above changes by running:
curl -o ~/chasemapper/horusmapper.cfg curl -o test.cfg https://gist.githubusercontent.com/darksidelemm/323872f897881845e5e68315fd563833/raw/bc0895ef9cc0c144b98cad6d6744cc58fb27730c/horusmapper.cfg... though please change the habitat_call setting!!!
This is not strictly necessary, though if you know you're going out of phone coverage then it can be useful to have some map tiles available offline. There's some notes on offline map downloading here: https://github.com/projecthorus/chasemapper?tab=readme-ov-file#offline-mapping
If you have downloaded maps, these need to be placed into the /home/pi/Maps/ directory.
Download and startup the chasemapper docker container with the multi-line command:
docker run \
-d \
-t \
--name chasemapper \
--restart="always" \
--device=/dev/ttyACM0 \
--network=host \
-v ~/chasemapper/horusmapper.cfg:/opt/chasemapper/horusmapper.cfg:ro \
-v ~/chasemapper/log_files/:/opt/chasemapper/log_files/ \
-v ~/Maps/:/opt/chasemapper/Maps/ \
ghcr.io/projecthorus/chasemapper:latestThe log output from the docker image can be checked for errors using:
docker logs chasemapperPay close attention to the start of the log, as this will expose any errors in parsing the config file. If the config file cannot be parsed correctly, chasemapper will revert to defaults which may result in things like GPS connectivity breaking.
Confirm the chasemapper web interface is accessible by visiting http://<your_pi_ip>:5001 in a web browser.
Things worth testing now:
- Confirm the chase car position is appearing on the map (this will require GPS lock). You can also check the number of SVs tracked in the 'car' settings.
- Confirm you can download a GFS model. (The 'Current Model' text should change to 'Started Downloader'). It may take quite a while for the GFS model to download, and depending on how broken the NOMADS grib-filter is on any particular day it may fail altogether. After a while it should change to something like
2024042418z (Offline) - If you have added any offline map layers, check you can select them from the map layer list.
- If you want, check you can upload your position to the SondeHub-Amateur tracker by enabling 'Chase Car Position Upload' in the car settings. By default this setting is disabled, so it will need to be turned on if you restart the RPi or Chasemapper.
If you need to change any configuration settings, you can restart chasemapper with docker restart chasemapper
git clone https://github.com/projecthorus/horusdemodlib.git
cd horusdemodlibpython3 -m venv venv
. venv/bin/activate
pip install horusdemodlibcp user.cfg.example user.cfgEdit user.cfg (nano user.cfg):
-
callsign- This should match whatever you set forhabitat_callwhen setting up Chasemapper further above. -
station_latandstation_lon- Leave these at 0.0 for a chase car! Your position will be uploaded by Chasemapper -
radio_commentandantenna_commentas desired...
For our flights we're going to use the start_dual_4fsk.sh script as-is. If you are running different frequencies you may need to modify the frequency settings.
Startup a test Horus Binary payload on an appropriate frequency. Then, run start_dual_4fsk.sh:
./start_dual_4fsk.sh
Found horus_demod.
Found bc.
Entering venv.
Using SDR Centre Frequency: 434195000 Hz.
Using MFSK1 estimation range: 2500 - 7500 Hz
Using MFSK2 estimation range: 12500 - 17500 Hz
Using AGC.
Setting estimator limits to 12500 to 17500 Hz.
Setting estimator limits to 2500 to 7500 Hz.
Found 1 device(s):
0: Nooelec, NESDR SMArt v5, SN: 00000001
Using device 0: Generic RTL2832U OEM
Detached kernel driver
Found Rafael Micro R820T tuner
Tuner gain set to automatic.
Tuned to 434579000 Hz.
Oversampling input by: 32x.
Oversampling output by: 1x.
Buffer size: 5.33ms
Allocating 15 zero-copy buffers
Sampling at 1536000 S/s.
Output at 48000 Hz.
2024-04-25 11:47:10,427 INFO: Opened log file telemetry.log.
2024-04-25 11:47:10,429 INFO: Attempting to download latest payload ID list from GitHub...
2024-04-25 11:47:10,435 INFO: Opened log file telemetry.log.
2024-04-25 11:47:10,436 INFO: Attempting to download latest payload ID list from GitHub...
2024-04-25 11:47:11,485 INFO: Attempting to download latest custom field list from GitHub...
2024-04-25 11:47:11,495 INFO: Attempting to download latest custom field list from GitHub...
2024-04-25 11:47:12,478 INFO: Payload list contains 438 entries.
2024-04-25 11:47:12,480 INFO: Custom Field list contains 15 entries.
2024-04-25 11:47:12,480 INFO: Payload list contains 438 entries.
2024-04-25 11:47:12,481 INFO: Custom Field list contains 15 entries.
2024-04-25 11:47:12,483 INFO: Sondehub Amateur Uploader - Started Sondehub Amateur Uploader Thread.
2024-04-25 11:47:12,485 INFO: Sondehub Amateur Uploader - Started Sondehub Amateur Uploader Thread.
2024-04-25 11:47:12,486 INFO: Using User Callsign: CHASEBOX
2024-04-25 11:47:12,484 INFO: Using User Callsign: CHASEBOX
2024-04-25 11:47:12,497 INFO: Started Horus Demod Uploader. Hit CTRL-C to exit.
2024-04-25 11:47:12,498 INFO: Started Horus Demod Uploader. Hit CTRL-C to exit.
2024-04-25 11:47:14,205 INFO: Sondehub Amateur Uploader - Uploaded station information to Sondehub.
2024-04-25 11:47:14,607 INFO: Sondehub Amateur Uploader - Uploaded station information to Sondehub.
2024-04-25 11:47:16,437 INFO: Received raw binary packet: <Removed>
2024-04-25 11:47:16,468 INFO: Decoded Binary Packet (SNR 14.3 dB): $$FLIGHTDESIGN2,52,02:17:11,-34.00000,138.00000,106,0,6,33,1.41,-0.01,0.0,0,0.0*9AC4
2024-04-25 11:47:18,110 INFO: Sondehub Amateur Uploader - Uploaded 1 telemetry packets to Sondehub Amateur in 1.5 seconds.You can then Ctrl-C this.
This should also upload telemetry which should be visible on the SondeHub-Amateur tracker, assuming your payload has GPS lock.
Refer horusdemodlib guide to startup using systemd here: https://github.com/projecthorus/horusdemodlib/wiki/1.2--Raspberry-Pi-'Headless'-RX-Guide#systemd-based-startup
Now, reboot (sudo reboot), then once rebooted, open up the ChaseMapper web interface and confirm you are receiving telemetry!
Once you know what wifi network you're going to run the RPi off on the day (e.g. some kind of 4G hotspot), you're going to need to setup the RPi to connect to this.
Under Bullseye adding another Wifi network is fairly easy. All we have to do is edit the /etc/wpa_supplicant/wpa_supplicant.conf file, e.g. sudo nano /etc/wpa_suplicant/wpa_supplicant.conf
Add a new section to the file like this:
network={
ssid="YourWifiSSID"
psk="yourwifipassword"
priority=2
}
A higher priority number makes your RPi preferentially connect to that network. Useful if you want to test connecting to a mobile hotspot while at home where your 'setup' network is still active!
Save and reboot for this to take effect.
Under Raspbian Bookworm, things have changed and we now have to deal with Network Manager...
If you can somehow get into your RPi via SSH (e.g. via ethernet), the you may be able to use the nmcli utility to connect
Otherwise, we're going to have to mess about with Network Manager configuration files.
Create a new wifi connection setting file: sudo nano /etc/NetworkManager/system-connections/wifi.nmconnection
[connection]
id=wifi
uuid=95b17351-297c-4d9c-90f9-669d3ab81464
type=wifi
autoconnect-priority=2
[wifi]
mode=infrastructure
ssid=YOUR_SSID_HERE
hidden=false
[ipv4]
method=auto
[ipv6]
addr-gen-mode=default
method=auto
[proxy]
[wifi-security]
key-mgmt=wpa-psk
psk=YOUR_PASSWORD_HERE
Note: The autoconnect-priority setting tells Network Manager to prefer this connection over the default connection you set up with RPi Imager. Higher number = higher priority, with the default value being 0.
This file then need to have its permissions modified for Network Manager to be happy with it:
sudo chmod -R 600 /etc/NetworkManager/system-connections/wifi.nmconnection
sudo chown -R root:root /etc/NetworkManager/system-connections/wifi.nmconnection
If you want to add multiple connection options, you can create multiple .nmconnection files. e.g. wifi2.nmconnection. You will also need to modify the id field in the file, and change the uuid to something unique (e.g. just bump the last character by one).
Reboot, and hopefully your RPi will jump onto the right network.
This issue has hit me a few times: https://github.com/raspberrypi/trixie-feedback/issues/99 Basically, after a random amount of reboots, the RPi doesn't connect to wifi anymore. Some issue during startup resulting in netplan profiles files getting truncated. Temp fix is to pull the microSD card, plug it into a computer, and edit the meta-data file on the bootfs partition. Change the 'instance-id' number, e.g:
instance-id: rpi-imager-1787362126833 <-- change this number
Plug the microSD card back in, and the Pi should go through a reboot and reconfiguration process, and end up back on the wifi network.
This script may help stop this happening: https://raw.githubusercontent.com/juchong/ThePilotChannel/refs/heads/main/deploy/harden-wifi.sh
- Turn on your tracking payloads a good 30 min before launch.
- Set the wind model downloading.
- Update the expected burst altitude and descent rate. This is important for accurate predictions during the ascent part of your flight.
- ~20-10 min before launch, check they are being received by your system and showing up on ChaseMapper.
- Check the SNR you are seeing off the payloads looks 'right'. If you're very near the payloads, then the SNR should be very high, like >20 dB.
- On the SondeHub-Amateur Tracker:
- Check your payloads are showing up.
- Check the number of satellites used in the position solution (Unfortunately you can't yet do this on ChaseMapper). Do the payloads have decent GPS lock?
- Just before launch, re-check you are receiving the payloads and that they have GPS lock still. Don't launch if the payloads don't have GPS lock!
- You can expect the receive SNR to drop down as the payloads go further away, and end up in negative numbers. You will probably see low SNR if you end up directly beneath the payload due to antenna pattern nulls.
- Keep an eye on the predicted landing location, and head that way ASAP!
- After balloon burst, the prediction will go a bit wild while the payloads are in their initial descent. This will stabilise after a few minutes.
- Keep following that predicted landing location! With luck you'll be in place to either watch the payloads land, or at least be close enough to get a telemetry position very close to the landing spot.
Core Electronics:
- GPS Receiver: https://core-electronics.com.au/usb-gps-receiver-2m-extension-cable.html
- Raspberry Pi 3 (Less RFI)
- Raspberry Pi 4 (More CPU, not really needed for Horus Binary):
Officeworks:
- SanDisk High Endurance microSD Card (64GB): https://www.officeworks.com.au/shop/officeworks/p/sandisk-64gb-high-endurance-microsdxc-memory-card-sdsqqnr64?scrollTop=false
- 32GB cards are fine too, get whatever is in stock.
RTLSDR Blog:
Amazon:
- Short USB3 Extension cable: https://www.amazon.com.au/tunghey-Extension-Material-Transfer-Compatible/dp/B0CR5T7KGK
- Short USB-MicroUSB cable (For Pi 3 power): https://www.amazon.com.au/GHNTJAP-Charging-Android-Charger-Compatible/dp/B0F4NDXDXR
- Short USB-USBC Cable (For Pi 4 Power): https://www.amazon.com.au/dp/B0DKJJ6Y68
Aliexpress:
- (Link to magmount antenna - these seem to keep changing)