DCF77-Empfänger zur Uhrzeitsynchronisation

Zur Synchronisation von zwei oder mehr Uhrzeitmodulen (RTCs - Real Time Clocks) untereinander bzw. zur Korrektur der Gangungenauigkeit einzelner RTCs möchte ich die Uhrzeitsignale verwenden, die von "Atomuhren" ausgehend, in Telegrammen versendet werden. Im ersten Schritt möchte ich daher versuchen, solche Telegramme zu empfangenen, mit einem Arduino daraus Datums- und Uhrzeitbits zu extrahieren, diese zu dekodieren und anschließend auf einem Display zu visualisieren oder kurz gesagt: Datum und Uhrzeit emfpangen und anzeigen.

Vom Langwellensender DCF77 in Mainflingen in der Nähe von Frankfurt am Main werden mit einer Sendefrequenz von 77,5 kHz die meisten funkgesteuerten Uhren im westlichen Europa mit der aktuellen Uhrzeit versorgt. Der Sender sendet mit einer Leistung von 50 kW (Abstrahlleistung ca. 30 - 35 kW) und hat eine Reichweite bis zu 2000 km.

Die Zeitinformationen werden amplitudenmoduliert übertragen, dabei wird die Trägeramplitude im Sekundentakt auf ca. 15 % abgesenkt. Die Dauer der Absenkung beinhaltet die digitale Information, wobei eine Absenkung mit einer Dauer von 100 ms einer logischen "0" und mit einer Dauer von 200 ms einer logischen "1" entspricht.

Abbildung 1-1: Amplitudenmoduliertes Signal des Langwellensenders DCF77


Mit einem z.B. bei Conrad Electronic erhältlichen DCF77-Empfängerplatine BN641138 (siehe Abbildung 2-1) können die amplitudenmodulierten Zeitinformationen empfangen und z.B. mit einem Arduino dekodiert und zur Anzeige gebracht werden.

Abbildung 1-2: DCF77-Empfängerplatine BN641138 von Conrad Electronic


Anschlussbelegung des DCF-Empfänger BN641138:

1: GND

2: VDD 2,5 - 15 V =

3: DCF-Ausgang Open Collector

4: DCF-Ausgang invertiert Open Collector


Telegramm:

Eine vollständige Übertragung des Telegramms dauert 60 Sekunden. Zur Synchronisierung des Auswertungsprogrammes mit dem Telegramm wird dabei die 59. Sekunde (ohne Sekundenmarke, d.h. ohne Absenkung der Trägeramplitude) des vorangegangenen Telegramms verwendet. Am Beginn der ersten Sekunde (Sekunde 0) wird immer eine logische "0" gesendet (Trägersignalabsenkung 100 ms). Mit dieser Zeitmarke können die übertragenen und geprüften Informationen des vorangegangenen Telegramms bei Fehlerfreiheit als Zeitinformation übernommen werden. Das heißt, in jeder Minute wird die Zeitinformation für den Beginn der nächsten Minute übertragen. Danach folgen im Sekundenzyklus 15 Bits, die für Datum- und Uhrzeit keine Bedeutung haben. Ab Bit 16 werden Informationen übertragen, ob die Uhrzeitangabe Mitteleuropäische Zeit (MEZ) oder Mitteleuropäische Sommerzeit (MESZ) ist und ob eine Schaltsekunde eingefügt wird. Die eigentlichen Datums- und Uhrzeitinformationen werden mit den Bits 20 bis 58 übertragen, wobei dazwischen auch Paritätsbits für Minute, Stunde und Datum eingefügt sind. Bei einer Minute mit Schaltsekunde wird zu Beginn der 59. Sekunde eine "0" und zur eingefügten 60. Sekunde keine Sekundenmarke gesendet.


Zeitlicher Ablauf eines Telegramm, wobei beim DCF77-Empfänger BN641138 das Telegramm am Ausgang 3 nicht invertiert und am Ausgang 4 invertiert zur Verfügung steht:



Abbildung 1-3: Ausgangssignale des DCF77-Empfänger BN641138 


Die im Telegramm übertragenen Bits haben folgende Bedeutung und Bitwertigkeit:

Abbildung 1-4: Bedeutung und Werigkeit der einzelnen Bits eines Telegramms


Um an die gesendeten Informationen für Datum und Zeitangaben zu gelangen, müssen die Bitfolgen zuerst dekodiert werden.

Im nachfolgenden Beispiel wird die Dekodierung der Bitfolge für die Minute gezeigt. Dabei werden die Bits 21 bis 27 mit ihren vorgegebenen Bitwertigkeiten multipliziert und anschließend die Einzelergebnisse summiert:

