HGG Subproject: DCF77 Timing Module
This is a draft for a documentation of the work that @rel0c8 and @hdznrrd from shackspace did to implement a timing module for the HGG.
We got into some issues when implementing the module. What we did, what we found and how we solved it and why we thought that the things we did are a good idea should be described in this document. If you don't understand things, please ask @rel0c8 or armin [_at_] shackspace.de .
DCF77 and Further Reading
DCF77 is a timing synchrinisation system used in western europe and operated by the Physikalisch Technische Bundesanstalt in Braunschweig, Germany. Further Information on DCF77 can be found in the Wikipedia Article http://de.wikipedia.org/wiki/DCF77.
The modules we used to receive the dcf77 signal were bought at Conrad Electronics and can be found in their online shop (http://www.conrad.de/ce/de/product/641138/DCF-EMPFAENGERPLATINE, article Number 641138-62). The datasheet did not contain much valuable information and can be gotten on the website. The module operates at 3-15 Volts, we used 5 Volts since that's the Voltage we also use for our Atmega Microcontrollers. The module has an Open Collector output which means it should be used with a pullup resistor.
Getting the module to work
The module comes completely assembled with an Antenna. The Antenna should be aligned so that the long side shows to Frankfurt, Germany. The modules did not work properly if the short side was directed to Frankfurt, Germany and best if the long side was.
The module has a pin Header with 4 Pins, Vcc and Ground are just plugged in. We found that the module was delicate to even small fluctuations in the operating voltage. Only when we had a superstable input voltage, the signal was useable. Even the small Variations that can come out of a laptop USB port were enough to cause interference.
We originally tried to use the module against the internal pull-up resistors of the Atmega. Didn't work out well. We found that it was best to use external Pull-Up Resistors and that 47 kOhms works best.
What happens when the module sucks around?
When the module sucks around, which happens (as told before) more ofthen with wrong pull ups or bad in-voltage, the signals on the Output AND the inverted output just have a short signal edge for a short time and then revert back.
What to do if the module sucks around?
The tips already given are part 1 of the cure to this problem.
* Have a good input voltage that is super stable. * Use external 47 kOhm pull up resistors on both output pins, even if you just use one of them. * Operate the module with the antenna aligned to Frankfurt, Germany (that's actually where the signal is sent from) * Keep the module in a box during operation, don't touch it, keep a few meters away from it.
We found that it was almost impossible to use the module without getting into sucky mode at times. Since we want a constant synchronisation of out internal ground station clocks with the external clocks, we discarded the plan to use a straightforward algorithm for reading the signal from the module and thought of one that can sample the signal in a more efficient way that is less prune to signal errors.
How DCF77 tells us the time
DCF77 sends one bit per second. When the bit starts it means that a new second is starting. There will be 59 Bits coming per minute, the 60th will not be sent. The missing bit indicates that a new minute starts with the next incoming second. For each second the signal can be DOWN either 100 milliseconds or 200 milliseconds. A down of 100 milliseconds means a digital zero, a low of 200 milliseconds means a digital one. The way to get the time from the received bitstring after a minute can be read in papers on dcf77. If you're interested in the details, read further in the wikipedia article on dcf77 and the papers from the Physikalisch Technische Bundesanstalt in Braunschweig.
What happened with the signal
As previously said the problem is that the signal from the receiver just flips randomly. Since we know what to expect of the DCF77 signal we can filter most of the bad edges in the signal.
Since you need to know how long the pulse was, you need at least two measurements, one to find the beginning edge of the pulse and one to see if it was still down after a while.
FAIL#1: fails between two seconds
In this case the new second is expected too early.
FAIL#2: fails while the pulse should be down
In this case a second could be made from a 1 to a 0 and the information is just soo wrong.
FAIL #3: omits a pulse
This is very rare. A minute then ends too early and the next minute is also affected. Fortunately it almost never happened and the problem vanished completely with the 47 kOhm resistors.
FAIL #4: a random spike comes in the last (ommited) bit
Then it does not realise the minute ended at all…
And now for some nice imagery
images of the signal we expected (top line) and the signal we got (bottom one) can be found in this schematic.
As you can see, the fails of the module in a bad place can greatly screw up reading the signal.
Description of the Algorithm
The internal clock of the microcontroller is used. Thus we can determine how much time a second is (roughly). It seems safe to assume that the clock is at maximum 10 microseconds per second off because the clock runs at 16Mhz and we can expect +/- 10 parts per million from the crystals used to generate the clock.
Note: We decided to use the inverted input (for no apparent reason).
We wait for down edges and store the internal time when the pulse comes into a ringbuffer. We stay in this phase until the ringbuffer is full of valid entries. Entries are valid if the time delta between all the entries are 1 second +/- 10 msec appart.
If we have a ringbuffer full of valid entries, we go to the running phase.
We use this phase to predict when the next valid signal should come. This helps us to filter out random spikes in between the seconds and elliminates FAIL#1.
In the running phase we wait for the DOWN edge of the signal. If it's within the predicted timeframe we assume it's a valid peak. A state transition to a state that detects the zero.
In this phase over a time of about 80 msecs reading the signal for 15 times is tried. Thus we can find out if the down edge was just a short peak that was randomly in the predicted time. This solves FAIL#1 (partly) and FAIL#2. It then goes to a ONE-Detection-Phase. It basically makes the signal sampling robust against peaks within the 100 msec time the signal should be down.
In this phase the same as in the ZERO-Detection phase but if it detects the signal to be down in most samples for this timeframe, we note that we got a ONE-bit here, otherwise we got a ZERO-bit.
The minute break
If the peak was once ommited, we have a minute break. When the minute break comes up, we can decode the time for the current minute.
About the algorithm
I don't think you'll get it from the explanation, it's probably not good enough for that. Please read it, try to read the code and help improve it. Since I was part of writing the code, maybe i'm not the best person to tell other's what the point was. I hope i could anyway help with understanding what we did for this project.
The code can be found in the HGG repository