DCF77 - einfach erklärt
Das DCF77-Zeitsignal ist nicht kompliziert, leicht zu
entschlüsseln und wenn man einen fertigen Empfänger verwendet
auch elektronisch für jeden Anfänger zu handhaben. Diese
Empfänger haben quasi alle Elektronikhändler für unter
10 im Angebot, sie funktionieren alle ähnlich und liefern
am Ausgang des Empfängerschaltkreises fertig aufbereitete und
TTL-kompatible Digitalimpulse, die den aufmodulierten
Zeitimpulsen des Funksignals entsprechen. Man muß also keinerlei
Schwingkreise selbst zu bauen und benötigt keinerlei
HF-Kenntnisse.
Meistens findet man aber zur Erklärung des Signals nur einen
Link auf eine "Zeitscheibe", mit
der nicht jeder auf Anhieb was anfangen kann.
Deshalb nachfolgend der Versuch einer möglichst simplen
Erklärung was das bedeutet, wie man es auswertet und welche
Probleme häufig auftreten.
Wie wertet man diese Impulse aus:
Empfängt das Antennenmodul ein DCF77-Signal liefert es Ausgang
genau jede Sekunde ein Impuls, der zwischen 100ms und 200ms lang
ist. Der kürzere 100ms-Impuls entspricht einer logischen 0, der
200ms-Impuls entspricht einer logischen 1. Startet man also bei
der postiven Flanke eines Impulses einen Timer, kann dieser den
Signalzustand nach 150ms direkt in eine Variable speichern, die
dann entweder 0 oder 1 ist und damit dem gesendeten Bit
entspricht.
Der DCF77-Sender liefert so eine serielle Folge von 58 Bits, die
immer zu jeder vollen Minute neu startet und sich jede Minute
wiederholt.
Bis man ein komplettes Datenpaket empfangen hat vergehen also im
ungünstigsten Fall fast 2 Minuten, da die erste Minute nach dem
Einschalten ja nicht vollständig empfangen wurde.
Wie erkennt man den Beginn eines Datenpaketes?
Ganz einfach: daß 59ste Datenbit fehlt! Während man also
zwischen beliebigen Datenbits immer nur eine Pause < 1 Sekunde
hat, ist die Pause nach dem letzten/vor dem ersten Bit > 1
Sekunde, sogar mindestens 1,8 Sekunden lang.
Um den Datenpaketanfang herauszufinden kann man den Timer, der
nach 150ms den Bitzustand ermittelt, einfach weiterzählen
lassen. Mitten in Datenpaketen wird dieser spätesten alle
Sekunde zurückgesetzt und kann keine Werte größer 900ms
annehmen. Direkt vor Beginn eines neuen Datenpaketes zählt
dieser jedoch aufgrund des fehlenden 59sten Bits bis zu 1800ms
hoch.
Hat der Zählerstand also z.B. 1500ms überschritten kann man
einen Bit-Zähler zurücksetzen und weiß, daß das nächste
empfangene Bit das Bit Nr.1 eines neuen Paketes ist und daß dann
genau eine neue Minute beginnt. Diesen Zeitpunkt werde ich im
Folgenden als Synchronisationspunkt bezeichnen.
Hinweis: Alle empfangenen Zeitinfomationen beziehen sich auf den
Beginn der folgenden Minute!
Alle eingelesenen Zeiten sollten also erstmal nur in temporäre
Variablen geschrieben erst zum Synchronisationspunkt
übertragen/ausgegeben werden.
Bascom enthält z.B. vorgefertigte DCF77-Routinen und ein
Beispielprogramm, das einem alle Einzeldaten direkt nach Empfang,
also immer zu früh ausgeben - darum die Daten der richtigen
Minute zuzuordnen muß man sich selber kümmern, auf diese
Problematik wird meines Wissens in der Dokumentation aber auch
nicht hingewiesen!
Wie finde ich die Zeitinfomationen aus dem Datenpaket
heraus?
Hierbei kann jetzt die "Zeitscheibe"
behilflich sein, die einem die Bedeutung der Bits
veranschaulichen soll. Die wesentlichen Daten habe ich
nachfolgend mal zusammengefasst:
Die Sekunde gibt es im Protokoll garnicht - wie
auch, wenn ein Datenpaket eine knappe Minute braucht... Um die
Sekunden mitzuzählen setzt man einfach eine Sekundenvariable im
Synchronisationspunkt auf 0 und zählt diese bei jedem weiteren,
eintreffenden Impuls hoch. Praktisch: den Sekundenwert kann man damit später gleich als
Index/Pointer für die Bits des Datenpaketes benutzen! Wegen des fehlenden, 59sten-Bits springt die Uhr dann
natürlich von Sekunde 58 auf 0 um. Das Problem könnte man beheben, indem der Timer die Sekundenvariable bei Zählwert 1000ms ebenfalls um eins hochzählt.
Allerdings ist aus später erklärten Gründen dringend zu einer separaten Softclock zu raten und dann ist die Sekundenkorrektur überflüssig.
Die Minute findet man in den Bits 21 bis 27 in
BCD-Codierung. D.h. die ersten 4 Bit (Nibble) zeigen die
Einerstelle an, die oberen Bits geben die Zehnerstelle als
Binärzahl an. Wenn man sich damit auskennt ist es simpel die
Bits einfacheiner Variablen zuzuordnen, die man durch eine
Standardfunktion von BCD in andere Zahlenfomate umwandeln kann.
Um es auch für Anfänger verständlich zu halten will ich das
aber einfach als Additionsverfahren erklären:
Zu jedem Bit gehören Zahlenwerte, die man einfach aufaddiert,
wenn das entsprechende Bit = 1 ist. Also einfach eine temporäre
Minutenvariable vorher irgendwann auf 0 setzen (z.B. bei Bit 20,
dem Startbit) und dann einfach nach Liste bis Bit 27 die
Einzelwerte aufaddieren.
Minute = 0
Bit 21: Minute + 1
Bit 22: Minute + 2
Bit 23: Minute + 4
Bit 24: Minute + 8
Bit 25: Minute + 10
Bit 26: Minute + 20
Bit 27: Minute + 40
Die Stunde, den Kalendertag, den Monat und das Jahrt findet man in den folgenden Bits und
diese werden genauso berechnet wie der Minutenwert. Stunde und Kalendertag haben Maximalwerte von 24 bzw. 31, sind damit immer < 40 (24 und 31) und ist deshalb nur 6 Bits lang,
und benötigen nur jeweils 6 Bits, der Monat mit 12 als Maximalwert kommt sogar mit nur 5 Bits aus. Die Jahresangabe stellt nur die letzten beiden Ziffern des aktullen Jahrhunderts,
also z.B. eine 09 für 2009. Da innerhalb eines Jahrhunderts Werte bis 99 möglich sind ist die Jahresangabe um ein 8tes Bit erweitert, daß dem Dezimalwert 80 entspricht:
Stunde = 0
Bit 29: Stunde + 1
Bit 30: Stunde + 2
Bit 31: Stunde + 4
Bit 32: Stunde + 8
Bit 33: Stunde + 10
Bit 34: Stunde + 20
Tag = 0
Bit 36: Tag + 1
Bit 37: Tag + 2
Bit 38: Tag + 4
Bit 39: Tag + 8
Bit 40: Tag + 10
Bit 41: Tag + 20
Monat = 0
Bit 45: Monat + 1
Bit 46: Monat + 2
Bit 47: Monat + 4
Bit 48: Monat + 8
Bit 49: Monat + 10
Jahr = 0
Bit 51: Jahr + 1
Bit 52: Jahr + 2
Bit 53: Jahr + 4
Bit 54: Jahr + 8
Bit 55: Jahr + 10
Bit 56: Jahr + 20
Bit 57: Jahr + 40
Bit 58: Jahr + 80
Weitere Daten:
Paritybits: Am Ende des Minutenpaketes (Bit 28)
des Stundenpakets (Bit 35) und des gesamten Datums (Bit 58)
findet man Paritybits zur Fehlerprüfung des letzten Blocks. Wie
man Paritybits prüft findet man überall im Netz, für mich hat
es sich aber als zu unsicheres Kriterium zum Prüfen der
Übertragung erwiesen, weshalb ich nicht näher darauf eingehe.
Wochentag: der Wochentag, beginnend mit 1 für
Montag ist zwischen dem Kalendertag und dem Monat in den Bits 42;
43; 44 nach bekanntem Schema enthalten.
Sommerzeit: Ist Bit 15 = 1 erfolgt am Ende der
aktuellen Stunde eine Zeitumstellung. Bit 17 = 0 gibt Normalzeit
an, Bit 17 = 1 gibt Sommerzeit an. Bit 18 ist einfach invertiert
zu Bit 17.
Schaltsekunde: Ist Bit 19 = 1 wird am Ende der
aktuellen Stunde eine Schaltsekunde eingefügt - ist nur alle
paar Jahre der Fall.
Sonstiges: In den Bits 1-14 können
Katastrohenwarnungen enthalten sein, oder Wetterdaten. Um die
Wetterdaten zu entschlüsseln muß man aber eine Lizenz besitzen.
Das Bit 15 ist ein "Rufbit" womit der DCF77-Sender bei
Problemen Techniker alarmiert, die ihn reparieren. Diese Bits vor
Bit 20 werden in den meisten Anwendungen ignoriert. Bit0 und
Bit20 sind Startbits, Bit 0 ist immer 0 und Bit 20 ist immer 1
Wie ein µC-Programm einer DCF77-Uhr aufgebaut sein könnte:
- man programmiert sich einen frei laufenden Timer, der z.B. alle 10ms eine eigene Subroutine ausführt
Jetzt programmiert man sich zunächst eine frei laufende Uhr (Softclock) in den Timer, die die Anzahl der Timeraufrufe
aufaddiert, und ist diese = 100 eine Skundenvariable inkrementiert (um 1 hochzählt), bei 60 Sekunden eine Minutenvariable incrementiert usw.
Die Zeit dieser Uhr ist die einzig relevante und nur diese wird später angezeigt/ausgegeben. Auf die Variablen dieser Uhr wird
nachfolgend nicht weiter eingegangen und alle Variablennamen beziehen sich auf Zwischenvariablen, die mit der Softclock nichts zu tun haben
und nicht verwechselt werden dürfen.
- nun schließt man den Antennenimpuls an einen Hardwareinterrupteingang an (Pullup einschalten!) und definiert sich eine entsprechende Subroutine,
die bei der ersten Flanke eines eintreffenden Impulses ausgeführt wird. In dieser Routine inkrementiert man eine
Sekundenvariable und setzt eine Hundersttelsekundenvariable auf 0 - mehr nicht.
Diese Hundertstelsekundenvariable inkrementiert man ebenfalls bei jedem Timeraufruf und prüft sie dort am einfachsten mit If-Abfragen
auf folgende Zustände:
= 15: bedeutet 150ms des Eingangsimpulses sind vergangen und der Signalzustand des Eingangssignalpins kann als logische 0 oder 1 gelesen
werden. Welches Bit der oben angegebenen Bittabelle man gerade am Wickel hat sagt einem die Sekundenvariable, die bei jedem Impuls automatisch
inkrementiert wurde. Je nach Bedeutung des Bits addiert man nun die angegbenen Listenwerte zu den entsprechende Zeitvariablen für Minute, Stunde, Tag
usw. hinzu, oder schreibt den Bitzustand einfach in enstprechende BCD-Variablen (wenn man das versteht).
> 1500: bedeutet daß bei der nächsten Signalflanke eine neue Minute /ein neues Datenpaket beginnt, dies also ein Synchronisationspunkt ist
und die Sekundenvariable auf 0 gesetzt werden muß.
Das war es prinzipiell: gibt man jetzt die DCF77-Zeitvariablen z.B. mit jedem Sekundentakt (Impuls) auf dem Bildschirm aus, dann sieht
man die emfangenen "Rohwerte" und sieht, wie sich z.B. der Minutenwert bei jeder Sekunde zwischen 21 und 27 neu berechnet, danach aber konstant
bleibt während andere Variablen gerade geändert werden. Theoretisch könnten diese Zwischenwerte schon beim jeweils nächsten Synchronisationspunkt
(also am Ende eines kompletten Datenpaketes) in die Softclock übernommen werden - wenn da nicht die vielen Empfangsfehler wären...
Worauf man die DCF77-Zeiten prüfen sollte bevor man sie in die Softclock übernimmt folgt im Asnchluss:
Übertragungsfehler und Kausalitätsprüfung:
Impulszählung: Man kann zum Synchronistationszeitpunkt einfach gucken, ob seit dem letzten tatsächlich 58 Impulse eingetroffen sind.
Mancher wird sich wundern wie häufig das nicht so ist!
Pakete, bei denen das nicht stimmt könnte man prinzipiell als falsch verwerfen, wenn man allerdings nur an der Uhrzeit und nicht am Datum interessiert
ist verwirft man damit auch Pakete bei denen Minuten-/Stundeninfomationen noch korrekt empfangen wurden, sich aber beim Datum ein Fehler eingeschlichen hat.
Parityüberprüfung: Das DCF77-Zeitsignal liefert selbst 3 Paritybits mit, die man zur Prüfung der empfangenen Daten benutzen kann.
Allerdings kann ein Paritybit immer nur 2 Zustände besitzen 0 oder 1 und ist demnach bei Übertragungsfehlern in ca. 50% der Fälle
auch zufällig richtig. D.h. bei Prüfung aller 3 Paritybits, daß eines von 8 fehlerhaften Datenpaketen trotzdem immernoch zufällig
als korrekt anzeigt wird - nicht sehr sicher! Oft interessiert nur die Uhrzeit, man begnügt sich mit den beiden
Paritybits von Minuten- und Stundenblock und verzichtet auf Prüfung des Datumsblocks - und hat schon eine Fehlerwahrscheinlichkeit von 1:4!
Man könnte die Sicherheit etwas verbessern, indem man die Parity mehrerer Datenpakete in Folge prüft und nur wenn mehrere korrekt waren von
richtigen Daten ausgeht. Allerdings ist jedes einzelne ist mit einer Wahrscheinlichkeit von 1:8 falsch, d.h. bei x Datenpaketen steigt die
Fehlersicherheit auch nur in einfacher Ordnung um Faktor x.
Die Parity-Prüfung wird in Datenübertragungssystemen deshalb nur als einfache Erstkontrolle verwendet, um eindeutig falsche
Datenpakete sofort herauszufiltern. Sie ist aber ungenügend sicher um zu beweisen, daß ein Datenpaket wirklich korrekt war.
In der EDV benutzt man deshalb zur Erhöhung der Sicherheit andere Varianten wie Checksummenprüfung u.a. die mögl. viele Daten einbeziehen.
Das DCF77-Signal liefert solche Fehlerprüfungsmöglichkeiten nicht - braucht es aber auch nicht, weil sich die Möglichkeit etwas viel
besseren bietet:
Kausalitätsprüfung: Völlig anders als bei den meisten anderen Datenübertragungssystemen bietet ein stetig gesendetes Zeitsignal
einen erheblichen Vorteil: hat man ein Paket gelesen weiß man schon im voraus, wie das nächste aussehen müßte! Eines steht unter normalen Raum/Zeit-Bedingungen
nämlich fest: nach einer Minute ist man ca. eine Minute älter!
D.h. der Minutenwert jedes Datenpaketes muß innerhalb einer Stunde immer genau um 1 größer sein als beim letzten Datenpaket.
Die Wahrscheinlichkeit, daß ein fehlerhaftes Datenpaket damit zufällig genau um 1 größer ist beschränkt sich damit nicht etwa nur auf
1:60 - sondern beträgt sogar 1:100, da bei Fehlern beide Stellen der Sekunde von 0-9 ergeben könnten.
Diese Prüfung liefert beim Stundenumschlag dafür natürlich auch sicher immer einen Fehler, was ist bei Verwendung einer Softclock quasi egal ist.
Man kann die Fehlersicherheit noch erhöhen, indem man nicht nur die Minuten einer Stunde berücksichtigt, sondern die Stunden hinzunimmt.
D.h. man berechnet zunächst wieviele Minuten der Tag schon alt ist: Stunden x 60 + Minuten. Da hier alle 4 Digits stimmen müssen,
ergibt sich eine Fehlerwahrscheinlichkeit von 1:10000 und das ist schon brauchbar!
Wenn man das Datum auswerten will empfiehlt es sich dieses auch hinzuzuziehen und einfach alle Dezimalstellen von Jahr, Monat, Tag, Stunde und Minute
hintereinander zu schreiben - auch dieser Wert muß bei jedem Folgenden Datenpaket um genau 1 größer sein als beim letzten Paket und das liefert
lediglich beim Stunden-/Tages-/Monats-/Jahreswechsel prinzipbedingte Fehler, dafür aber extrem große Sicherheit.
Kommt es einem nicht darauf an, daß sich die Uhr unbedingt schnell synchronisiert kann man natürlich auch über 3, 4 oder
nochmehr Minuten hinweg prüfen, ob alle Datenpakete jeweils korrekt eine Minute mehr als das letzte angezeigt haben und die
Fehlerwahrscheinlichkeit sinkt in Potenz der Anzahl! D.h. die Wahrscheinlichkeit, daß 3 aufeinanderfolgende, falsche Tagesminutenwerte
genau so emfangen wurden, daß die Werte zufällig genau aufeinaderfolgen beträgt schon ohne Berücksichtigung des Datums 1:100000000...
Ausreichend, würde ich sagen und gut genug um sich die Paritätsprüfung und Impulszählung gleich ganz zu sparen!
Aber man muß aufpassen: treibt man es zu weit, synchronisiert sich die Uhr nach dem Einschalten über mehrere Stunden hinweg oder gleich
garnicht mehr, weil zu häufig ein falsches Datenpaket dazwischenflutscht. Nach meinen einführenden Behauptungen, daß of mal 9 von 10 Datenpaketen unbrauchbar sind, dürfte eine
solche Variante garnicht mehr synchronisieren. Allerdings habe ich bei praktischen Tests festgestellt, daß die Störeinflüsse über den
Tag hinweg stark variieren, daß zeitweise extrem häufig Fehler auftreten, während gelegentlich gleich 10-20 Pakete korrekt empfangen werden.
Das hängt möglicherweise mit der zufälligen, zeitgleichen Reduzierung äußerer Störquellen zusammen, ermöglicht aber auch bei erhöhten
Anforderungen eine gelegentliche Synchronisation der Uhr.
Ich habe es mal mit einer 5-Minuten-Folgenprüfung ausgetestet und diese Prüfung hat die Uhr gerade 2-3mal
in 24h bestanden, entsprechend würde sich die Softclock nach dem Einschalten z.B. erst nach 8-12 Stunden synchronisieren!
Wieviel sicherheit für euch sinnvoll erscheint bleibt Euch überlassen und hängt auch von der Empfangsqualität in Eurer Gegend ab.
Rein rechnerisch sollten 2-3 sinnvoll aufeinanderfolgende Zeitwerte aber völlig ausreichen, um das zuletzt empfangene als
definitiv korrekt zu verarbeiten und die Softclock danach zu stellen.
Die häufigsten Fehler, wenn das Programm nicht funktioniert:
Diese Datei wird momentan noch bearbeitet und sollte täglich
etwas "fertiger" werden...