Remote ham radio operation through a Raspberry Pi

This post is about how I set up remote operation on my ham radio through a Wifi network, over a VPN, and around the world using a Raspberry Pi, like this:

radio-link-global

This could be useful for people who travel a lot and want to be able to use their rig while away. Or for people who want to set up their radio and antenna far away from where they actually live (e.g. apartment dwellers who have friends or parents who live in the boonies and wouldn’t mind you erecting an antenna). If you want to skip the VPN and just control your ham shack from your kitchen, that’s even easier.

I did this all with an ICOM-7100 all-mode radio, a Raspberry Pi B+, a Buffalo DD-WRT router/VPN server, and a laptop running Ubuntu 15.04. This post focuses on the radio control and networked audio but not on setting up the VPN.

Prerequisites

Setting up the Raspberry Pi

I want the RPi to be a “headless” remote server (no screen, no keyboard), so I need to be able to SSH into it from my client. This is pretty easy. I set up public/private keys so I don’t have to type a password every time I log in. Follow the link to set this up.

If you want your Raspberry Pi to work on wifi, you’ll have to set that up too.

Building PulseAudio 6.0 on the Raspberry Pi

We need to use the PulseAudio linux sound system to pipe audio through the network. PulseAudio 2.0 exists in the RPi repositories, but I had much better luck with a more recent version (PulseAudio 6.0), which I built from source. Following this guide, I got it to work (I skipped the bluetooth stuff). In summary, first install some build dependencies:

sudo apt-get install -y libltdl-dev libsamplerate0-dev libsndfile1-dev libglib2.0-dev libasound2-dev libavahi-client-dev libspeexdsp-dev liborc-0.4-dev libbluetooth-dev intltool libtdb-dev libssl-dev libudev-dev libjson0-dev bluez-firmware bluez-utils  libbluetooth-dev bluez-alsa libsbc-dev libcap-dev checkinstall

There’s a libjson-c dependency that I had to build myself:

git clone git://github.com/json-c/json-c.git
cd json-c
./autogen.sh 
./configure 
make
sudo make install

Clean pulse files that may be installed (note: this may break other installed packages like pygame)

sudo apt-get remove libpulse0

Now get the PulseAudio source code and compile. I used checkinstall so I could remove the built package easily later on.

git clone git://anongit.freedesktop.org/pulseaudio/pulseaudio
cd pulseaudio
./bootstrap.sh
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --disable-bluez4 --disable-rpath --with-module-dir=/usr/lib/pulse/modules
make
sudo checkinstall --pkgversion 6.0 --fstrans=no
sudo addgroup --system pulse
sudo adduser --system --ingroup pulse --home /var/run/pulse pulse
sudo addgroup --system pulse-access
sudo adduser pulse audio
sudo adduser root pulse-access

Then I built the init.d script as in the link above to get pulseaudio to auto-start in system mode (yes, it says this isn’t recommended, but it makes sense on a Raspberry Pi). Start PulseAudio by rebooting or just using

sudo service pulseaudio start

Configuring PulseAudio to pass sound from the Raspberry Pi through the network

On the Raspberry Pi, edit the `/etc/pulse/system.pa` file and uncomment or add a line to turn on module-native-protocol-tcp, authorizing the local network to communicate with it.

### Enable networked audio
load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;192.168.0.0/16

I also found it useful to comment out the module-suspend-on-idle line in there as it caused some 10 second lags at first.

Plug the radio into the Raspberry Pi and restart PulseAudio with:

sudo service pulseaudio restart

Configuring PulseAudio on the laptop/client

On Ubuntu, PulseAudio runs on a per-user basis, not in system mode. As such, we can turn on and off modules with scripts, which is just what we’ll do. Make a script and put commands like this in it:

#!/bin/sh

pactl load-module module-tunnel-source server=raspberrypi source_name=icom_source
pactl load-module module-tunnel-sink server=raspberrypi sink_name=icom_sink


# radio -> laptop speakers
pactl load-module module-loopback source=icom_source

