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
Congrats on the nicely done project! Do you know if this setup would work with a cheap USB audio card -- like the ones sent on ebay for $5-7?
ReplyDeleteAlso, I assume this works as a monoband wspr beacon; is it possible to control the rig (e.g. via a usb-serial converter) to change bands from the wspr/RaspberryPi?
Hi Paul,
DeleteA cheap usb sound card should also work but I haven't tried one yet. For rig control install rigctl and use a usb serial converter, I've tried this on the Raspberry Pi and it works fine, you'll need to set the port parameters in WSPR.INI.
cheers,
Karl
Just wanted to say many thanks for this first class tutorial! I set up step by step by your instructions. RX FT-817, Raspi and a cheap USB sound dongle. Tuned in 30 m, and first spot was W3HH - distance 7597 km. Great fun! Thank you so much again.
ReplyDeleteMichael DL9LBG
Hi Michael,
DeleteI'm glad you found the howto useful, it's nice to give something back to radio community as I've benefited greatly from other users helpful tips and tricks.
73's
Karl
Karl,
ReplyDeleteTX now also working great, I have the Beaglebone Black hooked up to a SignaLink USB and my Kenwood TS870 pushing 5W.
Now that I can see this works and works well, I will be swapping out the SignaLink for a cheap USB stick and the Kenwood for a small homebrew TX.
Can't believe that will give me a standalone WSPR station for less than £75!
For your information, the Beaglebone Black is using CPU, as follows:
2.3% - 3.3% TX
2.4% - 3.1% RX
95% - 99% Decoding
Memory stats are:
KiB Mem: 507496 total, 181804 used, 325692 free, 14008 buffers
KiB Swap: 262140 total, 0 used, 262140 free, 65820 cached
I've had some very nice reports already.
Hi,
DeleteGreat to hear it's working fine for you, I also use the Beaglebone black as well, the Raspberry Pi had too many problems with the USB interface with high speed applications.
Check out my Beaglebone black WebSDR here (software by PA3FWM) -> http://websdr.dyndns.info:8901/
cheers,
Karl
Excellent Karl, been on it all afternoon, now it makes me wonder if I should use their tx/rx to make my standalone.
DeleteAlso, have you seen the new Cubieboard, that looks an interesting piece of kit.
Nice write up. I couldn't edit them make file. I had no problem adding to line 5 but when I tried to move down to line 9 the result was to add a bunch of random characters at the top of the makefile. What am I doing wrong?
ReplyDelete73,
Chris AK4SK
thanks for the excellent advices -- but let me comment. WSPR is still under development and nowadays preferred is python3.
ReplyDeleteMy idea is: raspi should use python 2 first. So you cannot use the newest svn releases.
I use revision R3015 and python2.7
Prepare a bare Raspian by
sudo apt-get install subversion python-dev python-numpy python-imaging-tk python-tk libportaudio2 portaudio19-dev libsamplerate0-dev gfortran cl-fftw3 python-dev autoconf libtiff5 python-imaging libhamlib-dev libhamlib-utils python-libhamlib2 libhamlib++-dev
and fetch from (the today archives)
svn co svn://svn.code.sf.net/p/wsjt/wsjt/branches/wspr -r 3015
hope this give an addition to your very helpful advices
vy 73
Michael
Hi, having fun and games getting wspr to run on a new Pi B+ ...
ReplyDeleteHave gone with Michael's (DK5HH) suggestions since I was unable to download source code from "svn co http://svn.berlios.de/svnroot/repos/wsjt/branches/wspr"
but still having issues - see below
WSPR Version 3.00_r2326, by K1JT
Run date: Sat Dec 27 17:02:38 2014 UTC
setting g.Win32
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.hdmi
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.hdmi
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.modem
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.modem
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.phoneline
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.phoneline
ALSA lib pcm_dmix.c:957:(snd_pcm_dmix_open) The dmix plugin supports only playback stream
FATAL: cannot locate cpu MHz in /proc/cpuinfo
Any suggestions...
73's
Simon (G4USP)
thought about putting an sbc inside the ft817 with colour lcd on the lid? could wirelessly couple audio, data, cat, echolink via wifi, standalone data modes etc
ReplyDeleteI have a SSB Rx for Rx WSPR can I Tx WSPR packets using RPi directly ?
ReplyDeletecan't access the svn
ReplyDelete