(This is part 2 in a small series on using DCF77 for accurate time keeping with an Arduino. You can find post #1 here and post #3 here)
Our DCF77 radio receiver picks up the DCF77 time signal from the low frequency transmitter located in Mainflingen near Frankfurt, Germany. The LF transmitter sends out Central European Time, CET or the Central European Summer Time, CEST. The DCF77 signal can be received in many parts of Europe.
The 77.5 kHz carrier signal is generated from local atomic clocks, and the time and date is encoded on top of this signal. A power drop of 100 ms indicates a 0, A power drop of 200 ms indicates a 1. The DCF output returns just these pulses.
bit (sec) |
Name | Meaning |
0 | M | Start of minute, always 0. |
1-14 | Civil warning bits. | |
15 | R | Call bit, set during abnormal transmitter operation |
16 | A1 | Summer time announcement. Set during hour before change. |
17-18 | Z1, Z2 |
01 when CEST is in effect. 10 when CET is in effect. |
19 | A2 | Leap second announcement. Set during hour before leap second. |
20 | S | Start of encoded time, always 1. |
21-27 | Minutes | |
28 | P1 | parity checksum over minute bits 21–27 |
29-34 | Hours 0–23 |
|
35 | P2 | parity checksum over hour bits 29–34 |
36-41 | Day of month.01–31 | |
42-44 | Day of week Monday=1, Sunday=7 |
|
45-49 | Month number 01–12 | |
50-57 | Year within century 00–99 | |
58 | P3 | parity checksum over date bits 36–57 |
(59) | – | No bit transmitted during last second of each minute |
Let us now look at the signal coming from the DCF77 receiver that we connected to the Arduino .
The code below samples the signal, and starts a new line every time the signal toggles from LOW to HIGH.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#define BLINKPIN 13 #define DCF77PIN 2 int prevSensorValue=0; void setup() { Serial.begin(9600); pinMode(DCF77PIN, INPUT); pinMode(13, OUTPUT); Serial.println("0ms 100ms 200ms 300ms 400ms 500ms 600ms 700ms 800ms 900ms 1000ms 1100ms 1200ms"); } void loop() { int sensorValue = digitalRead(2); if (sensorValue==1 && prevSensorValue==0) { Serial.println(""); } digitalWrite(BLINKPIN, sensorValue); Serial.print(sensorValue); prevSensorValue = sensorValue; delay(10); } |
When I run this, I get output such as this:
We see pulses that are roughly 100 ms, and pulses that are roughly 200 m. This is what we expect. Note that we also see one pulse-to-pulse time that is clearly longer than 1s, indicating the end of a time sequence. Note that the axis drawn above underestimates the elapsed time slightly, because a single loop takes a bit longer than 10ms.
So, what is the exact timing of the pulses? Let’s try the following program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#define BLINKPIN 13 #define DCF77PIN 2 int flankUp = 0; int flankDown = 0; int PreviousflankUp; bool Up = false; void setup() { Serial.begin(9600); pinMode(DCF77PIN, INPUT); pinMode(BLINKPIN, OUTPUT); } void loop() { int sensorValue = digitalRead(DCF77PIN); if (sensorValue) { if (!Up) { flankUp=millis(); Up = true; digitalWrite(BLINKPIN, HIGH); } } else { if (Up) { flankDown=millis(); Serial.print("Cycle: "); Serial.print(flankUp-PreviousflankUp); Serial.print(" Pulse :"); Serial.println(flankDown - flankUp); PreviousflankUp = flankUp; Up = false; digitalWrite(BLINKPIN, LOW); } } } |
Running this program give me the following output:
Notice that while the DCF specification says that pulses should be either 100 or 200 ms, we notice pulse lengths that are approximately 30ms longer. This is likely due to the hardware of the decoder together will the pull up and capacitor electronics. We will account for this in the DCF77 library, to get optimal differentiation between long and short pulses. What is more worrying, is we alos also a pulse that is too short and too early to be a time bit. In our library we will try to reject these spikes, based on their time of arrival.
In the next post I will discuss the DCF library but for now, if you’re not bored yet, have look at this website that continuously displays the signal broadcasted by DCF77:
http://www.dcf77logs.de/WebConsole
March 22, 2013 at 5:45 PM
Excellent job!
I have an Arduino UNO and the BN 641138 receiver, when I run both codes I get a small number of pulses and a small number of cycles. I can not see neither the 100 ms or 200 ms pulse. I believe that’s noise.Could you help me with this? Just so you know I am in Ravensburg, Germany so the location is not an issue.
April 1, 2013 at 2:57 PM
Since the time code is transmitted in the longwave range by amplitude modulation, it can therefore be easily disturbed, resulting in erroneous peaks. A source or RF noise is indeed the PC, the level of noise may depend on the shielding by the case.
I have been explained that noise may also creep up through the mains, either by picking up signal in the power lines or through the power supply. The latter I tried to minimize by using a by-pass capacitor. You could try using a bigger one and see if you AC power source works better. To minimize picking up signal, you can twist the cables going the DCF receiver
Another thing you can try is buying a better antenna:
http://fpga-xilinx.blogspot.nl/2012/04/your-6-hourly-digest-for-electronics_9462.html
March 28, 2013 at 5:46 PM
Hello again,
I changed the pull-resistor to 1K and used a 1.2-meter long twisted cable to get a decent reception. However, the signal is not as accurate as you depicted.
April 1, 2013 at 2:54 PM
Hi,
Is it sufficiently accurate? DCF77 is notoriously troublesome concerning signal quality. 🙁