iy3xk ftc9ky lscsucks

Yet Another WWVB Howto

Aug 2025 (c) RLamb


These WWVB receiver modules are just so cheap (<$3), I had to get one and waste $1000s in time to play with one. The result is the hookup* in the photo above and the raw C code here. Drop this code into your ESP32 code and call showwwvb() every minute or so to display WWVB time, data, UT1 corrections, leap seconds. Have fun.
*I put a 1uF across the CME6005 DEM pin (C6) to reduce noise.
...uh...but cant I do better?..


Roll your own BPSK WWVB clock .

Feb 2026 (c) RLamb

Fig 1 Block Diagram

In a moment of weakness I acquired a few of those $2 WWVB modules [fig 5,ref 1] out of curiosity about 60kc propagation. Figured at 1 bit per second it would be a fun few day exercise to decode the pulse width modulated (PWM) output to get time. Well I am embarrassed to say many months later I am still having a bit of fun with WWVB. E.g., at 1 bit per second surely I could easily make my own radio-decoder and do better with a little bit of C code on a ESP32 to handle the updated BPSK format instead of just the AM/PWN that the module provides. Ha! Although I was able to write a good PWM decoder [fig 2,ref 2] early on, I wanted more.
Fig 2 Version 0 using AM/PWM module only. Yeah. Threw gps, latlon->TZ support in there too.
Found the ES100 BPSK module [ref 8] but given my signal levels, performance was a bit disappointing for someone who wanted to "see" every waveform every minute. How hard could it be? Ha!
Starting at the input. After many 60kc pre-amp designs [ref 3-6] stealing the loopstick from the modules a 4 stage JFET amp was the first success (mpf102 then bf862 then 2sk932).
Fig 3 Early version of 60kc preamp that worked.
But what made sense and worked ok was to simply connect a high input impedance follower right after the (1/2 lattice) xtal filter on the modules. This gave a good (+10dbc) signal to work with and an AGC for free (part of CME6005 chip on module).
Fig 4 Preamp and loopstick Fig 5 CME6005 module
Fed this into a familiar Tayloe mixer [ref 7]/si5351 combination via very low cost ethernet xfrmr [ref 9]. This provided plenty of signal level albeit still unwanted interference even with the xtal filter.
Fig 6 Front end schematic (Ra=10k) Fig 7 At xfrmr secondary on a good day.
Big spike is LO. 50ohm loading from SA may effect this.
Forced me to throw away a big UPS, a few switching wall warts (replaced with toroidal xfrmr linear ps feeding lab bus bar), and become more "electrically aware" of my neighbors (solar wasnt a problem but heater is).
Fig 8 Neighbor's heater Fig 9 UPS noise Fig 10 NIST heading taped to
my floor for best signal
Mixed 60kc down to a 100Hz low-IF. My human demod-detection skills did not bode well for decoding what I saw on my scope.
Fig 11 "I" channel
So fed into PC sound card and ..learned GRC.. Tried/learned all sorts of digital filter/pll/demod/pll techniques. But what worked best was a decimating raised cosine matched filter feeding a costas loop [ref 10]. Now I can finally "see" the bits - both BPSK and PWM. Next is how to decode.
Fig 12 GRC Costas loop output
Tried various on PC C-code trying to decode Costas loop/GRC output and synchronize to the 1 bit per second data clock. Some hand waving to sync by looking at bit trailing edges on BPSK sign swings. Saw 13-bit sync word and time bits right away [ref 13] but what about the 5 ECC correction bits? Wasted another week of my life diving into Hamming check sum/correction. Rolled one from scratch using [ref 11,12] (not obvious!). Given the high error rate I do not think this was worth it. Sanity checking the decoded time proved much more useful. Ecc often passed even when the time was way off. At this point I ported/moved all the GRC to an ESP32 which seemed to work just fine. Initially connecting the 100Hz low-IF to the 10bit ADC on a ESP32S2 proved ok. Wanted a nicer display but this did not provide access to ADC. So took a TI AIC3254 I2S from another project and connected up BCLK/WS/DOUT to the ESP32S3 (MCLK provided by same si5351 driving mixer).
Fig 13 Back (RF top half and 9V step up not used)
Wasted more time with (counterintuitive) LVGL to natively work with ($25 7inch esp32s3 combo) display.
Fig 14 Front
Other mods to try to keep the graphics intensive LCD operations on one CPU while using the other for I2S and WWVB processing resulted in the final "product". WWVB signal quality varies wildly from day to day. Ive tested from No Cal and Death Valley. Will take it along as I travel..
Fig 15 My SNR measurement vs UTC (near two rock ranch)
If this project was only for 60kc wwvb there are many cost reductions and optimizations that could be had. But I have to go back to real work. TBD: update PCB; figure how to lock si5351 phase (freq does track), i.e., wwvbdo; maybe straighten up my lab. Ha! ..and if I could get a signal, eLoran anyone?
Fig 16 Rev B. Used esp32s2 module for wifi/fcc cert.
drives 3.5in LCD directly.
Fig 17 Rev B preamp.
Loopstick and CME6005/JFET follower fit in PVC
Fig 18 Rev B front w/ 3.5in display
/w opt gps module connected for TZ
Fig 19 Rev B front w/ 7in display
/w opt gps module connected for TZ

