Skip to content

Wenet RX Instructions (Linux using KA9Q‐Radio)

Andrew Koenig edited this page Oct 7, 2024 · 3 revisions

Last Updated: 2024-10-04

KA9Q-Radio is a very high performance multi-channel SDR server and demodulator, written by Phil Karn, KA9Q. Use of KA9Q-Radio allows multiple Wenet, horusdemodlib, and other receivers share a single SDR simultaneously as long as all transmitters are within the bandwidth of the receiver. In this document, KA9Q-Radio is configured to establish multiple receiver channels that output on unique multicast RTP streams.

This solution uses Docker, to avoid the need to build dependencies, and lets you get into receiving quickly. Docker Compose allows you to set up multiple receiver instances and define them in a single docker-compose.yml file.

A huge thanks to Steven Honson for setting up the Docker containers and making this all possible!

Please contact me at vk5qi (at) rfhead.net if you have any issues with these instructions.

1. Hardware Required

1.1. Receiver - SDR supported by KA9Q-Radio

Wenet requires an SDR that is supported by KA9Q-Radio to receive the transmitted signal, and of course some sort of antenna suited to the operating band (usually the 70cm amateur radio band).

As of October 2024, KA9Q-Radio supports the RTL-SDR, Airspy, FunCube Dongle, and the RX-888. Forks of KA9Q-Radio support the SDRplay series of radios.

We highly recommend the 'v3' rtl-sdr.com dongles.

1.2. Antenna

Wenet transmissions are usually found on the upper half of the amateur 70cm band, with the nominal frequency used in South Australia being 443.5 MHz, and 441.2 MHz in Victoria. Depending on your distance from the Wenet transmitter, you will need some antenna gain for reliable reception. For best reception, a 5-element yagi works well. These are available commercially from places like Arrow Antennas, or you could build one yourself out of tape measure and PVC pipe.

1.3. Preamplifier

To achieve best receive performance, a preamplifier should be used between the RTLSDR and the antenna, ideally as close to the antenna feed-point as possible. Examples of suitable amplifiers include:

The Wenet receiver software can be configured to enable the Bias-Tee on the RTLSDR to power some preamplifiers via the coax. (Note that the MiniKits preamps required 12v and cannot be powered this way).

1.4. Computer

Wenet reception with KA9Q-Radio has been successful using the following platforms:

  • Raspberry Pi 4 (single Wenet receiver)
  • Raspberry Pi 5 (multiple Wenet receivers, tested up to 4)
  • Various Intel i3 Laptop computers running Ubuntu Linux (18.04 or newer)

Any reasonably modern single-board computer (Pi 4 performance or better) should be able to handle Wenet reception, and most modern laptops (when running a Linux OS) should also work.

As the Wenet receiver interface is now browser-based, your Linux installation will also need a modern-ish web browser, such as Firefox or Chromium.

2. Software Dependencies

2.1. Installing Raspbian (RPi computers only)

If using a Raspberry Pi (4 or 5 recommended), I highly recommend installing Raspberry Pi OS using the Raspberry Pi Imager. This lets you pre-configure the OS with various settings. Some settings I recommend you change include:

  • Enable SSH and set a username and password.
  • Configure your WiFi details (note that if you are going to operate portable, you might need to set this to a mobile hotspot network!)

Use the "Raspberry Pi OS (64-bit)" or "Raspberry Pi OS Lite (64-bit)" (if only accessing the RPi via a network) versions. The latest Wenet images (as of 2024-10-04) have been confirmed to work on the latest Raspberry Pi OS version (Bookworm).

Once you've logged into the Pi for the first time (either via screen/keyboard/mouse or via SSH), ensure all your system packages are up to date by opening a terminal and running:

sudo apt-get update
sudo apt-get upgrade

2.2. Installing KA9Q-Radio

These instructions are based on: https://github.com/ka9q/ka9q-radio/blob/main/docs/INSTALL.md

Installation

Install the required libraries for KA9Q-Radio using apt:

sudo apt install avahi-utils build-essential make gcc libairspy-dev libairspyhf-dev libavahi-client-dev libbsd-dev libfftw3-dev libhackrf-dev libiniparser-dev libncurses5-dev libopus-dev librtlsdr-dev libusb-1.0-0-dev libusb-dev portaudio19-dev libasound2-dev uuid-dev rsync time

Clone the ka9q-radio repository, and checkout the latest known-working commit:

git clone https://github.com/ka9q/ka9q-radio.git
cd ka9q-radio
git checkout 26a8015
make -f Makefile.linux
sudo make -f Makefile.linux install

