DCF77: Wie funktioniert das Zeitsignalsystem?

Hallo Habr.

Wahrscheinlich haben viele, die eine Uhr oder eine Wetterstation kaufen, das Logo einer Funkuhr oder sogar einer Atomuhr auf der Verpackung gesehen. Das ist sehr praktisch, denn es genügt, die Uhr auf den Tisch zu stellen, und nach einer Weile stellt sie sich automatisch auf die genaue Uhrzeit ein.
DCF77: Wie funktioniert das Zeitsignalsystem?

Lassen Sie uns herausfinden, wie es funktioniert, und einen Decoder in Python schreiben.

Es gibt verschiedene Zeitsynchronisationssysteme. Am beliebtesten in Europa ist das deutsche System DCF-77Japan hat sein eigenes System JJY, in den USA gibt es ein System WWVB, usw. Darüber hinaus geht es in der Geschichte um DCF77, das an einigen Orten im europäischen Teil Russlands und in den Nachbarländern am relevantesten und zugänglichsten für den Empfang ist (die Bewohner des Fernen Ostens sind möglicherweise der gegenteiligen Meinung, können dies jedoch wiederum das japanische Signal empfangen und analysieren;).

Alles, was im Folgenden geschrieben wird, dreht sich um DCF77.

Signalempfang

Der DCF77 ist ein Langwellensender, der mit 77.5 kHz arbeitet und AM-Signale sendet. Die Station mit einer Leistung von 50 kW liegt 25 km von Frankfurt entfernt, sie nahm 1959 ihre Arbeit auf, 1973 wurde die genaue Uhrzeit durch die Angabe des Datums ergänzt. Die Wellenlänge bei einer Frequenz von 77 kHz ist sehr groß, daher sind auch die Abmessungen des Antennenfeldes sehr ordentlich (Foto aus Wikipedia):
DCF77: Wie funktioniert das Zeitsignalsystem?

Mit einer solchen Antenne und Eingangsleistung deckt das Empfangsgebiet fast ganz Europa, Weißrussland, die Ukraine und einen Teil Russlands ab.

DCF77: Wie funktioniert das Zeitsignalsystem?

Jeder kann aufnehmen. Gehen Sie dazu einfach zum Online-Receiver http://websdr.ewi.utwente.nl:8901/, wählen Sie dort eine Frequenz von 76.5KHz und USB-Modulation. Ein Bild sollte etwa so aussehen:

DCF77: Wie funktioniert das Zeitsignalsystem?

An derselben Stelle drücken wir den Download-Button und nehmen ein paar Minuten langes Fragment auf. Wenn Sie einen „echten“ Empfänger haben, der eine Frequenz von 77.5 kHz aufzeichnen kann, können Sie ihn natürlich verwenden.

Wenn wir Funksignale mit genauer Zeit über das Internet empfangen, erhalten wir natürlich keine wirklich genaue Zeit – das Signal wird verzögert übertragen. Unser Ziel ist jedoch nur, die Struktur des Signals zu verstehen, dafür reicht die Internetaufzeichnung völlig aus. Im wirklichen Leben werden zum Empfangen und Dekodieren natürlich spezielle Geräte verwendet, auf die weiter unten eingegangen wird.

Wir haben also den Datensatz erhalten, beginnen wir mit der Bearbeitung.

Signaldekodierung

Laden wir die Datei mit Python und sehen uns 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:
DCF77: Wie funktioniert das Zeitsignalsystem?

Um die Dekodierung zu vereinfachen, nehmen wir die Signalhüllkurve mithilfe der Hilbert-Transformation:

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

Erweitertes Ergebnis:
DCF77: Wie funktioniert das Zeitsignalsystem?

Lassen Sie uns die Geräuschemissionen mithilfe eines Tiefpassfilters glätten und gleichzeitig den Durchschnittswert berechnen. Dies wird später beim Parsen nützlich sein.

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 nahezu rechteckiges Signal, das relativ einfach zu analysieren ist.
DCF77: Wie funktioniert das Zeitsignalsystem?

Parsing

Zuerst müssen Sie die Bitfolge ermitteln. Die Signalstruktur selbst ist sehr einfach.
DCF77: Wie funktioniert das Zeitsignalsystem?

Die Impulse werden in Sekundenintervalle unterteilt. Wenn der Abstand zwischen den Impulsen 0.1 s beträgt (d. h. die Länge des Impulses selbst beträgt 0.9 s), fügen wir „0“ zur Bitfolge hinzu, wenn der Abstand 0.2 s beträgt (d. h. die Länge beträgt 0.8 s), fügen wir hinzu „1“. Das Ende jeder Minute wird durch einen „langen“ Impuls von 2 s Länge angezeigt, die Bitfolge wird auf Null zurückgesetzt und die Befüllung beginnt von neuem.

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, die in unserem Beispiel für zwei Sekunden so aussieht:

0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000

Interessant ist übrigens, dass es im Signal auch eine „zweite Datenschicht“ gibt. Die Bitfolge wird ebenfalls mit kodiert Phasenmodulation. Theoretisch sollte dies selbst bei einem abgeschwächten Signal eine robustere Decodierung ermöglichen.