# laptop microphone -> radio
pactl load-module module-loopback sink=icom_sink source=alsa_input.usb-0d8c_C-Media_USB_Audio_Device-00-Device.analog-mono

You will have to adjust the hostname of your Raspberry Pi (or just type in its IP address directly). You will also have to adjust the source of the second loopback module. I have it set to my USB microphone, but your laptop microphone will be different. Use the pacmd list-sources command to get a list of sources on your laptop and just take the name of the one you want. Make the script executable like this:

chmod +x radio_pulse.sh

You could also enable networking in this script, but I find it more convenient to use the paprefs program and just select “Make discoverable PulseAudio network sound devices available locally”.

Finally, you have to set up authentication. PulseAudio uses a shared secret called a cookie to authenticate. Copy the cookie from the RPi at /run/pulse/.config/pulse/cookie to ~/.pulse-cookie on your client computer (in the home directory). Now it will authenticate.

Restart PulseAudio on your client with

pulseaudio -k && sudo alsa force-reload

Now, run the script created above. If all goes well, you should now hear the sound from your radio on your laptop. You may have to make some adjustments in the pavucontrol program. Turn down the radio squelch so there’s something coming through and then, on the playback tab, select Show: All Streams and make sure the loopback from the Raspberry Pi is playing on the device you want it to be playing on. It should look like this:

pavucontrol_playbackYou can also run pavucontrol for the RPi from your client like this:

PULSE_SERVER=raspberrypi pavucontrol

And then you can adjust the connections on the RPi side of things if necessary. I don’t think you’ll have to do this.

If you’re using a IC-7100 too, make sure you have it set either to DATA mode (FM-D) or in such a way that the USB audio will make it into the transmitter. Now you can do voice and digital modes through your network! Cool. Here’s a screenshot of running fldigi on my laptop, receiving audio in this kind of a setup.

fldigi_through_rpi

Recall, at this point, we’re on a local network. We’d have to set up the VPN to go outside of our home through the internet.

radio-link-local

Controlling the Radio from afar

If you just want to do digital modes through fldigi, you’re probably good to go at this point. You can have flrig running on the Raspberry pi and fldigi running on the client, and they will be able to communicate and key up the radio and stuff. But I wanted to do voice as well. So what to do?

Well, being a programming nerd, I thought it’d be fun to write my own little controller for the IC-7100. I did this in Python. It’s hosted on github. So far, it’s exceedingly simple, but it allows me to turn the radio on and off, go to different memory channels, turn DATA mode on and off, and key up the radio. This is a good start, but I hope to make it much more sophisticated later. I especially need to be able to type in the frequency I want or scan up and down the bands for HF. This should be easy to add. If you want to use it, feel free. But don’t expect much. If you want to improve it, please do!

There are also other programs out there that offer the ability to control a radio through the network.

Troubleshooting

I gone through many iterations and come across many problems while figuring all this out. At first, I did the PulseAudio configurations on the RPi but I eventually decided doing it on the laptop was more flexible. I tried very hard to get downsampling to work to minimize the required bandwidth. This is important for slow wifi networks but especially important when going over the VPN to the internet. I played a lot with resampling methods and took it down to 11025 sample rate. It works and sounds fine for a while, but it kept fading out every few minutes. I haven’t quite solved this issue.

To downsample, change your tunnel source to be:

pactl load-module module-tunnel-source server=tau.partofthething source_name=icom_source rate=11025
pactl load-module module-tunnel-sink server=tau.partofthething sink_name=icom_sink rate=11025

This uses about 60 KiB/s over the network, as opposed to 200 KiB/s with the defaults.

To adjust the sampling methods, edit /etc/pulse/daemon.conf on the Raspberry Pi and change the resample-method = speex-float-1 setting.

In certain resampling conditions, PulseAudio uses too much of the RPi CPU.

The biggest problem is that over a VPN, there are a few seconds of delay as the audio travels through the internet.

