WSPR monitoring node

What is this?

Instructions to build and operate an all-band WSPR node using cheap hardware and free software. At the end of this you'll have a Raspberry Pi, connected to an RTL-SDR dongle that monitors all of the WSPR frequencies rotating randomly every 15 minutes.

Last edited: 6 March 2019

How it works

Using the Linux based rtlsdr_wsprd software and an RTL-SDR dongle we monitor a particular frequency for a set period of time. The process is killed and restarted with a new frequency. Rinse and repeat.

The meat of the code uses the Linux "timeout" command which allows an executable to run for a set period of time after which it's killed.

We loop through a randomly shuffled list of frequencies, starting rtlsdr_wsprd with a different frequency every time.

This is set to loop forever.

while true ; do
  shuf frequencies | while read f ; do
    timeout 15m rtlsdr_wsprd $f


I used the following hardware to make this work:

  • Raspberry Pi 2 B+
  • RTL-SDR v3 dongle
  • TP-LINK TL-WR702N 150Mbps Wireless N Nano Router
  • 4 Gb MicroSD card


Installing software is not complicated, but there are several steps involved, which are documented below:

  • Install Linux and activate SSH, by copying a raspbian image onto an SD card and setting up SSH.
  • Configure Wi-Fi, this step is optional and only needed if your Pi has on-board Wi-Fi.
  • First Boot and Update OS, by powering up the Pi and running apt-get update.
  • Install WSPR software, by downloading the source and build dependencies.
  • Set-up RTL-SDR dongle, by ensuring that no spurious drivers are loaded by the kernel.
  • First Test
  • Create a simple WSPR monitoring script
  • Set-up OS to automatically start

Install Linux