Abbildung 1-5: Beispiel der Dekodierung der Bitfolge für die Minute


In gleicher Weise erfolgt die Dekodierung der Stunde, des Kalendertags, Wochentags, Monats und des Jahres.


Paritätsüberprüfung:

Die Paritätsüberprüfung erfolgt auf gerade Parität. Die gesendeten Paritätsbits für Minute, Stunde und Datum enthalten also jene Werte, die erforderlich sind, dass die zu prüfenden Bits eine gerade Anzahl von "1en" ergeben. Im obigen Beispiel würde also das gesendete Paritätsbit (Bit 28) eine "0" beinhalten, da die Anzahl der gesendeten "1er" (4 x) eine gerade Zahl ist.

Zur Überprüfung sind daher mit den gesendeten Minuten-, Stunden- und Datumsbits die Paritäten neu zu ermitteln und die Ergebnisse mit den gesendeten Paritätsbits zu vergleichen. Wenn die ermittelten und gesendeten Paritätsbits nicht übereinstimmen, ist davon auszugehen, dass die Übertragung fehlerhaft war. Stimmen die Paritätsbits dagegen überein, ist eine fehlerfreie Übertragung zwar wahrscheinlich, aber trotzdem nicht gesichert. Um die Sicherheit zu erhöhen, kann man z.B. die Werte erst dann übernehmen, wenn sich die Werte mit dem nächsten Telegramm bestätigen, wobei da natürlich berücksichtigt werden muss, dass die Zeit inzwischen um 1 Minute weitergelaufen ist.


Testaufbau:

Verwendete Bauteile:

  • 1 Arudino Uno
  • 1 DCF-Empfänger BN641138
  • 1 LED
  • 1 Widerstand 10 kOhm (Pullup-Widerstand R > VDD / 1 mA)
  • 1 Widerstand 220 Ohm


Beschaltung des DCF-Empfänger BN641138:

1: GND

2: VDD 5V=

3: DCF-Ausgang Open Collector --> Arduino Digitalpin 2

4: DCF-Ausgang invertiert Open Collector --> nicht benutzt


Abbildung 1-6: Testaufbau zur Überprüfung, ob das Signal empfangen wird


Einfaches Testprogramm, ob das Sendesignal empfangen wird:

Das nachfolgende Programm bringt bei Empfang des Sendesignals im Sekundentakt die LED zum Blinken, wobei die Leuchtdauer der LED, entsprechend der gesendeten Informationen, entweder 100 oder 200 ms lang ist. Der Zeitunterschied von 100 ms ist mit dem Auge noch erkennbar.

Allerdings gab es bei mir einige Schwierigkeiten, bevor sicht das gewünschte Blinken einstellte:

In meiner Testumgebung (Wohnbereich) habe ich nur in einem beschränkten Umfeld Empfang. Ob es an der Lage meines Wohnorts liegt, der unmittelbar in nordwestlicher Richtung - also meinem Fall Richtung Frankfurt - von Bergen eingeschlossen ist, den dicken Ziegelmauern meiner Räme und/oder die Entfernung von Frankfurt ca. 700 km beträgt, weiß ich nicht. Bis ca. 600 km soll das Signal als Bodenwelle zu empfangen sein, ab etwa 1100 km soll der Raumwellenanteil überwiegen. Im Bereich zwischen 600 km und 1100 km vom Sender soll es bei gleichen Feldstärken von Boden- und Raumwelle zur Auslöschung des Signals kommen können. So kann ich nur direkt an Fenstern den Empfang herstellen.

Und noch ein Problem: Mit der Stromversorgung des Arduino über die USB-Schnittstelle meines Laptops funktionierte der Empfang überhaupt nicht. Die LED blinkte mit unterschiedlichen Frequenzen zwischen 3 und 5 Hz. Anscheinend verursacht mein Laptop so viele Störsignale, dass an einen Empfang nicht zu denken ist. Abhilfe schaffte ich, dass ich zuerst den Arduino über eine Batterie mit Strom versorgte und später mit einem Steckernetzteil. Der Nachteil beider Varianten: Leider keine Verbindung mehr zum Seriellen Monitor und lästiges An- und Abstecken des USB-Steckers bei jeder Programmänderung.


//DCF77_Signaltest.ino
//Code fuer Arduino
//Author Retian
//Version 1.0

#define signalPin 2
#define ledPin 3

char dcf77Signal;
char altSignal;

void setup() {
  pinMode(signalPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  dcf77Signal = digitalRead(signalPin);
  if (dcf77Signal != altSignal)
  {
    digitalWrite(ledPin, dcf77Signal);
    altSignal = dcf77Signal;
  }
}


Hier geht's weiter ....