Netpirate: Morse code over Pirate Radio using Raspberry Pi/BalenaFin (WIP)


Is my attempt at sending ip packets using morse code over a pirate radio using a raspberry pi and a wire!

Note under active development 20220317

Last update:

20220321 - adding api server, created a kanban board for people to see project status here
20220324 - added status video

Status Update Video Demo

Status Update v2

first successful transmission of morse code over fm radio!


The hardware

  • Raspberry pi (or BalenaFin :wink:))
  • Jumper wire standard size OR 75cm of wire
  • Free Time ( Really hard to source due to international chip shortage)

plug the jumper wire into pin 4 on the raspberry pi (or balenafin in my case)

where the arrow is pointing

Finished Hardware setup!

Note: im using a common jumper wire because its easy to find, but bear in mind that this will have reduced performace vs a 75 cm wire, if you really want long range (not recommended due to fcc will not like you) you can go with a longer range.

Connect your RPI (or Balena fin) to network and power

Software used rpitx which is an alterative to the now dead pifm

Download and flash the code to the pi

this tutorial assumes you aready have a account with BalenaCloud

If not signup here ------v

Go to your dashboard balena dashboard

create a fleet

name it whatever you want, and select your board for me its BalenaFin

what i put for my balena fin

what you might put for rpi 4

add a device

Select development, if you want to modify and play around with the code, if you just want to use the project select production

read the instructions

make sure the power is connected

Noob mistake: I made the mistake of thinking the USB could power the device on its own, and had to do some trouble shooting. takeaway, make sure the powerjack and the USB are plugged in at the same time.

Plug the USB cable into the PRG port, and the other end into you computer

download BalenaEtcher from here

once installed click flash

Issue I ran into, the balenafin wasn’t showing up

things to try

or try look at BalenaFin troubleshooting for more answers, if the above didn’t work

Found the issue! bad cable had to try 3 cables until i found one that worked

Not all usb cables are created equal! just because i through it was a data one didnt mean it actually was! good to know…

Now on to flashing!

Issue #2 missing drivers

Download and install this driver


note i had to unplug my fin before the driver would finish installing, but everything worked fin after that

YAY drivers installed!

Woop woop!

all the binking things means good things

Issue: my fin didnt popup :confused:

things I tired

found the issue, i didnt have the ethernate cable plugged in correctly!

from the docs

A pattern of 4-blinks on the ACT status LED indicates that the balenaFin cannot connect to a network

video of what the 4 blinks looked like

here’s what it should look like

Success! :partying_face::partying_face::partying_face::dancer::women_with_bunny_ears:

Now lets add the project’s code to my pi/balena fin

Build log

I started out using F5OEO/rpitx: RF transmitter for Raspberry Pi which seemed like the way to go, it has alot of advanced features.

but I was running into alot of errors, and finally got it installed but commands run with no output! really confusing, and frustrating

Lets try another software package


Advanced Raspberry Pi FM transmitter with RDS encoding

my goal is to convert this install script into a docker file

here’s my first attempt at it.

FROM balenalib/rpi-raspbian:latest

WORKDIR /usr/src/app
RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -y git cmake build-essential libgtk-3-dev libsdl2-dev zlib1g-dev liblua5.3-dev libgif-dev libsndfile1-dev  libsoxr-dev
RUN git clone
WORKDIR /usr/src/app/PiFmAdv/src
RUN make clean
RUN make
COPY . ./
CMD ["/bin/sh", "./pi_fm_adv"]

first error

pirateradio ./pi_fm_adv: 1: Syntax error: word unexpected (expecting ")")

attempt #2

seems promising


lets see what happens when i run /bin/sh ./pi_fm_adv

darn! same issue… from google it says this might be a archeticture build issue

running ./pi_fm_adv --audio sound.wav

oops missing sound.wav file, wait no, still event if i provide correct filename

going to try privileged: true in the docker file

from google says it might help.

Failed to open /dev/mem, try checking permissions. - Forum - Raspberry Pi - element14 Community

version: '2'
    build: ./pirateradio
      - "80"
->privileged: true

lets give that a try

./pi_fm_adv --audio sound_22050.wav


looks like i neeed to adjust the default fequency

./pi_fm_adv --audio sound_22050.wav --freq 90.6

turns out 90.6 doesnt pop up on the car radio :confused:

./pi_fm_adv --audio sound_22050.wav --freq 90.5

well its something, but its not great. im going to try another sound track from

wise · radio sound failed attempt

attempt with new sound file

./pi_fm_adv --audio sound2.wav --freq 90.7
nope. :confused: somethings up. i think its
a) wiring
b) configuration of the program
c) adjusting the gpu_freq

after some fiddling im starting to think its the gpu_freq

found this article on setting /mnt/boot/config.txt but doesnt say anything about gpu_freq Advanced boot settings - Balena Documentation

Raspberry Pi Documentation - The config.txt file

looks like i can edit the config.txt after boot.

Advanced boot settings - Balena Documentation

Key: gpu_freqBALENA_HOST_CONFIG_gpu_freq
Value: 250