If you’re experimenting with different settings, you can unload all the PA modules on your laptop with commands like

pacmd unload-module 32

Where 32 is the index of the module to unload. Use pacmd list-modules to list all loaded modules. I do this a bunch as I tweak my script and rerun it.

Securely connecting to the LAN from afar with a VPN

A VPN will let you securely connect to your local network through the internet as if you were sitting in your kitchen, even though you may be in Paris. This unlocks the potential of the remote radio-through-RPi thing, as it allows you to do it all from everywhere.

Conveniently, I already had a “road-warrior” OpenVPN set up on my WRT-based router. This means I can connect to my home LAN at anytime from anywhere securely. I do this to print stuff from afar, talk to my internal devices, and avoid surveillance while on public or other untrusted networks. This is a non-trivial step that involves getting a WRT-compatible router, flashing it with a ROM that has an OpenVPN server (like OpenWRT or DDWRT), building some public/private keys, and configuring the server and clients. It’s not THAT hard, but definitely took me a while to get it working due to the large number of slightly different instructions available online. The GUI-based config in recent DDWRT builds makes it pretty easy. Get started with this guide (slightly outdated) and build some RSA keys and flash your router. Then go to this other guide that’s very close to what I actually did. Go buy some wifi security cameras while you’re at it because you can now securely connect to them and watch your home while you’re away.

I hope this helps someone. It was a lot of fun for me to figure out.

73!

11 thoughts on “Remote ham radio operation through a Raspberry Pi”

  1. Have you had any issues with the number of the ttyUSB port incrementing if you lose connection? I haven’t tried using Linux and my IC-9100 (which I believe uses the same USB chips as the IC-7100) on OS-X increments the serial number every time the connection changes. It’s a problem with how the USB port driver works, so I imagine it’s just a problem with OS-X, but want to make sure.

    1. I noticed that as well on Linux. One thing you can do (at least on Linux, so you can probably do it on Mac as well) is make an alias for the IC-7100 that always gets a name. For instance, you could name it /dev/ic7100. See instructions here.

      My rule looks like this:

      SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", SYMLINK+="ic7100"

  2. This is awesome!
    I’ve just sold enough stuff to order a new IC-7100 (on sale under $800. via GigaParts this November).
    I’m planning an IF tap to feed a SDR into the PC in order to gain some features.
    This goes between the IF and the SDR – I will probably need to add a filter https://www.ebay.com/itm/DC-12V-10KHz-1GHz-10dBm-RF-Broadband-Low-Noise-Amplifier-LNA-Module-HF-VHF-UHF-/182183408801
    I’m really interested in remote operation from the EOC to test ARES setups – so your Raspi article was a timely find for me!
    I’ll be checking back for updates & will share the page.
    Thanks!

  3. I have been considering remotely operated radios for disaster areas. I have not personally worked a disaster area, but do not see the sense in adding an on-site ham operator, for each radio, to assist a person communicate out of the area.

    It seems to me that with the radios that take remote commands, an area could have only a couple hams on site consuming resources, and have a bunch of remote assist guys sitting at home while talking or messaging the people through the process of communicating with the outside world.

    Good ideas in this article.

  4. I’m encouraged by this.
    I would like to get a 7100 as my first HF rig and set up an SDR/panadapter. But mainly I am interested in Winlink for my local ARES. I could also afford running the radio from the shop, or placing the radio in the shop and running it from the house/desk-shack. This is helpful and right up my alley.

    Thanks

  5. This is awesome to read and to find! I have been doing reading and searching since I got my license last fall. I just ordered my first HF radio, 857D, for my truck. I’m in hopes of connecting it and using it with a RPi3 touch screen setup to enhance its abilities, and mine. Thanks for the extra reference! This does help to fill in a few blanks or holes in my plan.

  6. hi how are you
    i want to ask about the pins you used to connect the radio to Raspberry Pi
    please give me a picture to the pins in the radio and Raspberry Pi

Leave a Reply

Your email address will not be published. Required fields are marked *