Wenet Modulation Preset

Add Wenet modulation scheme to: /usr/local/share/ka9q-radio/presets.conf

[wenet]
demod = linear
samprate = 921600
low =  -460800
high = +460800
stereo = yes
pll = no
shift = 0
envelope = no
conj = no
hang-time = 1.1
recovery-rate = 20

FFTW Wisdom file generation

(Reference: ka9q-radio/docs/FFTW3.md)

This needs to be run to ensure the FFT calculations used in ka9q-radio are run as optimally as possible.

This can take many hours to run, so set the fftwf-wisdom command going and come back in a few hours. On a RPi 5 this took 2 hours to run.

cd /etc/fftw/
sudo time fftwf-wisdom -v -T 1 -o nwisdom rof500000 cob2400 cob1250 cob1202 ob1200
ls -l nwisdom wisdomf
# check that nwisdom is larger than wisdomf
cp -i nwisdom wisdomf

Config file for Airspy R2

A radiod@.conf file configures the KA9Q-Radio software. The @ in the filename and subsequent text allows systemd to configure multiple radiod instances with a single service file.

The specifics of the config file are documented in the KA9Q-Radio respository.

Unlike radiosonde_auto_rx, we must configure each receiver in the radiod@.conf file before starting radiod. When running multiple Wenet receivers on the primary sonde-pcm.local stream, significant packet loss was reported by pcmcat. To avoid overloading pcmcat, we can define unique receivers (which yield unique RTP streams) in the radiod@.conf file.

Make a new file: /etc/radio/radiod@airspy-sonde-vk5qi.conf

Containing:

[global]
hardware = airspy
mode = fm
status = sonde.local
ttl = 0 # This needs to be 0 else traffic will 'escape' into your network, potentially causing issues.
data = sonde-pcm.local

[airspy]
device = airspy
description = "Radiosonde RX"
# Need to check what settings below we need.
#serial =
#samprate = 20000000
#converter = 0
#calibrate = 0
#linearity = false
#lna-agc = false
#mixer-agc = false
#lna-gain =
#mixer-gain =
#vga-gain =
#gainstep =
#bias = false
#agc-high-threshold = -10
#agc-low-threshold = -40
#frequency = 149000000
# Frequency should be set ~600 kHz higher than the highest frequency you want to receive.
# For an Airspy R2 running at full sample rate, set this to 407m0 to cover 400-406 MHz.
frequency = 407m0 ; lock to radio sonde band (front end is a downmixer)

[wenet-1]
# Mode (as defined in /usr/lib/)
mode = wenet
data = wenet-1-pcm.local
# USB RX Frequency for Wenet FSK receiver is determined by this equation:
# TX_FREQ - BAUD_RATE * (OVERSAMPLING/4 - 0.25) -- rounded to nearest integer
# example: 443.5 MHz @ 115200 baud with 8x oversampling:
# 443500000 - 115200 * (8/4 - 0.25)
# 443500000 - 201600 (use 201600 as an offset if maintaining 115.2kbaud @ 8x oversampling)
freq = 443298400

#[wenet-2]
#mode = wenet
#data = wenet-2-pcm.local
#freq = 431548400

#[horus]
#mode = horus
#data = horus-pcm.local
#freq = "432605000 432610000 432615000 432620000 432625000 432630000 432635000 432640000"

Enable using:

sudo systemctl enable --now radiod@airspy-sonde-vk5qi
sudo systemctl start radiod@airspy-sonde-vk5qi

It should be possible to check if it's running using:

control sonde.local

It'll probably ask you for a SSRC (channel ID -- this defaults to the frequency, such as 443298400).

Additional FFT Optimizations

Additional optimizations may need to be created if a sample rate was used that was not covered by this baseline. Check the logs with journalctl -u radiod after the radiod service is running and verified.

Log entry suggesting more optimizations may help:

suggest running "fftwf-wisdom -v -T 1 -w /var/lib/ka9q-radio/wisdom -o /tmp/wisdomf cof200000", then "mv /tmp/wisdomf /etc/fftw/wisdomf" *if* larger than current file. This will take time.

Running the fftwf-wisdom command as written in the log entry is preferred. It should factor in any prior optimizations in /etc/fftw/wisdomf. However you should verify the new optmization file is larger than the old file (ls -l /tmp/wisdomf and ls -l /etc/fftw/wisdomf) before moving the new file. sudo may be required to move the new file.

2.3. Installing Docker

It is highly recommended that you use the latest version of Docker, rather than the one available from your systems default package repositories. If you already have Docker installed, then hopefully you already know what you're doing here!

