Well, this is what it looked like at the end, but it took a while getting there. From the hardware perspective, this was a good first project after the long dead spell. I settled on the Parallax Propeller as the heart of the thing rather than the more common Arduino. Why? Good question. I think I was lured in by the Propeller’s interrupt-free programming model, 8 parallel processors, and ready-to-go prototyping boards. I had also poked around their OBEX site of contributed objects for interfacing with common peripherals and liked the one-stop shopping.
It was a snap to hook up the WWVB receiver breakout board from Sparkfun, it’s just power/ground and a signal output line. Hooking up the serial LCD (also from Parallax) was equally simple to do. Later in the project I also added a battery-backed RTC from Maxim, which was a little more complicated to figure out since it was an I2C based chip and so I needed to learn about that protocol in some depth in order to get that working. The weird gymnastics of using the “illegal” states of the data/clock lines to signal the beginning and end of a transfer, and the use of one bit of the address to signal a read vs. write, were not entirely intuitive at first, seeing as how I was a little rusty in this department at the time. The cable and extra box leading out of the enclosure is simply an extension to house the little ferrite bar antenna, because when I tried using it within the main casing, it was noisy enough in there to pretty much spoil any reception. Getting it 5 or 6 inches away seems to be enough to get back to good reception most of the time, even often in daylight hours.
The real complexity of this project turned out to be the WWVB signal itself. The wikipedia entry was my bible, because decoding the signal is just bizarre. First, you wait for the dark hours of the evening, because daylight tends to drown the signal (coming in at verrry low signal strength from Colorado). Then, you time the pulses come out of the receiver chip. A 200ms pulse (yes, milliseconds – an eternity…) is a zero, a 500ms pulse is a one, and an 800ms pulse is a “mark” that is supposed to show up at regular intervals to help you figure out where the top of the minute starts.
It takes an entire minute to receive one complete frame of data, so the debugging process can take rather a long time when you’re working with the live data. Also, those pulse lengths vary within a pretty wide threshold because the pulses are determined from amplitude modulation of just 17dB (which is not a huge amount), so virtually any noise in reception causes a short pulse or a pulse where there shouldn’t be one at all. Turning on a fluorescent lamp (of which there are now many) can ruin the signal completely. There are a lot of techniques for working around the noise, such as averaging consecutive frames over a period of several minutes and trying to figure out where the errors occurred, but after a lot of trial and error, in the end I went for the simple version and I simply throw out any frames where any obviously invalid bits were received, or expected bits were missed. This seems to work OK in practice.
For a while I used serial-printf() style debugging to tell me how frequently the pulses were coming in, how long they were, and so on. This was enough to figure out when the signal was really poor and when it was doing well and so on, but somewhere about midway through this project I splurged on a LeCroy WaveAce 102 (a 60Mhz digital oscilloscope) and being able to actually see the pulses and any noise on the signal onscreen made life much, much easier. (The scope purchase will make a good post in itself, I think.) As a simple signal quality monitor, I programmed a few of the custom characters on the serial LCD to give me a simple 0-3 “bars” meter like a cellphone, and when the clock is locked on and actively receiving a good frame it shows a little “antenna” icon with a little wave overhead. This way I can at least see what’s going on in a rough sense without hooking up test equipment. To calculate how many bars to show I just keep a running average of how many good pulses were received in the last 30 seconds and how many were thrown out as invalid due to being too far off “center” (as calculated from the last “top of minute” signal we received, which is two marks in a row) or pulses which were of some obviously invalid duration. This technique works pretty well too in practice.
There also turned out to be a lot more complexity than I really expected there to be just in the act of keeping time. Since the time comes in formatted for Greenwhich Mean Time (really, UTC), you need to translate it for local time, which can of course mean rollovers (or rollbacks) in the date as well, all depending on what timezone you’re in and whether DST is in effect or not. Handling daylight savings time shifts also turns out to require a little thought – when the clocks go back in the fall, you need to make sure you don’t fall back again when you get to 2am the second time that night. Ask me how I know. Then there’s trying to set the onboard RTC chip with some level of fidelity over I2C, once the Propeller thinks it knows for sure exactly what time it is.
Well, making all that work while learning how to make best use of the Propeller’s parallel programming turned into a couple months of nights spent banging away at the project, but I was reasonably happy with the outcome and I scraped off an awful lot of rust from my brain in the process. Another clock for the collection
Next time: RGB LEDs Gone Wild.