This project is based on the prototype dealing with receiving and decoding WWVB time signal. The outcome is a digital clock that synchronizes itself with an atomic clock by using CME6005 receiver chip. The synchronization is performed once per day at time defined by software settings. With the used 32.768 kHz time keeping crystal the clock accuracy is within 3 sec during the day following a successful synchronization.
Schematic | Chassis | |||
![]() |
The heart of the clock is Microchip PIC16F914 microcontroller with built-in LCD driver. The LCDs are driven in static mode with 64 Hz refresh frequency. They can work from 3-5 volts, however, the best contrast is achieved by running them at 5V. For this purpose MAX1724 DC/DC converter is used, so the clock primary power source is 2xAA batteries. Tests showed that the converter efficiency is about 80%, which is very good. This way the clock consumes about 30 μA from batteries, so they could be able to power the clock literally for years. The microcontroller itself draws just about 3 μA if the LCDs are disconnected (LCD driver and TMR1 timer are on). The LCDs are pretty big (digit height is about 1.5") and connecting them to the PIC increases the drawing current up to 15 μA form a 5V source. When the CME6005 receiver is on the draw current from batteries goes up to 160 μA, but only for a couple of minutes needed for the time synchronization.
CME6005 receiver | MAX1724 & PIC boards | |
The CME6005 receiver is built on a similar board as in the prototype. This time I utilized the receiver's s Hold pin that puts on hold the internal AGC (Automatic Gain Control) circuit. This is absolutely needed to get rid of noise caused by PIC. It turns out, however, that working LCDs do not affect the reception at all, even if they are driven with 64 Hz frequency and there are a lot of wires leading to them from PIC, each emitting this low frequency. Furthermore, DC/DC converter also does not affect reception, since it is located pretty far away from the receiver. What really makes a problem is the PIC. If it is left running with working TMR1 timer and LCD driver, everything is OK and the reception is noise-free and stable. But once PIC starts to compute the length of the received pulse and run the time-setting algorithm, this results in a lot of short pulses in the receiver output signal, which makes receiving of the time signal impossible. The PIC is clocked by internal lower-power 31 kHz oscillator. I also tried other settings without a great success. To resolve the problem I ended up with building a brass screen around the receiver board and moving it to the opposite end of the chassis. The PIC is kept in sleep for most of the time, and upon waking up from sleep mode, it puts the receiver on hold by grounding its pin 14. This was absolutely necessary, as the receiver is not far enough away from PIC. Now, everything worked fine as I powered the circuit from a 1.5 V lab power supply. Another problem appeared as I attached the batteries. Initially they were planned to be mounted between the PIC and receiver boards on the chassis. However, because of the DC/DC converter the batteries also radiate electromagnetic pulses that influence the time signal reception. I found the only appropriate place for them on chassis right above the converter board oriented as shown on the image below and put into a brass box.
Back side | Finished device | |
To appear. |
---|
The clock has no interface for setting time. Right after powering up it turns into the time setting mode trying to synchronize itself with the WWVB time. The clock got 8 minutes for doing this. If the synchronization was not successful, it returns to time keeping mode and displays currently stored time. To force the clock to do another attempt one can press the Reset button. This way the CPU is reset and the embedded code starts over. The clock has no dots separating the hours and minutes and run in a 12-hour mode. For hours less than 10 the leftmost leading 0 is not shown and the corresponding LCD is blanked. The dot after the rightmost digit indicates PM.
The clock is assembled on 3 boards, whose layout in Eagle format is provided for download below. The boards are mounted on a perf-board from RadioShack. The LCDs are fixed with sockets on the back side of the chassis. The sockets are made from standard DIP-20 sockets by cutting them into two parts. All connections between the board and the LCD sockets are done by point-to-point method. The 4-pin connector on the main board is for in-circuit programming of PIC. The clock power during programming must be turned on.
The code is written in assembly language. The #define statements at the beginning set initial clock starting time (12:00 PM) and the time to perform synchronization. Currently is is 22:01 (10:01 PM), which works fine for spring. In general, it would be better to set it to 02:01 AM.
The time decoding routines are practically identical to the ones in the above mentioned prototype. The PIC runs from 31 kHz internal oscillator, and the time is kept by TMR1 clock stabilized with a 32.768 kHz crystal. In the time keeping mode the CPU is kept in sleep mode and the timer provides interrupts every 15 seconds. Upon counting 4 of those the minutes counter is incremented within an interrupt and the hours are updated accordingly. After waking up every 15 seconds the code checks for the update time and calls the corresponding routine syncTime() if needed. Node that the actual time synchronization starts at 22:01:45, or 15 seconds prior to sending the next sync pulse by the time server. These 15 seconds are needed for turning the receiver on and letting it stabilize.
The receiver output is sensed by pin PORTB:5, whose interrupt on change is used to wake up CPU from sleep. The interrupt is enabled at the beginning of syncTime() routine. Pin PORTB:5 is normally configured for output and is reconfigured for input right before enabling the interrupt. This is done to prevent switching of input at this pin that can raise a false interrupt flag. The switching is possible because of a long wire attached to this pin. I did not use a pulling-up resistor at this pin, since this would increase the power consumption.
The time signal decoding FSM form the prototype is extended with one state - state 3 - which the receiver enters after a successful reception of 60 time pulses. The main loop in syncTime() method periodically checks for reaching this state. If this happened the received time stored in variables min and hrs is copied to the main time keeping variables minutes and hours and time-keeping interrupt is triggered to reset seconds and start counting time from this setting. If the maximum number of synchronization attempts exceed the setting (currently the receiver got 8 minutes to perform synchronization), the method returns and the current clock time is not modified. The next synchronization will be automatically performed next day at the same time.
Last modified:Mon, Jan 23, 2023.