It’s about time… (with some WSPR updates)
Yesterday I finally found a copy of the code that I wrote years ago to figure out the tone sequence for messages used by the Weak Signal Propation Reporter system. To avoid losing it again, I decided to put both the C versions and the Python versions on my github page so that even if my servers go down I’ll have the code archived somewhere. If you have need of the code, feel free to use it (it would be nice if you gave an attribution in any derivative works that you distribute, but I won’t go so far as to insist).
When I got home, I found myself thinking about using the AD9850 as a WSPR beacon, using an Arduino (or similar) to generate the tone sequence, telling the AD9850 to switch to those frequencies, and generate the appropriate RF. This was basically a meld of two programs: the genwspr.c code that I listed above, and a simple sketch that can be used to set the AD9850 to different frequencies. It seemed very simple, so I sat down and started tinkering.
I began by copying the genwspr.c program into a new wspr.ino sketch. It pretty much would compile as is (after I added the necessary dummy setup() and loop() entry points needed by the Arduino) but it did not generate the same code sequence as the code did when I ran it on my desktop. A moment’s thought revealed the likely cause: “int” values are only 16 bits on the AVR. It actually took me a bit of time to get the types sorted out (maybe 30 minutes), mostly because I didn’t remember that I should use (1UL< <n) instead of just (1<<n) to get the needed 32 bit values.
Once I got that sorted out, I extracted the needed “setFrequency” routines from an AD9850 sketch, and created a loop that would send the different frequencies at the right time. The four tones needed by WSPR are 12000/8192 (or about 1.465 Hz) apart and are 8192 / 12000 seconds in duration. My initial code simply calculated the frequency for the the given message entry, sent the appropriate tuning word to the AD9850, and then called delay(8192/12) (delay uses microseconds). Because that didn’t take into account the time spent calculating and setting the tuning word, the overall message was a bit long (actually only 22ms long) so instead I did a delay(8192/12-1), and then a delayMicroseconds(22000/162). That put it right at the 110.592 seconds that are specified. (I know it’s silly, the clock in the Arduino could easily be off, but I thought it would be good to be tidy. If you had source to an accurate 1PPS source, you could do a better job of this).
I was a tiny bit concerned that the tuning resolution of the AD9850 was insufficient, but consulting the datasheet, the nominal resolution is about 0.029 Hz. That should be fine. I’ll dig out my SDR-IQ this weekend and try to do some workbench reception tests over the next few days.
The next bit you need to make a functioning beacon is to ensure that the transmissions start one second after even minutes. That requires some accurate time keeping. My initial idea was to hook up an old Parallax PMB-648 GPS module that I had lying around. During slots where it wasn’t transmitting, it could use the time signal from the GPS to ensure that the clock had not drifted. I hadn’t played with this module in a while (it’s listed as obsolete on the Parallax page) so I hooked it up to the Arduino, wrote a simple sketch to read data from it, and let it run.
Frown. It’s just not sensitive enough to get a lock while inside my house. I thought about alternatives for mounting it. Grumble. Didn’t like that idea. External antenna? Newer module? Grumble.
Perhaps a different approach was needed. I considered the various wireless modules that I had lying around. Perhaps I could use the esp8266 modules (which are really cheap) to fetch the time with NTP, and then the Arduino could use that to trigger the transmissions.
Hooking the ESP8266 to the Arduino is not quite as straightforward as the GPS because the Arduino that I use is 5V, and the ESP8266 is a 3.3v device. I have some Sparkfun level converter boards around, but it turns out that you really only need to be careful about the TX from the Arduino. The circuit below uses a little 3.3V Zener diode to drop the voltage to avoid blowing the URXD on the ESP8266. I think I have some 3.3V zeners in my box somewhere. The circuit shows a separate 3.3V low drop out regulator because the ESP8266 can be quite power hungry, and the regulator on your traditional Uno can only supply about 50ma. I believe the Redboard has a better regulator, the MICREL MIC5205 LDO can supply 150ma, so that should be fine. If I can find the Zeners, it should be easy to breadboard.
My idea was to use the ESP8266 to send out NTP packets, parse the results… but a little googling revealed a better way. There is
alternative firmware for the ESP8266 that adds support for NTP directly via AT commands. If you send the AT command below, you’ll get the time back:
AT+CIPNTP? Time: 22:22:42 12/02/2014 GMT+02
That seems awesome. The idea will be that when the Arduino is reset, it will bring up the network and try to get the time and will figure out when the next time slot begins for transmission. When that slots begins, it can decide to either transmit, or wait until the next slot. Easy-peasy.
When I get the completed sketch up, I’ll add it to my github respository.