References:

1. https://www.xtcn.com/yawwvb/CME6005-A18.pdf
2. https://www.xtcn.com/yawwvb/
3. https://www.arrl.org/files/file/QEX_Next_Issue/2015/Nov-Dec_2015/Magliacane.pdf
4. https://www.worldradiohistory.com/Archive-DX/Ham%20Radio/70s/Ham-Radio-197312.pdf  This is an amazing little circuit but I could not keep it from oscillating for 60kc. Used "hot" xsistors 2SC3357
5. https://www.eevblog.com/forum/rf-microwave/wwvb-preamp-help/
6. https://www.burningimage.net/clock/sensitive-60khz-receiver/ and http://www.marvellconsultants.co.uk/DCF/
7. https://norcalqrp.org/files/Tayloe_mixer_x3a.pdf  Used https://www.diodes.com/datasheet/download/PI3B3253.pdf for switch
8. https://everset.tech/wp-content/uploads/2014/11/ES100DataSheetver0p97.pdf At most only decodes every other frame/minute.
9. xfrmr speced for 100kc-100mc. 6db loss @60kc. Early designs used ISDN xfrmrs I had on hand with no loss. https://www.xtcn.com/yawwvb/pulse_PE65575-2904661.pdf But nothing as cheap ($0.10) as https://www.xtcn.com/yawwvb/etherxfrmrC7501941.pdf
10. Costas loop design https://ez.analog.com/cfs-filesystemfile/__key/communityserver-discussions-components-files/333/Costas-Loop.pdf?_=637218102685428736
11. https://www.xtcn.com/yawwvb/NIST-Enhanced-WWVB-Broadcast-Format-1_01-2013-11-06.pdf
12. https://eng.libretexts.org/Bookshelves/Electrical_Engineering/Introductory_Electrical_Engineering/A_First_Course_in_Electrical_and_Computer_Engineering_(Scharf)/07%3A_Binary_Codes/7.05%3A_Hamming_Codes_for_Channel_Coding
13. The hourly correct frame count is "46" at most because of the 12 special frames/hr according to [ref 11] and because of the way I look for sync then look back 60 bits. Fix+add support for special low SNR frames:TBD
14. WWVB: A Half Century of Delivering Accurate Frequency and Time by Radio https://pmc.ncbi.nlm.nih.gov/articles/PMC4487279/  (as a kid I did summer camp there at Van Ness and Conn Ave)

[ref code] Obviously uses various pieces from my own libraries and other projects. Sorry for the mess.  What would Claude say? Will clean up later.  
Here is the meat clock.c (esp32 build env to follow), gerber+drill zip file, bom, top placement, pcb notes. 

[other stuff] https://www.co.tt

'I no longer wish to be limited to the clouds.' - Star Trek 1969 'The Cloud Minders'
"I no longer wish to be limited to the clouds." - Star Trek 1969 "The Cloud Minders"
Copyright © 2025-2026 Department C Inc