A bit of feedback from some WSPR Watch users has prompted a bit of work on the app. Recent updates have added and then improved the graphing of the number of spots per block of time - which I think is a fair way to show the rise and fall in propagation, then colours to show bands on not only the graphs but also on the arcs on the map.
Spurred on by recent success transmitting WSPR with a simple Arduino and Si5351 clock generator, I've done the work to generate the needed audio right in the app.
Tests here have shown that simple acoustic coupling from the phone to the mic of an SSB transmitter is enough to be spotted at great distance.
The new transmit feature also has a few goodies:
Figures out your maidenhead locator by using the phone's location services.
Uses the phone's time sync to start the transmission on time.
There's more to be done but this is a good start. To generate the audio, I used the fabulous AudioKit framework. Symbol generation code was copied from the GPL2 WsprryPi project. (I love how swift can so simply call C functions just by making a bridging header).
WSPR Watch 3.2.6 is now available and I hope you find it useful.
Update 3.2.6 had a bug that led to an intermittent crash. Update to 3.2.7 or later to get over that. I'd like to add that the new band colours in both the graph and map views look great.
The crash was interesting, it wasn't clear what was crashing, somewhere deep in framework c++ code. In the end it turned out that my table of band frequency edges hadn't got 60m correct for all parts of the world and if I got a frequency I didn't expect I'd try to set the colour of an attributed string to an illegal colour. It didn't crash right away though. Thanks to those who reported the issue.
Intrigued by the ZachTek pocket WSPR transmitter Peter, VK3YE, has reviewed, I wondered if I could get a simple beacon going using just an Arduino, an Si5351 clock generator and (you'll be pleased to hear) a low pass filter.
Here's the rig. The low pass filter is from the VK3YE Beach 40 design which I like because it uses off the shelf inductors.
The waveform isn't perfect but it's certainly a long way from the square wave the comes out of the clock generator.
I've taken this sketch, ripped out the lovely GPS time synchronisation, and turned it into a 1 shot beacon. You power on, or press reset, it transmits one message and then turns off RF. Of course you need to push the button at the beginning of a two minute cycle.
Here's how it decodes locally on my receiver with no antenna connected.
You can see that big signal drift earlier where I powered up with the antenna disconnected to let it get up to temperature. In the actual slot it reports a drift of -1 and decodes nicely (well... twice).
Hooked it up to the antenna just now and the little Arduino/sSi5351 transmitter is being heard quite widely.
Both very easy to use. Here's my hack of the code, I'm afraid Blogger doesn't like parts of it like angle brackets so no doubt there will be some things to fix up.
* Minimal WSPR beacon using Si5351Arduino library
* Based on code:
* Copyright (C) 2015 - 2016 Jason Milldrum
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
#define TONE_SPACING 146 // ~1.46 Hz
#define WSPR_CTC 10672 // CTC value for WSPR
#define SYMBOL_COUNT WSPR_SYMBOL_COUNT
#define CORRECTION 0 // Change this for your ref osc
#define TIME_HEADER "T" // Header tag for serial time sync message
#define TIME_REQUEST 7 // ASCII bell character requests a time sync message
#define TX_LED_PIN 13
//#define SYNC_LED_PIN 13
unsigned long freq = 7040500UL; // Change this
char call = "VK2TPM"; // Change this
char loc = "QF56"; // Change this
uint8_t dbm = 10;
// Global variables used in ISRs
volatile bool proceed = false;
// Timer interrupt vector. This toggles the variable we use to gate
// each column of output to ensure accurate timing. Called whenever
// Timer1 hits the count set below in setup().
proceed = true;
// Serial.println("timer fired");
// Loop through the string, transmitting one character at a time.
jtencode.wspr_encode(call, loc, dbm, tx_buffer);
// Reset the tone to 0 and turn on the output
// Now do the rest of the message
for(i = 0; i < SYMBOL_COUNT; i++)
uint64_t frequency = (freq * 100) + (tx_buffer[i] * TONE_SPACING);
Serial.print("freq = ");
proceed = false;
// Turn off the output
// Use the Arduino's on-board LED as a keying indicator.
// Set time sync provider
//setSyncProvider(requestSync); //set function to call when sync required
// Initialize the Si5351
// Change the 2nd parameter in init if using a ref osc other
// than 25 MHz
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, CORRECTION);
// Set CLK0 output
si5351.set_freq(freq * 100, SI5351_CLK0);
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); // Set for max power
si5351.set_clock_pwr(SI5351_CLK0, 0); // Disable the clock initially
// Set up Timer1 for interrupts every symbol period.
noInterrupts(); // Turn off interrupts.
TCCR1A = 0; // Set entire TCCR1A register to 0; disconnects
// interrupt output pins, sets normal waveform
// mode. We're just using Timer1 as a counter.
TCNT1 = 0; // Initialize counter value to 0.
TCCR1B = (1 << CS12) | // Set CS12 and CS10 bit to set prescale
(1 << CS10) | // to /1024
(1 << WGM12); // turn on CTC
// which gives, 64 us ticks
TIMSK1 = (1 << OCIE1A); // Enable timer compare interrupt.
OCR1A = WSPR_CTC; // Set up interrupt trigger count;
interrupts(); // Re-enable interrupts.
encode(); // transmit once and stop
// blink LED when we've finished the transmit
There's a new version of the iOS WSPR Watch app coming out today. Encouraged by some enthusiastic WSPR watchers, I've done some work to add and rapidly improve the graphing of spots.
The graph now shows spot counts aggregated over various blocks of time rather than per two minute slot. The band colours match those used on the WSPRnet.org site.
My thanks to Mark, Phil and Ross for feedback and ideas. Phil, VK7JJ, has an exceptionally low noise level in Tasmania and he also runs an excellent web tool for plotting WSPR spot reception.
I've been picking up Peter, VK3YE, quite reliably and I asked him how he was doing the multi-band transmissions. He's been using a Zachtek WSPR transmitter which he reviews here:
Most entertainingly, Peter took the transmitter bus mobile and I was one of the stations that received him during a trip!
I like how peter holds the compact loop at the ground point of the feed line and how he notes the SWR change as the metal window frame changes the loop characteristics.
What SNR level shown on WSPR is needed for an actual conversation?
The fact that I can reliably hear some stations got me wondering about what Signal to Noise ratio shown in a WSPR reception would mean the two stations could have a keyboard to keyboard chat. There's a bit of controversy about the equivalence between WSPR and other modes such as this thread, but the consensus seems to be that Olivia 500/8 is the best bet.
"Submissions were received from people and organisations based across Australia and the Asia Pacific region, as well as other countries, including Germany, Indonesia, New Zealand, Palau, Papua New Guinea (PNG), Peru, Philippines, Samoa, Singapore, the United Kingdom (UK), the United States (US) and Vanuatu."
I've tinkered with machine learning in the past using TensorFlow but wanted to try Apple's tools which are extremely simple to use by comparison.
We have a low quality webcam pointing out into the street in front of the house that writes a file to a NAS every time it detects motion near the letter box. I often check these images to see if the postie has come. The project's objective is to automate looking at the images and recognise the postie.
Following Apple's documentation, I created an Xcode storyboard and trained it with a folder containing two sub-folders named "Postie" and "No Postie".
The storyboard is just this:
let builder = MLImageClassifierBuilder()
And it puts up a nice little UX where you drag your training folder.
I did try all of the augmentations shown above, it took a lot longer but wasn't more accurate in my case.
After saving the model, I created a simple macOS application with an ImageWell in it. You drag in an image and it shows the most likely tag like this:
Here's the main bit of the code to look at the image and display the classification.
After re-building the inside of the van to replace the double bed with a single bed/couch facing a long bench with shelves, I've taken the opportunity to travel north for a few days and try living in it.
The new arrangement is much better than before. Along the way I stopped at very pleasant spots and could enjoy the view while still being able to make cups of coffee and access everything with ease.
The woodwork on the bench isn't great and if I do it again there are things I'd change but in the end it was built with straight timber in a curving van interior.
The sink and manual pump tap is fantastic and makes me feel much more at home when doing things like cleaning my teeth.
Another change is that I've mounted an antenna base on the roof rack and reception on 20m is pretty good although I do get noise from the solar charge controller and fridge.
Once again my destination was a farm stay in Eden near Dorrigo and it really is beautiful countryside. The morning view from the side of the van.
Lovely rivers are all over the place. (Click photos to enlarge).
I'm still figuring out where to put things and even in a "tiny house" it's amazing how things can be hard to find.
The bed, which is slats supporting a medium density single camp mattress from Clark Rubber is very comfortable and I quite like going to sleep when the sun goes down.
I've purchased a battery monitor with a current shunt that displays voltage, current and then figures out power use. This is being trialled in the shed and will be installed in the van in due course.