Unser letzter Schritt: Holen Sie sich die tatsächlichen Daten. Bits werden einmal pro Sekunde übertragen, wir haben also nur 59 Bits, in denen ziemlich viele Informationen kodiert sind:
DCF77: Wie funktioniert das Zeitsignalsystem?

Die Bits sind in beschrieben Wikipediaund sie sind ziemlich neugierig. Die ersten 15 Bits werden nicht verwendet, obwohl geplant war, sie für Beschallungs- und Zivilschutzsysteme zu verwenden. Bit A1 zeigt an, dass die Uhr in der nächsten Stunde auf Sommerzeit umstellt. Bit A2 zeigt an, dass die nächste Stunde hinzugefügt wird Schaltsekunde, die manchmal verwendet wird, um die Zeit entsprechend der Erdrotation zu korrigieren. Die restlichen Bits kodieren Stunden, Minuten, Sekunden und Datum.

DCF77: Wie funktioniert das Zeitsignalsystem?

Für diejenigen, die selbst experimentieren möchten, finden Sie den Dekodierungscode unter dem Spoiler.
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 etwa diese Ausgabe:

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

Eigentlich ist das die ganze Magie. Der Vorteil eines solchen Systems besteht darin, dass die Dekodierung äußerst einfach ist und auf jedem noch so unkomplizierten Mikrocontroller durchgeführt werden kann. Wir zählen einfach die Länge der Impulse, sammeln 60 Bits und am Ende jeder Minute erhalten wir die genaue Zeit. Im Vergleich zu anderen Methoden der Zeitsynchronisierung (z. B. GPS oder Gott bewahre das Internet :) benötigt eine solche Funksynchronisierung praktisch keinen Strom – beispielsweise funktioniert eine gewöhnliche Heimwetterstation etwa ein Jahr lang mit 2 AA-Batterien. Daher werden auch Armbanduhren mit Funksynchronisation hergestellt, ganz zu schweigen von Wanduhren oder Bahnhofsuhren.

Der Komfort und die Einfachheit des DCF ziehen auch Heimwerker an. Für nur 10–20 US-Dollar können Sie ein fertiges Antennenmodul mit einem fertigen Empfänger und einem TTL-Ausgang kaufen, das an einen Arduino oder einen anderen Controller angeschlossen werden kann.
DCF77: Wie funktioniert das Zeitsignalsystem?

Für Arduino bereits geschrieben und fertige Bibliotheken. Es ist jedoch bereits bekannt, dass man mit allem, was man auf dem Mikrocontroller macht, entweder eine Uhr oder eine Wetterstation erhält. Mit einem solchen Gerät ist es wirklich einfach, die genaue Uhrzeit zu ermitteln, es sei denn, Sie befinden sich natürlich im Empfangsbereich. Nun, Sie können die Aufschrift „Atomuhr“ an die Uhr hängen und gleichzeitig allen erklären, dass das Gerät tatsächlich mit einer Atomuhr synchronisiert wird.

Wer möchte, kann die alte Großmutteruhr sogar aufwerten, indem er ein neues Uhrwerk mit Funksynchronisation einbaut:

DCF77: Wie funktioniert das Zeitsignalsystem?

Sie können eines bei eBay unter dem Stichwort „Radio Controlled Movement“ finden.

Und zum Schluss noch ein Life-Hack für diejenigen, die bis hierher gelesen haben. Auch wenn es in den nächsten paar tausend Kilometern keinen einzigen Funksignalsender gibt, lässt sich ein solches Signal leicht selbst erzeugen. Bei Google Play gibt es ein Programm namens „DCF77 Emulator“, das ein Signal an die Kopfhörer ausgibt. Laut dem Autor werden die Kopfhörer das Signal empfangen, wenn man sie rund um die Uhr umwickelt (ich frage mich, wie, denn gewöhnliche Kopfhörer geben kein 77-kHz-Signal aus, aber der Empfang ist wahrscheinlich auf Oberwellen zurückzuführen). Das Programm funktionierte bei mir unter Android 9 überhaupt nicht – es gab einfach keinen Ton (oder vielleicht habe ich ihn auch nicht gehört – immerhin 77 kHz :), aber vielleicht hat jemand mehr Glück. Einige bauen sich jedoch selbst einen vollwertigen DCF-Signalgenerator, was auf demselben Arduino oder ESP32 einfach zu bewerkstelligen ist:

DCF77: Wie funktioniert das Zeitsignalsystem?
(Quelle sgfantasytoys.wordpress.com/2015/05/13/synchronize-funkgesteuerte-uhr-ohne-zugriff)

Abschluss

Das DCF-System erwies sich als wirklich recht einfach und praktisch. Mit Hilfe eines einfachen und günstigen Empfängers haben Sie immer und überall die genaue Uhrzeit, natürlich auch im Empfangsbereich. Es scheint, dass solch einfache Lösungen trotz der weit verbreiteten Digitalisierung und des „Internets der Dinge“ noch lange gefragt sein werden.

Source: habr.com

Kommentar hinzufügen