the fin rebooted automatically

lets try it again

./pi_fm_adv --audio sound2.wav --freq 90.7


wise · successful transimition

adding api server

which sends data to the api endpoint /v1/morse to be piped to a filepipe that will send that audio data out the fm transmitter code

getting minimul api up and running

first succesfull build

turns out the flask_restx flask server doesnt allow outside hosts

should be a simple fix

from                debug=True, port=7878)
to'', debug=True, port=7878)

try number #2

nope. something else is going on

possible issues:

  • computer is on a different subnet
  • port 80/7878 are not exposed to outside world
  • maybe i dont understand‘’…) and it doesnt actually allow outside connections

lets see if its the port issue

from this stackoverflow makes me think: hmmmmm
What is the difference between docker-compose ports vs expose - Stack Overflow
going to try this
yeah i think its a port vs expose docker issue

lets see if that worked


sharing a filepipe for audio across two containers

the shared_pipe is a data volume shared across two containers
heres how i map the shared folder

testing to see if that the pipe works

connecting to into fm radio’s container

good news the shared folder named ‘public’ is present

creating a file to see if it shows up on both sides

loggining into the api container the file audio.wav is present! woop woop!

dockerizing a cool tool that does most of what I want. called cwwav which takes stdin text and outputs a .wav file containing the beeps and boops of morse code.

note: CW is another way of saying morse code

getting cwwave to install in docker was a royal pain.

what I did

  • change base image from balenalib/rpi-raspbian:latest to -balenalib/-python:3-stretch-run because the install script required python3
turns out the issue with my dockerized cwwav program was that it didnt have anything to do after being built. so it would eminently quit. this is not good for testing because i cant ssh into it. :confused:

so i am breaking the problem down into smaller chunks.

here i’m converting text into morse code audio file

issues installing.

these errors say to me that the data volume ‘shared_pipe’ is not mounted until when building the container

got that issue solved.

first successful manually triggered transmission of morse code over fm radio!

first automated transmition!

raw text → morse audio → fm radio!

complicated but working!

/bin/sh -c " find . -name 'morse_data.txt' | entr -r cwwav -f 400 -w 20 -o /usr/src/app/PiFmAdv/src/public/hello_world.wav /usr/src/app/PiFmAdv/src/public/morse_data.txt & /usr/src/app/PiFmAdv/src/pi_fm_adv --freq 90.7 --audio /usr/src/app/PiFmAdv/src/public/hello_world.wav"

this is two containers talking through one another using a file called morse_data.txt which is the message getting broadcast out the radio on repeat

im using a cool command called entr which watches for file changes within a directory and runs a command.

the command i run does two things.

- cwwav creates a audio file from the text within the morse_data.txt, the audio file is named hello_world.wav

- pi_fm_adv is the radio tranmitter code, and reads the file called hello_world.wav and sends it over fm radio!

pictured here is the interaction between the two docker containers. the interupted pattern is when data is written to morse_data.txt. the api will eventurally write to that file as a means to send fm morse code. cool right?

Got api working! no can update message being sent via api!

Decoded message!

still has some minor issues with encoding.

after some more investigating its not a encoding error something else is going wrong

errors and fixes:

ERROR: Could not allocate memory.

fix: just reboot your device. that fixed it for me.

I added the feature where you can configure the radio station frequency by using some environment variables (device variables in balena speak)

more information about setting env variables Variables - Balena Documentation

getting some errors when i restart the fm radio execuritable

It might be a issue where the PiFmAdv doesnt exit properily and locks the system in a weird state of limbo. the result is the fm fm radio exe doesnt restart but gives off ERROR: Could not allocate memory. error

im going to give PiFmAdv --wait 0 (instead of --wait 1 the default) a try which according to the docs

--wait specifies whether PiFmAdv should wait for the the audio pipe or terminate as soon as there is no audio. It's set to 1 by default.

I think i figured out the issue with i was running into with the ERROR: Could not allocate memory. error. there was two copies of PiFmAdv trying to run at the same time, which caused the error.

I’m experimenting with converting the file from write file read file, to pipes as recommended by @ramirogm

Also a suggestion by @ramirogm was to give local mode a shot! it was taking 5 mins to make just 1 change to populate on my device

Develop locally - Balena Documentation

note all the pushes wont be shown in balena dashboard

When trying to use localmode on windows 11 I ran into a issue.

balena scan requires admin

fix: run powershell as admin✅

Missing Bonjour service

fix: install from here Download Bonjour Print Services for Windows v2.0.2

fix works!

PS local mode has livepush mode! with does heavy caching and auto reloads stuff! nice!

Challenages trying to convert my shell script that runs the translation from files to filepipes.

according to brave search .wav does not support file pipes! darn.
c - Audio file format that can be written without seeking - Stack Overflow
but this post does say that au is supported

ended up abandoning the full pipe method and im now giving a while loop a try

More updates to come!

  • Still working on getting morse to work. should be out soon!


- oran#


What sort of range comes from that antenna?