Thursday, 28 March 2013

WSPR on a RaspberryPi

Building a reliable WSPR decoder on a headless Raspberry Pi (no GUI)

Version info
31/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 RAM

Disk media is an 8 GB SDHC card, I use class 10 cards for faster disk IO performance
RaspberryPi.jpg

Successfully tested USB sound cards -  Signalink USB & Terratec 5.1 USB



Aureon_51_USB_MK_II_trans


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

Set the following parameters
  1. Change the default password from raspberrypi to something more secure
  2. Update raspi-config
  3. Expand the rootfs
  4. Set timezone
  5. Change GPU memory split to minimum value, 16 MB for GPU (we don't need a display) 
  6. 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

Add the string -mfloat-abi=hard to the end of line 5 as shown below
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

Reboot to activate changes
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
}

Create a wspr configuration file in the wspr directory (/home/pi/wspr/WSPR.INI in my case)

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


MyCall LX3KR
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)

So you want to frequency hop as well? no problem, you'll need a USB serial converter and a copy of the hamlib utilities.

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.gz

Enter 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)


CatPort /dev/ttyUSB0
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

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

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

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.'

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

13 comments:

  1. 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?
    Also, 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?

    ReplyDelete
    Replies
    1. Hi Paul,

      A 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

      Delete
  2. 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.

    Michael DL9LBG

    ReplyDelete
    Replies
    1. Hi Michael,

      I'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

      Delete
  3. Karl,

    TX 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.

    ReplyDelete
    Replies
    1. Hi,

      Great 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

      Delete
    2. Excellent Karl, been on it all afternoon, now it makes me wonder if I should use their tx/rx to make my standalone.

      Also, have you seen the new Cubieboard, that looks an interesting piece of kit.

      Delete
  4. 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?
    73,
    Chris AK4SK

    ReplyDelete
  5. thanks for the excellent advices -- but let me comment. WSPR is still under development and nowadays preferred is python3.

    My 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

    ReplyDelete
  6. Hi, having fun and games getting wspr to run on a new Pi B+ ...
    Have 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)



    ReplyDelete
  7. 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

    ReplyDelete
  8. I have a SSB Rx for Rx WSPR can I Tx WSPR packets using RPi directly ?

    ReplyDelete