DCF77: Wie funktioniert das genaue Zeitsignalübertragungssystem?

Hallo Habr.

Wahrscheinlich haben viele Leute, die eine Uhr oder eine Wetterstation kaufen, das Logo der ferngesteuerten Uhr oder sogar die Atomuhr auf der Verpackung gesehen. Dies ist sehr praktisch, da es ausreicht, die Uhr auf den Tisch zu stellen, und nach einer Weile werden sie automatisch auf die genaue Zeit eingestellt.



Mal sehen, wie es funktioniert und einen Decoder in Python schreiben.

Es gibt verschiedene Zeitsynchronisationssysteme. Das beliebteste in Europa ist das deutsche DCF-77-System , Japan hat ein eigenes JJY- System, die USA haben ein WWVB- System und so weiter. Darüber hinaus handelt es sich um DCF77, das an einigen Orten im europäischen Teil Russlands und in den Nachbarländern am relevantesten und für den Empfang zugänglich ist (die Bewohner des Fernen Ostens mögen die gegenteilige Meinung vertreten, können jedoch wiederum das japanische Signal akzeptieren und analysieren;).

Alles, was unten geschrieben steht, handelt von DCF77.

Signalempfang


DCF77 ist eine langwellige Station, die mit einer Frequenz von 77,5 kHz arbeitet und Signale in Amplitudenmodulation überträgt. Die Station mit einer Leistung von 50 kW befindet sich 25 km von Frankfurt entfernt und wurde bereits 1959 in Betrieb genommen. 1973 wurden die Datumsangaben zur genauen Uhrzeit hinzugefügt. Die Wellenlänge bei einer Frequenz von 77 kHz ist sehr groß, daher sind auch die Abmessungen des Antennenfeldes sehr anständig (Foto aus Wikipedia):



Mit einer solchen Antenne und Stromversorgung deckt der Empfangsbereich fast ganz Europa, Weißrussland, die Ukraine und einen Teil Russlands ab.



Jeder kann ein Signal aufnehmen. Gehen Sie dazu einfach zum Online-Empfänger http://websdr.ewi.utwente.nl:8901/ , wählen Sie dort die Frequenz 76,5 kHz und die USB-Modulation aus. Ein Bild von so etwas sollte sich öffnen:



Dort drücken wir den Download-Button und nehmen ein mehrere Minuten langes Fragment auf. Wenn Sie einen „echten“ Empfänger haben, der eine Frequenz von 77,5 kHz aufnehmen kann, können Sie ihn natürlich verwenden.

Wenn wir über das Internet Funksignale der genauen Zeit empfangen, erhalten wir natürlich keine wirklich genaue Zeit - das Signal wird mit einer Verzögerung übertragen. Unser Ziel ist es jedoch nur, die Struktur des Signals zu verstehen. Dafür ist die Internetaufzeichnung mehr als ausreichend. Im wirklichen Leben werden natürlich spezielle Geräte zum Empfangen und Decodieren verwendet, auf die weiter unten eingegangen wird.

Also haben wir den Datensatz, fangen wir an, ihn zu verarbeiten.

Signaldecodierung


Laden Sie die Datei mit Python herunter und sehen Sie sich ihre Struktur an:
from scipy.io import wavfile from scipy import signal import matplotlib.pyplot as plt import numpy as np sample_rate, data = wavfile.read("dcf_websdr_2019-03-26T20_25_34Z_76.6kHz.wav") plt.plot(data[:100000]) plt.show() 

Wir sehen eine typische Amplitudenmodulation:



Um die Decodierung zu vereinfachen, nehmen wir die Hüllkurve des Signals mit der Hilbert-Transformation:

 analytic_signal = signal.hilbert(data) A = np.abs(analytic_signal) plt.plot(A[:100000]) 

Ergebnis in vergrößerter Ansicht:



Wir glätten die Interferenzemissionen mithilfe eines Tiefpassfilters. Gleichzeitig berechnen wir den Durchschnittswert, der später zum Parsen nützlich sein wird.

 b, a = signal.butter(2, 20.0/sample_rate) zi = signal.lfilter_zi(b, a) A, _ = signal.lfilter(b, a, A, zi=zi*A[0]) avg = (np.amax(A) + np.amin(A))/2 

Ergebnis (gelbe Linie): Ein fast rechteckiges Signal, das ziemlich einfach zu analysieren ist.



Parsen


Zuerst müssen Sie die Bitfolge erhalten. Die Signalstruktur selbst ist sehr einfach.



Impulse werden in zweite Intervalle unterteilt. Wenn der Abstand zwischen den Impulsen 0,1 s beträgt (dh die Impulslänge beträgt 0,9 s), fügen Sie der Bitsequenz „0“ hinzu. Wenn der Abstand 0,2 s (dh 0,8 s Länge) beträgt, fügen Sie „1“ hinzu. Das Ende jeder Minute wird durch einen "langen" Impuls angezeigt, der 2 Sekunden lang ist, die Bitsequenz wird auf Null zurückgesetzt und das Füllen beginnt erneut.

Das Obige ist einfach in Python zu schreiben.

 sig_start, sig_stop = 0, 0 pos = 0 bits_str = "" while pos < cnt - 4: if A[pos] < avg and A[pos+1] > avg: # Signal begin sig_start = pos if A[pos] > avg and A[pos+1] < avg: # Signal end sig_stop = pos diff = sig_stop - sig_start if diff < 0.85*sample_rate: bits_str += "1" if diff > 0.85*sample_rate and diff < 1.25*sample_rate: bits_str += "0" if diff > 1.5*sample_rate: print(bits_str) bits_str = "" pos += 1 

Als Ergebnis erhalten wir eine Folge von Bits. In unserem Beispiel sieht es zwei Minuten lang so aus:

0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000


Interessant ist übrigens, dass das Signal eine „zweite Datenschicht“ enthält. Die Bitfolge wird auch mittels Phasenmodulation codiert. Theoretisch sollte dies auch bei einem geschwächten Signal zu einer stabileren Decodierung führen.

Unser letzter Schritt: Holen Sie sich die tatsächlichen Daten. Bits werden einmal pro Sekunde übertragen, sodass wir nur 59 Bits haben, in denen viele Informationen codiert sind:



Die Bits sind auf Wikipedia beschrieben und ziemlich neugierig. Die ersten 15 Bits werden nicht verwendet, obwohl geplant war, sie für Warnsysteme und den Zivilschutz zu verwenden . Bit A1 zeigt an, dass in der nächsten Stunde die Uhr auf Sommerzeit eingestellt wird. Bit A2 zeigt an, dass in der nächsten Stunde eine zusätzliche Sekunde hinzugefügt wird, die manchmal verwendet wird, um die Zeit entsprechend der Erdrotation zu korrigieren. Die verbleibenden Bits codieren Stunden, Minuten und Datum.



Für diejenigen, die alleine experimentieren möchten, wird der Code zum Decodieren unter dem Spoiler angegeben.

Quellcode
 def decode(bits): if bits[0] != '0' or bits[20] != '1': return minutes, hours, day_of_month, weekday, month, year = map(convert_block, (bits[21:28], bits[29:35], bits[36:42], bits[42:45], bits[45:50], bits[50:58])) days = ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday') print('{dow}, {dom:02}.{mon:02}.{y}, {h:02}:{m:02}'.format(h=hours, m=minutes, dow=days[weekday], dom=day_of_month, mon=month, y=year)) def convert_ones(bits): return sum(2**i for i, bit in enumerate(bits) if bit == '1') def convert_tens(bits): return 10*convert_ones(bits) def right_parity(bits, parity_bit): num_of_ones = sum(int(bit) for bit in bits) return num_of_ones % 2 == int(parity_bit) def convert_block(bits, parity=False): if parity and not right_parity(bits[:-1], bits[-1]): return -1 ones = bits[:4] tens = bits[4:] return convert_tens(tens) + convert_ones(ones) 


