Building a reliable WSPR decoder on a headless Raspberry Pi (no GUI)
Version info31/03/2013 - Fixed typo in configure statement --with-portaudio-lib-dir=/usr/lib/arm-linux-gnueabihf, changed from rrm-linux-gnueabihf to arm-linux-gnueabihf (thanks to JonOve LA3JJ for pointing this out)
7/4/2013 - Added frequency hopping howto, formatting cleaned up to improve readability
12/4/2013 - Added some additional info on hopping.ini
The Hardware
Raspberry Pi Model B (rev 2) with 512 MB of RAMDisk media is an 8 GB SDHC card, I use class 10 cards for faster disk IO performance
Successfully tested USB sound cards - Signalink USB & Terratec 5.1 USB
Download and install Raspbian Wheezy from http://www.raspberrypi.org/downloads
Once installed connect via ssh and perform the following changes with raspi-config
pi@raspberrypi ~ $ sudo raspi-config
- Change the default password from raspberrypi to something more secure
- Update raspi-config
- Expand the rootfs
- Set timezone
- Change GPU memory split to minimum value, 16 MB for GPU (we don't need a display)
- Overclock to improve performance - **warning using over volt invalidates the Pi warranty** I'm happy to use Medium but modest may be a safer option for you (no over volt)
Update package lists first
sudo apt-get update
Download and install wspr dependencies
sudo apt-get install build-essential subversion python2.7-dev python-numpy python-imaging-tk python-pmw libportaudio2 portaudio19-dev libsamplerate0-dev gfortran cl-fftw3 python-dev hamlib-utils
Get the latest version of WSPR
svn co http://svn.berlios.de/svnroot/repos/wsjt/branches/wspr
Enter wspr directory
cd wspr
Configure source
./configure --with-portaudio-include-dir=/usr/include --with-portaudio-lib-dir=/usr/lib/arm-linux-gnueabihf
Edit the Makefile to enable hardfloat, this will improve decoding performance
pi@raspberrypi ~/wspr $ vi Makefile
FFLAGS = -g -O2 -fno-range-check -ffixed-line-length-none -Wall -Wno-character-truncation -Wno-conversion -Wtabs -fPIC -mfloat-abi=hard
And also to the end of line 9
CFLAGS = -Wall -O0 -g -Wall -O0 -g -mfloat-abi=hard
Make the build
sudo make
And Install
sudo make install
As we will use the wspr_nogui.py program and not wspr.py copy the compiled w.so module from the WsprMod to the WsprModNoGui directory
pi@raspberrypi ~/wspr $ cp WsprMod/w.so WsprModNoGui/
Demote the on board Raspberry Pi sound card to the second device by adding/modifying the following parameters in /etc/modprobe.d/alsa-base.conf
pi@raspberrypi ~/wspr $ sudo vi /etc/modprobe.d/alsa-base.conf
#options snd-usb-audio index=-2
options snd_bcm2835 index=-2
Save the above file and reboot
sudo reboot
In order to improve USB stability add the following command to /boot/cmdline.txt, this limits the USB speed to 12Mbps (USB 1.1) - without this I have problems
dwc_otg.speed=1
Create a .libao file your home directory with the following lines
driver=alsa
dev=default
sudo reboot
Create a .asoundrc file (don't forget the leading dot) in your home directory (/home/pi/.asoundrc) and add the following lines
pcm.radio {
type hw
card 1
device 0
}
pcm_slave.radioslave {
pcm radio
rate 48000
}
pcm.radioconv {
type rate
slave radioslave
}
Add the following lines to the configuration file with vi, change MyCall and MyGrid to your callsign and location, the selected band in this example is 160 m (iband 2) - change this to your desired band
MyGrid JN39GT
CWID 0
dBm 37
PttPort None
CatPort None
AudioIn 2#radio
AudioOut 3#radioconv
BFOfreq 1500
PTTmode DTR
CATenable 0
Acal 0.0
Bcal 0.0
CalEnable 0
IQmode 0
IQrx 0
IQtx 0
FIQ 12000
Ntxdb 0
SerialRate 4800
DataBits 8
StopBits 2
Handshake None
Rig 214#####Kenwood#########TS-2000
Nsave 0
TRminutes 2
PctTx 0
DGain 5
Upload 1
Idle 0
Debug 0
MRUdir /home/pi/wspr
freq0_600 0.5024
freqtx_600 0.5039
freq0_160 1.8366
freqtx_160 1.8381
freq0_80 3.5926
freqtx_80 3.5941
freq0_60 5.2872
freqtx_60 5.2887
freq0_40 7.0386
freqtx_40 7.0401
freq0_30 10.1387
freqtx_30 10.1402
freq0_20 14.0956
freqtx_20 14.0971
freq0_17 18.1046
freqtx_17 18.1061
freq0_15 21.0946
freqtx_15 21.0961
freq0_12 24.9246
freqtx_12 24.9261
freq0_10 28.1246
freqtx_10 28.1261
freq0_6 50.293
freqtx_6 50.2945
freq0_4 70.0286
freqtx_4 70.0301
freq0_2 144.489
freqtx_2 144.4905
freq0_other 0.136
freqtx_other 0.1375
iband 2
StartIdle 0
NoBeep 0
Reject 0
RxApply 0
Each time wspr_nogui.py is run a file called audio_caps is created in the wspr directory, check that the audio device id's match the configuration file above
pi@raspberrypi ~/wspr $ more audio_caps
0 2 2 0 0 USB Audio CODEC: USB Audio (hw:1,0)
1 32 32 0 0 pulse
2 2 2 0 0 radio
3 2 2 0 0 radioconv
ID 2 (radio) is Audio in and ID 3 (radioconv) is audio out
If you choose to use the Terratec sound card you'll need to switch to line in mode and set the volume with the following commands (not necessary for the SignaLink USB)
/usr/bin/amixer -c 1 cset numid=13,iface=MIXER,name='Capture Source' 1
/usr/bin/amixer -c 1 cset numid=10,iface=MIXER,name='Line Capture Switch' 1
/usr/bin/amixer -c 1 set Line 45%
Now it's time to run wspr without a GUI (run from the wspr directory)
pi@raspberrypi ~/wspr $ python -O wspr_nogui.py
The RX noise will read -30 dB until the next 2 minute receive interval, the program output will be displayed on your ssh console, if you close the session the process will die
if you want to run in the background use the command below, with this method you can disconnect your ssh session and let the Pi operate in standalone mode (no keyboard, mouse or monitor needed)
pi@raspberrypi ~/wspr $ nohup python -O wspr_nogui.py 2>/dev/null 1>/dev/null &
Make sure your Raspberry Pi remains connected to a network for accurate time (NTP) and for spot uploads to wsprnet
Questions?
So where can I see my spots?1) In the local text file /home/pi/wspr/ALL_WSPR.TXT
pi@raspberrypi ~/wspr $ more ALL_WSPR.TXT
2) http://www.wsprnet.org if you have a working Internet connection
How much CPU does the process use?
While receiving 2%, decoding about 98% and in transmit mode 6%
What is the average time to decode at the end of each interval?
Between 15 and 35 seconds depending on the number of spots and band/noise conditions
Does the transmit function work? how do I enable it?
In the above example I've configured wspr to run in receive only mode with PctTx 0, to enable transmit for 20% of the time set PctTx 20 in WSPR.INI, PctTx 50 is 50% transmit
Does the Raspberry Pi provide enough current for the USB sound cards above? do I need a powered USB Hub?
For the cards in this howto I don't need a powered hub, the 100 mA provided by the Pi is adequate, for other cards/usb devices you may need a powered hub
How do I check/set the sound levels?
Run wspr_nogui from your console and wait for the start of the next receive interval
pi@raspberrypi ~/wspr $ python -O wspr_nogui.py
The RX level should be around 0 dB but +- 10 dB is still ok
With the Signalink USB sound can be adjusted with the TX/RX knobs, for other cards you will have to use alsamixer to adjust playback/capture levels
pi@raspberrypi ~/wspr $ alsamixer (select F5 to show all inputs/outputs)
Frequency hopping configuration (optional)
This configuration has been tested without the need for an external USB powered hub, both the USB sound card and serial converter work fine together on the Raspberry USB ports.
So the first step is to install hamlib, the main site is here http://sourceforge.net/apps/mediawiki/hamlib/index.php?title=Main_Page
Download the latest tarball to your home dir
wget https://downloads.sourceforge.net/project/hamlib/hamlib/1.2.15.3/hamlib-1.2.15.3.tar.gz
Extract the contents
tar -zxvf hamlib-1.2.15.3.tar.gzEnter hamlib directory
cd hamlib-1.2.15.3
Install dependencies
sudo apt-get install libltdl-dev
Run configure from hamlib dir
./configure
And make (can take some time - don't hog the cpu, make sure wspr is not running during compile)
make
And make install
sudo make install
OK all done, now connect the USB serial converter, it should show up as /dev/ttyUSB0.
The next step is to test CAT communication between your rig and Raspberry Pi with rigctld, for this test you need to know the baud rate, data and stop bits and rig id from hamlib.
You will find your rig id in the file:
pi@raspberrypi ~/wspr $ more /home/pi/wspr/hamlib_rig_numbers
101 Yaesu FT-847 0.5 Beta
103 Yaesu FT-1000D 0.0.6 Alpha
104 Yaesu MARK-V FT-1000MP 0.0.5 Alpha
105 Yaesu FT-747GX 0.4.1 Beta
106 Yaesu FT-757GX 0.4.1 Beta
107 Yaesu FT-757GXII 0.4 Stable
109 Yaesu FT-767GX 1.0 Stable
110 Yaesu FT-736R 0.3 Stable
111 Yaesu FT-840 0.1 Untested
To limit the search to Kenwood rigs only use grep
pi@raspberrypi ~/wspr $ more /home/pi/wspr/hamlib_rig_numbers | grep Kenwood
201 Kenwood TS-50S 0.8 Untested
202 Kenwood TS-440 0.8.0.6.1 Alpha
203 Kenwood TS-450S 0.8.1 Beta
204 Kenwood TS-570D 0.8.2 Stable
205 Kenwood TS-690S 0.8.1 Beta
206 Kenwood TS-711 0.8.0.6.1 Untested
207 Kenwood TS-790 0.8.2 Alpha
208 Kenwood TS-811 0.8.0.6.1 Untested
209 Kenwood TS-850 0.8.1 Beta
210 Kenwood TS-870S 0.8.0 Beta
211 Kenwood TS-940S 0.8.0.6.1 Alpha
213 Kenwood TS-950SDX 0.8 Beta
214 Kenwood TS-2000 0.8.4 Beta
215 Kenwood R-5000 0.6.1 Alpha
216 Kenwood TS-570S 0.8.1 Stable
217 Kenwood TH-D7A 0.5 Alpha
219 Kenwood TH-F6A 0.5 Beta
220 Kenwood TH-F7E 0.5.1 Beta
222 Kenwood TS-930 0.8 Untested
223 Kenwood TH-G71 0.5 Beta
224 Kenwood TS-680S 0.8.1 Beta
225 Kenwood TS-140S 0.8.1 Beta
226 Kenwood TM-D700 0.5 Beta
227 Kenwood TM-V7 0.5 Beta
228 Kenwood TS-480 0.8.5 Untested
230 Kenwood TRC-80 0.8 Alpha
231 Kenwood TS-590S 0.8.1 Beta
233 Kenwood TH-D72A 0.5.1 Alpha
234 Kenwood TM-D710 0.5 Untested
The test command for my Kenwood TS-480 is below:
rigctl -vvvvv -r /dev/ttyUSB0 -s 38400 -C stop_bits=1 -m 228
If it works you will get the following output
pi@raspberrypi ~/hamlib-1.2.15.3 $ rigctl -vvvvv -r /dev/ttyUSB0 -s 38400 -C stop_bits=1 -m 228
rigctl, Hamlib 1.2.15.1
Report bugs to <hamlib-developer@lists.sourceforge.net>
rig:rig_init called
rig: loading backend kenwood
initrigs2_kenwood called
rig_register (213)
rig_register (201)
rig_register (225)
rig_register (203)
rig_register (204)
rig_register (216)
rig_register (224)
rig_register (205)
rig_register (207)
rig_register (209)
rig_register (210)
rig_register (222)
rig_register (214)
rig_register (230)
rig_register (221)
rig_register (229)
rig_register (202)
rig_register (211)
rig_register (206)
rig_register (208)
rig_register (215)
rig_register (226)
rig_register (217)
rig_register (233)
rig_register (220)
rig_register (223)
rig_register (227)
rig_register (234)
rig_register (231)
rig_register (231)
rig_register (228)
rig_register (219)
rig_register (232)
kenwood_init called
kenwood_init: if_len = 38
rig_set_conf: stop_bits='1'
rig:rig_open called
kenwood_get_vfo_if called
kenwood_get_if called
kenwood_safe_transaction called
kenwood_transaction called
kenwood_transaction: cmdstr = IF
write_block(): TX 3 bytes
0000 49 46 3b IF;
read_string(): RX 38 characters
0000 49 46 30 30 30 31 38 31 32 31 30 30 30 20 20 20 IF00018121000
0010 20 20 20 30 30 30 30 30 30 30 30 30 30 32 30 30 0000000000200
0020 30 30 30 38 30 3b 00080;
Opened rig model 228, 'TS-480'
Backend version: 0.8.5, Status: Untested
Rig command: f
kenwood_get_freq called
kenwood_safe_transaction called
kenwood_transaction called
kenwood_transaction: cmdstr = FA
write_block(): TX 3 bytes
0000 46 41 3b FA;
read_string(): RX 14 characters
0000 46 41 30 30 30 31 38 31 32 31 30 30 30 3b FA00018121000;
Frequency: 18121000
Rig command:
Great, let's configure WSPR to use CAT control, you'll need to set the following parameters in WSPR.INI (these parameters are specific to your rig)
CATenable 1
SerialRate 38400
DataBits 8
StopBits 1
Handshake Hardware
Rig 228#####Kenwood#########TS-480
And now have a look at hopping.ini in the wspr directory
On the first line you'll see two flags, the first flag is hopping enable 0=off 1=on, the second flag is standard or coordinated hopping 0=standard 1=coordinated
Check out K1JT's WSPR doc for more info (hopping function is described on page 11)
http://physics.princeton.edu/pulsar/K1JT/WSPR_3.0_User.pdf
Add a hash in front of the globalupdate() line near the bottom of the file and save, this will stop the 'Error reading hopping.ini' message
tuneupflag[r].set(int(s[r][13:16]))
#globalupdate()
except:
print 'Error reading hopping.ini.'
All done, start wspr_nogui.py and after a couple of minutes your rig will start hopping in RX and TX if you choose, please let me know if I have missed anything.
73's LX3KR
pi@raspberrypi ~/wspr $ more hopping.ini
1 1
600 0 0 0
160 0 0 0
80 0 0 0
60 0 0 0
40 1 0 0
30 1 0 0
20 1 0 0
17 0 0 0
15 0 0 0
12 0 0 0
10 0 0 0
6 0 0 0
4 0 0 0
2 0 0 0
Oth 0 0 0
Check out K1JT's WSPR doc for more info (hopping function is described on page 11)
http://physics.princeton.edu/pulsar/K1JT/WSPR_3.0_User.pdf
The four columns have the following use:
1) Band id
2) Enable hopping for this band, 1=yes, 0=no
3) pctx
4) Tuneup on each band? - 1=yes, 0=no
Unfortunately frequency hopping will not work with wspr_nogui.py out of the box due to a small bug related to leftover code from the GUI, to fix this edit the following file with vi or nano
pi@raspberrypi ~/wspr $ nano WsprModNoGui/hopping.py
Add a hash in front of the globalupdate() line near the bottom of the file and save, this will stop the 'Error reading hopping.ini' message
tuneupflag[r].set(int(s[r][13:16]))
#globalupdate()
except:
print 'Error reading hopping.ini.'
73's LX3KR