From c2ca5b179e66c36aa92d9fe4790fa75c7f9f9262 Mon Sep 17 00:00:00 2001 From: Mark Jessop Date: Wed, 27 Aug 2025 14:54:08 +0930 Subject: [PATCH] Bump version, update readme, modify start_tx to use I2S --- README.md | 7 ++- rx/WenetPackets.py | 2 +- start_tx.sh | 20 ++----- start_tx_uart.sh | 139 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 150 insertions(+), 18 deletions(-) create mode 100755 start_tx_uart.sh diff --git a/README.md b/README.md index e850b50..755377a 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,11 @@ Transmit and Receive code for the Project Horus High-Speed Imagery Payload - 'We The above image was captured on Horus 42, and downlinked via Wenet. The original downlinked resolution was 1920x1440, and has since been re-sized. The full resolution version is available here: http://rfhead.net/temp/horus_42_full.jpg ## What is it? -Wenet is a radio modem designed to downlink imagery from High-Altitude Balloon launches. It uses Frequency-Shift-Keying (FSK) at a rate of ~115kbit/s, and uses LDPC forward-error-correction to provide 6 dB of coding gain. +Wenet is a radio modem designed to downlink imagery from High-Altitude Balloon launches. It uses Frequency-Shift-Keying (FSK) at a rate of ~96 kbit/s, and uses LDPC forward-error-correction to provide 6 dB of coding gain. -The transmit side is designed to run on a Raspberry Pi, and the UART is used to modulate a HopeRF RFM98W in direct-asynchronous FSK mode. We usually operate in the quieter 440-450 MHz portion of the amateur 70cm band, with our nominal frequency being 443.5 MHz. Due to the non-ideal filtering in the transmitter module the [occupied bandwidth](https://github.com/projecthorus/wenet/raw/master/doc/occupied_bw.png) is ~300 kHz, so Wenet is not suitable for operation in the 434 MHz ISM band. The usual [transmit power](https://raw.githubusercontent.com/projecthorus/wenet/master/doc/tx_power.png) we use is 50mW, into an inverted 1/4-wave monopole underneath the payload. Details on the modulation and packet formats are [available here](https://github.com/projecthorus/wenet/wiki/Modem-&-Packet-Format-Details). +The transmit side is designed to run on a Raspberry Pi, and the latest 'Wenet v2' mode uses the I2S peripheral to modulate a HopeRF RFM98W in direct-asynchronous FSK mode. The 'legacy' Wenet mode used the UART to modulate the radio, which resulted in a 20% overhead from RS232 framing. + +We usually operate in the quieter 440-450 MHz portion of the amateur 70cm band, with our nominal frequency being 443.5 MHz. Due to the non-ideal filtering in the transmitter module the [occupied bandwidth](https://github.com/projecthorus/wenet/raw/master/doc/occupied_bw.png) is ~200 kHz, so Wenet is not suitable for operation in the 434 MHz ISM band. The usual [transmit power](https://raw.githubusercontent.com/projecthorus/wenet/master/doc/tx_power.png) we use is 50mW, into an inverted 1/4-wave monopole underneath the payload. Details on the modulation and packet formats are [available here](https://github.com/projecthorus/wenet/wiki/Modem-&-Packet-Format-Details). The receiver side makes used of Software Defined Radio (in particular, RTLSDR dongles), and a high performance FSK modem written by [David Rowe](http://rowetel.com/). Received images are available locally via a web interface, and are also uploaded to https://ssdv.habhub.org/ where packets contributed by many stations can be used to form a complete image live during a flight. @@ -28,6 +30,7 @@ Bench [testing](https://www.rowetel.com/?p=5080) has shown that for a receiver w * v1.0 - Docker image released, documentation updated. * v1.2 - Switched to the libcamera2 library, support for PiCam v3, and many additions to downlink telemetry. * v1.2.1 - Further optimizations for the PiCam v3. Flown on [Horus 63](https://www.areg.org.au/archives/212110). +* v2.0 - Added Wenet v2 mode, using I2S modulation for less overhead. Flown on [Horus 64B](https://www.areg.org.au/archives/212276). ## How do I Receive it? You can receive Wenet transmissions using a Linux computer, a RTLSDR, and a small yagi antenna (sometimes a vertical can work too). You can find a guide on how to get setup to receive imagery here: https://github.com/projecthorus/wenet/wiki/Wenet-RX-Instructions-(Linux-using-Docker) diff --git a/rx/WenetPackets.py b/rx/WenetPackets.py index 8514c52..3cf7143 100644 --- a/rx/WenetPackets.py +++ b/rx/WenetPackets.py @@ -19,7 +19,7 @@ from base64 import b64encode # Check if we are running in Python 2 or 3 PY3 = sys.version_info[0] == 3 -WENET_VERSION = "1.2.1" +WENET_VERSION = "2.0.0" WENET_IMAGE_UDP_PORT = 7890 WENET_TELEMETRY_UDP_PORT = 55672 diff --git a/start_tx.sh b/start_tx.sh index 87de3d3..5d61167 100755 --- a/start_tx.sh +++ b/start_tx.sh @@ -1,12 +1,11 @@ #!/bin/bash # -# Wenet TX-side Initialisation Script -# 2024-09-14 Mark Jessop +# Wenet TX-side Initialisation Script - Wenet v2 (I2S) Modulation +# 2025-08-27 Mark Jessop # # Run this to set up an attached RFM98W and start transmitting! # Replace the transmit frequency and callsign with your own. # -# # A callsign which will be included in the Wenet Packets. # This MUST be <= 6 characters long. @@ -42,24 +41,16 @@ EXPOSURE=0.0 # Refer near the end of this file for image flipping and overlay options # Baud Rate -# Known working transmit baud rates are 115200 (the preferred default). +# Only 96000 baud is known working in I2S mode # Lower baud rates *may* work, but will need a lot of testing on the receiver # chain to be sure they perform correctly. -BAUDRATE=115200 +BAUDRATE=96000 # RFM98W SPI Device # SPI device number of your RFM98W chip # This will either be 0 or 1 on a RPi. SPIDEVICE=0 -# Modulation UART -# The UART used to modulate the RFM98W with our Wenet transmission -# We want to be using the PL011 UART, *not* the Mini-UART -# On a Pi Zero W, you may need to disable bluetooth. See here for more info: -# https://www.raspberrypi.com/documentation/computers/configuration.html#uarts-and-device-tree -SERIALPORT=/dev/ttyAMA0 - - # CHANGE THE FOLLOWING LINE TO REFLECT THE ACTUAL PATH TO THE TX FOLDER. # i.e. it may be /home/username/dev/wenet/tx/ cd /home/pi/wenet/tx/ @@ -126,10 +117,9 @@ sleep 10 # --use_focus_fom python3 tx_picamera2_gps.py \ - --rfm98w $SPIDEVICE \ + --rfm98w-i2s $SPIDEVICE \ --baudrate $BAUDRATE \ --frequency $TXFREQ \ - --serial_port $SERIALPORT \ --tx_power $TXPOWER \ --gps $GPSPORT \ --gpsbaud $GPSBAUD \ diff --git a/start_tx_uart.sh b/start_tx_uart.sh new file mode 100755 index 0000000..1ba7cc9 --- /dev/null +++ b/start_tx_uart.sh @@ -0,0 +1,139 @@ +#!/bin/bash +# +# Wenet TX-side Initialisation Script - Legacy UART Modulation +# 2025-08-27 Mark Jessop +# +# Run this to set up an attached RFM98W and start transmitting! +# Replace the transmit frequency and callsign with your own. +# +# + +# A callsign which will be included in the Wenet Packets. +# This MUST be <= 6 characters long. +MYCALL=N0CALL + +# The centre frequency of the Wenet transmission, in MHz. +TXFREQ=443.500 + +# Transmit power, in dBm +# Allowed values are from 2 through 17 dBm. +TXPOWER=17 + +# GPS Port and baud rate +# Note that we only support uBlox GPS units +# set this to none to disable GPS support +GPSPORT=/dev/ttyACM0 +GPSBAUD=115200 + +# Image settings +# Image scaling - Scale the 'native' image resolution of the attached camera by this much +# before transmitting. +TX_IMAGE_SCALING=0.5 + +# White Balance settings +# Allowed Values: Auto, Daylight, Cloudy, Incandescent, Tungesten, Fluorescent, Indoor +WHITEBALANCE=Auto + +# Exposure compensation +# Allowed values: -8.0 to 8.0 +# You may wish to adjust this to bump up the exposure a little. +EXPOSURE=0.0 + +# Refer near the end of this file for image flipping and overlay options + +# Baud Rate +# Known working transmit baud rates are 115200 (the preferred default). +# Lower baud rates *may* work, but will need a lot of testing on the receiver +# chain to be sure they perform correctly. +BAUDRATE=115200 + +# RFM98W SPI Device +# SPI device number of your RFM98W chip +# This will either be 0 or 1 on a RPi. +SPIDEVICE=0 + +# Modulation UART +# The UART used to modulate the RFM98W with our Wenet transmission +# We want to be using the PL011 UART, *not* the Mini-UART +# On a Pi Zero W, you may need to disable bluetooth. See here for more info: +# https://www.raspberrypi.com/documentation/computers/configuration.html#uarts-and-device-tree +SERIALPORT=/dev/ttyAMA0 + + +# CHANGE THE FOLLOWING LINE TO REFLECT THE ACTUAL PATH TO THE TX FOLDER. +# i.e. it may be /home/username/dev/wenet/tx/ +cd /home/pi/wenet/tx/ + +# Wait here until the SPI devices are available. +# This can take a few tens of seconds after boot. +timeout=20 +echo "Checking that the SPI devices exist..." +while : ; do + [[ -e "/dev/spidev0.0" ]] && break + + if [ "$timeout" == 0 ]; then + echo "Did not find SPI device in timeout period!" + exit 1 + # At this point this script exits, and systemd should restart us anyway. + fi + + echo "Waiting another 2 seconds for SPI to be available." + sleep 2 + ((timeout--)) +done + +echo "Waiting another 10 seconds before startup." +sleep 10 + +# OPTIONAL - Wait for the GNSS receiver to obtain lock before starting up the camera and transmitter. +# This may help with getting first GNSS lock after boot. +# --waitforlock 10 Wait for up to 10 minutes before timing out and continuing anyway +# --lockcount 60 Wait for 60 sequential valid 3D fixed before exiting (2 Hz update rate, so 60 -> 30 seconds) +# --locksats 6 Only consider a fix as valid if it has more than 6 SVs in use. +#python3 ublox.py --waitforlock 10 --lockcount 60 --locksats 6 --baudrate $GPSBAUD $GPSPORT + + +# Start the main TX Script. +# +# Additional configuration lines you may wish to add or remove before the $CALLSIGN line may include: +# Flip the image vertically and horizontally (e.g. if the camera is mounted upside down) +# --vflip --hflip \ +# +# Add a logo overlay in the bottom right of the image. This must be a transparent PNG file. +# --logo yourlogo.png \ +# +# Set a fixed focus position on a PiCam v3 (NOTE: The Picamv3 focus drifts with temperature - beware!!!) +# 0.0 = Infinity +# --lensposition 0.0 \ +# +# Set a user-defined AutoFocus Window Area, for use wiith PiCam v3 in Autofocus Mode +# Must be provided as x,y,w,h , with all values between 0-1.0, where: +# x: Starting X position of rectangle within frame, as fraction of frame width +# y: Starting Y position of rectangle within frame, as fraction of frame height +# w: Width of rectangle, as fraction of frame width +# h: Height of rectangle, as fraction of frame height +# e.g: +# --afwindow 0.25,0.25,0.5,0.5 \ +# +# Set a custom focus mapping range for the PiCam v3, which maps the autofocus range to a lens position. +# This can be used to constrain the autofocus range, or even completely unlock it to the full lens travel. +# e.g., for full lens travel, use: +# --afcustommap 0.0,0.0,15.0,1024.0 \ +# +# +# Use the Focus Figure-of-merit metadata to select the transmitted image, instead of selecting on file size +# Only useful for lenses with autofocus (PiCam v3) +# --use_focus_fom + +python3 tx_picamera2_gps.py \ + --rfm98w $SPIDEVICE \ + --baudrate $BAUDRATE \ + --frequency $TXFREQ \ + --serial_port $SERIALPORT \ + --tx_power $TXPOWER \ + --gps $GPSPORT \ + --gpsbaud $GPSBAUD \ + --resize $TX_IMAGE_SCALING \ + --whitebalance $WHITEBALANCE \ + --exposure $EXPOSURE \ + $MYCALL