A quick way to install the latest version of Docker is by using the convenience script:

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

If you see errors along the lines of "InRelease' changed its 'Suite' value from 'stable' to 'oldstable'", then you are likely running an out-of-date version of Raspbian. You can temporarily get around this error by running the command:

sudo apt update --allow-releaseinfo-change

To be able to run docker commands as your non-root user (recommended), run:

sudo usermod -aG docker $(whoami)

You will need to logout and log back in afterwards to pick up the changes to group membership (you can check this by running groups).

2.3. Testing the Docker Install

After logging out and back in, test that docker is available by running:

docker version

This should return something along the lines of:

Client: Docker Engine - Community
 Version:           20.10.14
 API version:       1.41
 ... more lines here ...
Server: Docker Engine - Community
 Engine:
  Version:          20.10.14
  API version:      1.41 (minimum version 1.12)
  ... more lines here ...

If you don't see the server section then you likely haven't give your user the correct permissions (see above).

2.4. RTL-SDR Kernel Blacklisting

If using an RTL-SDR, the RTL DVB kernel modules must first be blacklisted on the Docker host. RTL-SDR itself is not required on the Docker host. This can be accomplished using the following commands:

echo 'blacklist dvb_usb_rtl28xxu' | sudo tee /etc/modprobe.d/blacklist-dvb_usb_rtl28xxu.conf
sudo modprobe -r dvb_usb_rtl28xxu

If the modprobe -r command errors, a reboot may be required to unload the module.

At this point it's recommended to disconnect and re-connect your RTLSDR, if it's already plugged in.

3. Configuring and Starting up the Docker Image

3.1. Configuring

We will make a directory to store a startup script, and to save received images to:

mkdir -p ~/wenet/rx_images
cd ~/wenet/
curl -o docker-compose.yml https://raw.githubusercontent.com/projecthorus/wenet/master/docker-compose.yml

Modify the docker-compose.yml file and update the fields within as appropriate. At the very least ensure you update your callsign!

You may also need to adjust the receive frequency depending on the launch you are receiving.

3.2. Startup

With radiod running, from within the wenet directory, run the image by running:

docker compose up

The first time this is run, it will download the required docker images, this may take a few minutes.

You can check the status of the container by checking the logs:

docker compose logs --tail 50 --follow

This will usually show a lot of debug information, which may be a bit hard to interpret!

3.3. Viewing the Web Interface

Open a web browser and navigate to: http://localhost:5003/

If all is working, this should show the Wenet web interface. The SNR value in the top-right corner should update even if only noise is being received (values of 3-4 dB are normal when receiving nothing). SNR values of >10dB are required for reliable reception of packets. Abnormally high values (e.g. >25 dB) may indicate you have a strong local interferer which the receiver is latching onto.

The main image display in the centre of the page will update as image packets are received. At the bottom of the page is further information on the image being received, and the status of packet uploads to ssdv.habhub.org. Also visible at the bottom of the page is the 'debug log' from the payload, showing the status of image capture and processing.

3.4. Accessing Received Images

To see live image data received by all the receivers of a flight, visit https://ssdv.habhub.org/

Images received by just your station are available in the wenet/rx_images directory.

3.5. Stopping / Restarting

The container can be stopped by running:

$ docker compose down

To restart the container (for example, if you changed a setting in docker-compose.yml, just re-run docker compose up -d.

3.6. Updating

Updating the docker image can be accomplished by running:

$ docker pull ghcr.io/projecthorus/wenet:latest

You must then restart the container.

TODO: is this section correct? compose may not need it.

3.7. Starting Automatically on Boot

To make Wenet start automatically on boot, add the line restart: "always" to docker-compose.yml, e.g.:

services:
  wenet-1:
    restart: "always"
    environment:
      MYCALL: "CHANGEME"
      RXFREQ: "443500000"
      SDR_TYPE: "KA9Q"
      DEVICE: "wenet-1-pcm.local"
      GAIN: "0"
      BIAS: "0"
      BAUD_RATE: "115177"
      OVERSAMPLING: "8"
      IMAGE_PORT: "7890"
      WEB_PORT: "5003"
    volumes:
      - ~/wenet/rx_images/:/opt/wenet/rx_images/
      - /var/run/dbus:/var/run/dbus
      - /var/run/avahi-daemon/socket:/var/run/avahi-daemon/socket
    image: wenet
    network_mode: "host"

After you re-run docker compose up -d again, this will result in the wenet decoder starting on system boot.