The process to install Linux depends heavily on what other computing hardware you have. In my case I have an iMac that's running MacOS and Linux, so I'm able to use those tools. There are countless tutorials on the matter, but for me the actual steps were:

  • Download the OS image (Source:
  • Unzip that zip file
    • unzip
  • Find out which drive the MicroSD card is
    • diskutil list
  • Copy the disk image onto the correct drive
    • sudo dd bs=1m if=2018-11-13-raspbian-stretch-lite.img of=/dev/rdisk3 conv=sync && sync

Activate SSH

My Raspberry Pi is running headless, that means that it does not have a keyboard or a monitor attached. It's just the Pi, in a box, connected to the LAN, doing it's thing in the corner.

This means you need to be able to get to the Pi via some other means, SSH is the tool for the job.

The MicroSD card is still plugged into the Mac after installing the image and the Mac with automatically mount a volume called "boot". If you're using Windows or Linux, the same thing is true, though auto-mounting will depend on your own computer at that time, so you may need to eject and re-insert the MicroSD card before your computer "sees" it.

After that, create a file called "ssh" and eject the card.

On MacOS the step is:

  • touch /Volumes/boot/ssh

Configure Wi-Fi

Create a file in the boot directory called "wpa_supplicant.conf" with the following text, and make sure you replace the bits between the chevrons, the «your_ISO-3166-1_two-letter_country_code», «your_SSID» and «your_PSK» for your own network:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev


First Boot

DHCP is already on and configured on your Pi, and depending on your network, either Wi-Fi as indicated above, or Ethernet as in my case, you'll soon see a new device on your network called "raspberrypi.local".

You should see a reply when you ping the device:

  • ping raspberrypi.local

You should then be able to login to the device with ssh:

The default password is raspberry.

First thing to do is set a new password using the passwd command:

  • passwd

If you forget your password, you'll need to start again with re-imaging your Pi, because recovering a headless Pi is outside the scope of this document ;-)

Update OS

Even if you've downloaded the very latest image, it's likely that there are updates already available. It's a good idea to update your Pi as one of the first things you do and considering it's connected to the Internet 24/7 it's a solid idea to keep it up to date:

  • sudo apt-get update
  • sudo apt-get upgrade

Install WSPR software

We're going to use this as a WSPR monitoring node, but the same hardware can be used to monitor anything across the RF spectrum. For our purposes we really only care about WSPR and we'll install the tools and libraries needed to compile and install rtlsdr_wsprd:

  • cd ~
  • sudo apt-get -y install build-essential cmake libfftw3-dev curl libcurl4-gnutls-dev ntp libusb-1.0-0-dev librtlsdr-dev git screen
  • git clone
  • cd rtlsdr-wsprd/
  • make
  • sudo cp rtlsdr_wsprd /usr/local/bin

Set-up RTL-SDR dongle

If you have the dongle plugged in at this point, remove it first, wait 10 seconds, then continue with the information in this section - this will allow the Pi to unload any Kernel modules it decided were needed for your dongle.

Information about black listing is incomplete and I'm including it here because I did it, but I'm not (yet) convinced it's needed. I believe that it won't do any harm and it may prevent harm from occurring:

  • cd ~
  • cat > blacklist-rtl.conf
  • blacklist rtl8192cu
  • blacklist rtl8xxxu
  • blacklist dvb_usb_rtl28xxu
  • blacklist rtl2832
  • blacklist rtl2830
  • <Ctrl-D>
  • sudo mv blacklist-rtl.conf /etc/modprobe.d/

Now you can plug the RTL-SDR dongle in and all should be well with the world.

First Test

My Pi was using more power than the USB adaptor could supply so I turned off HDMI, which incidentally will also likely reduce the amount of interference generated by the Pi:

  • /opt/vc/bin/tvservice -o

Running rtlsdr-wsprd for the first time, making sure to replace «your_callsign» with your own callsign, and «your_locator» with your maidenhead locator:

  • rtlsdr_wsprd -f 14.0956M -c «your_callsign» -l «your_locator» -d 2 -S

Some things to note:

  • -d 2 is specific to the RTL-SDR v3 dongle and allows it to use the "Q" stream to decode HF frequencies. Note that -d 2 is likely to change to -d 0, for frequencies above 10m or so (hardware dependent, RTFM).
  • The frequency of 14.0956 MHz is chosen as a 20m WSPR starting point, there are currently 19 different frequencies across amateur bands, use the one appropriate to you and your antenna.

Create a simple WSPR monitoring script

We'll create three files that will be the backbone of your monitoring station:

  • ~/bin/start-wsprd - this will run the rtlsdr_wsprd command with the appropriate defaults for your station, making sure to replace «your_callsign» with your own callsign, and «your_locator» with your maidenhead locator
  • ~/bin/monitor-wspr - this will run start-wsprd forever, switching frequency every 15 minutes
  • ~/frequencies - this is the list of frequencies used to monitor WSPR, check the side-bar on for current frequencies

Each frequency is checked once - in random order - until all frequencies have been checked, then the process starts again. Each frequency takes at least 15 minutes (plus the synchronisation time for the next slot), so divide the number of frequencies you have by 4 and you'll get a rough idea how many hours it will take to check all the frequencies in your list.

In the sections below you'll find the content of each of the files described above. Installation instructions follow below.



# If you're running this somewhere else and logging it, knowing the time is helpful
date -R


# set a default frequency if we don't specify one, 20m WSPR

if [ $# -eq 0 ] ; then

# bash does not have floating point math, this if statement checks to see if
# our frequency is less than 28.8 MHz, so we have to use the "Q" stream, otherwise
# we can use the default for anything above 28.8 MHz

if [ "${freq}" = "$(echo -e "${freq}\n28.8" | sort -g | head -1)" ] ; then

rtlsdr_wsprd -f ${freq}M -c ${callsign} -l ${location} -S -a 1 -d ${stream}



while true ; do
  sudo /usr/bin/sntp -s
  shuf /home/pi/frequencies | while read freq ; do
  timeout -s ${killsignal} ${duration} /home/pi/bin/start-wsprd ${freq}




Create a bin directory for your scripts:

  • mkdir ~/bin

Move the two executable script into the bin directory:

  • mv start-wsprd ~/bin
  • mv monitor-wspr ~/bin
  • chmod +x ~/bin/start-wsprd
  • chmod +x ~/bin/monitor-wspr


Reminder that you'll need to make sure you replace the callsign and location variables in the start-wsprd script.

You can run the monitor-wspr script, but killing it can be challenging. A better option is to run screen first, then you can leave it running and kill it independently at a later stage:

  • cd ~
  • screen -L wsprd.log
  • monitor-wspr
  • <Ctrl-A>, <Ctrl-D>

At this point you'll be up and running. Killing it is a single command:

  • killall timeout monitor-wspr

You can disconnect from SSH and leave it running. It will keep running until the power fails. If you want to see what it's up to:

  • screen -r

At that point you'll be inside the screen session that is running the monitor-wspr script, and it will show the progress based on each individual launch of start-wsprd on a different frequency. <Ctrl-A>, <Ctrl-D> to exit.

You can also see what your node has found with:

  • grep 'Spot :' wsprd.log

Set-up OS to automatically start

The Pi has a mechanism using /etc/rc.local to run various tools during start-up. My Pi is set to turn off HDMI and synchronise the clock and then launch monitor-wspr inside a screen session.

My /etc/rc.local has the following content:

#!/bin/sh -e
# rc.local
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
# In order to enable or disable this script just change the execution
# bits.
# By default this script does nothing.

# Wait for a bit, we don't appear to get a DHCP lease immediately after booting
sleep 60

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"

# Turn off HDMI
/usr/bin/tvservice -o

# Sync the clock
/usr/bin/sntp -s

# Start WSPR as the user pi inside a screen called WSPR
cd /home/pi && /bin/su pi -c "/usr/bin/screen -L /home/pi/wsprd.log -dmS WSPR bash -c '/home/pi/bin/monitor-wspr'"

exit 0

If it doesn't work

It's possible that you did everything right and it's still not working. Make sure that each of the steps worked without any errors, changing a directory that wasn't there, or compiling something that didn't will cause this all to fail and you won't be able to make the magic happen:

  • Is the Pi actually getting an IP address?
    • ifconfig
  • Is there enough power getting to the Pi?
    • dmesg
  • Can you connect via SSH to something else?
  • Did you remember the right password (and was CAPS-LOCK where you thought it was)?
  • Did your Pi connect to the Internet correctly and could you update it?
    • ping
  • Did you install all the bits needed to make the compile work?
    • apt-get only runs as root, so make sure you used sudo.
    • apt-get install only works after an initial apt-get update,run that first. Also if you have not run that in a while, the index on the Pi is likely out of date.
  • Did you install the source code correctly?
    • git gets installed with the apt-get command, which is required to download the source for rtlsdr_wsprd.
  • Was the Dongle plugged in after updating the black list?
    • If you updated the black list, pull out the dongle, wait 10 seconds, then plug it back in.
  • Did you attempt to reboot the Pi?
    • sudo reboot
  • If you cannot run any scripts in the ~/bin directory
    • Did you log out and back in (the $PATH variable automatically includes ~/bin, but only when you start a new shell).
    • Did you chmod +x the file that you're trying to run?

If you did everything right and it's still not working, you need to figure out what broke:

  • I installed several other tools, the RTL-SDR suite is quite feature rich, comes with testing software and the like. These instructions will give you rtl_test which you can use to run rtl_test -t to see if your Pi can see your Dongle and rtl_test -p to measure the frequency offset.
  • Note that I didn't see ANY WSPR spots after doing this, so YMMV and it might kill a kitten or a pony, or both.
    • cd ~
    • git clone
    • cd rtl-sdr/
    • mkdir build
    • cd build
    • cmake ../ -DINSTALL_UDEV_RULES=ON
    • make
    • sudo make install
  • We installed ntp to keep the clock synchronised, but you might want to set the time explicitly first. You can set the clock using sntp which should already be installed:
    • sudo sntp -s

You can also install rtl_biast, which allows you to turn the bias on and off on the RTL-SDR v3 dongle - RTFM before you do this!:

To turn off the bias (the LD_LIBRARY_PATH is because Debian uses the same name for the packaged library):

  • LD_LIBRARY_PATH=/usr/local/lib rtl_biast -b 0

To turn it on:

  • LD_LIBRARY_PATH=/usr/local/lib rtl_biast -b 1