Wenn wir das Programm ausführen, sehen wir ungefähr Folgendes:

0011110110111000001011000001010000100110010101100010011000
Tuesday, 26.03.19, 21:41
0001111100110110001010100001010000100110010101100010011000
Tuesday, 26.03.19, 21:42


Eigentlich ist das alles Magie. Der Vorteil eines solchen Systems besteht darin, dass die Decodierung äußerst einfach ist und auf jedem der unkompliziertesten Mikrocontroller durchgeführt werden kann. Zählen Sie einfach die Länge der Impulse, akkumulieren Sie 60 Bits und am Ende jeder Minute erhalten wir die genaue Zeit. Im Vergleich zu anderen Methoden der Zeitsynchronisation (z. B. GPS oder Gott bewahre das Internet :) benötigt eine solche Funksynchronisation praktisch keinen Strom - zum Beispiel arbeitet eine gewöhnliche Wetterstation zu Hause etwa ein Jahr lang mit 2 AA-Batterien. Daher wird sogar eine Armbanduhr mit Funksynchronisation hergestellt, ganz zu schweigen von einer Wand- oder Straßenstation.

Der Komfort und die Einfachheit von DCF ziehen Liebhaber hausgemachter Produkte an. Für nur 10 bis 20 US-Dollar können Sie ein fertiges Modul von einer Antenne mit einem fertigen Empfänger und einem TTL-Ausgang kaufen, der an einen Arduino oder einen anderen Controller angeschlossen werden kann.



Für Arduino wurden bereits vorgefertigte Bibliotheken geschrieben. Es ist jedoch bereits bekannt, dass Sie unabhängig davon, was Sie auf dem Mikrocontroller tun, entweder eine Uhr oder eine Wetterstation erhalten. Mit einem solchen Gerät ist es sehr einfach, die genaue Uhrzeit zu ermitteln, vorausgesetzt, Sie befinden sich im Empfangsbereich. Nun, Sie können die Aufschrift „Atomic Clock“ an die Uhr hängen und gleichzeitig allen, die es wollen, erklären, dass das Gerät wirklich mit einer Atomuhr synchronisiert ist.

Wer möchte, kann sogar die Uhren seiner alten Großmutter aufrüsten, indem er einen neuen Mechanismus mit Funksynchronisation installiert:



Sie finden eine bei ebay unter den Stichwörtern „Radio Controlled Movement“.

Und schließlich ein Lebenshack für diejenigen, die hier gelesen haben. Selbst wenn es in den nächsten paar tausend Kilometern keinen einzigen Sender eines Funksignals gibt, ist ein solches Signal leicht unabhängig zu erzeugen. Google Play hat ein Programm namens "DCF77 Emulator", das ein Signal an die Kopfhörer ausgibt. Wenn Sie das Kopfhörerkabel um die Uhr wickeln, werden sie laut Autor ein Signal empfangen (ich frage mich, wie, weil gewöhnliche Kopfhörer kein 77-kHz-Signal geben, aber der Empfang wahrscheinlich über Oberwellen erfolgt). Mein Programm funktionierte unter Android 9 überhaupt nicht - es gab einfach keinen Ton (oder ich habe ihn vielleicht nicht gehört - schließlich 77 kHz :), aber vielleicht hat jemand mehr Glück. Einige machen sich jedoch selbst zu einem vollwertigen DCF-Signalgenerator, was mit demselben Arduino oder ESP32 einfach zu bewerkstelligen ist:


(Quelle sgfantasytoys.wordpress.com/2015/05/13/synchronize-radio-controlled-watch-without-access )

Fazit


Das DCF-System erwies sich als sehr einfach und bequem. Mit Hilfe eines einfachen und günstigen Empfängers können Sie die genaue Zeit jederzeit und überall im Empfangsbereich abrufen. Trotz der weit verbreiteten Digitalisierung und des „Internet der Dinge“ scheinen solche einfachen Lösungen noch lange gefragt zu sein.

Source: https://habr.com/ru/post/de445470/


All Articles