DCF77: hogyan működik az időjelző rendszer?

Szia Habr!

Valószínűleg sokan, akik karórát vagy meteorológiai állomást vásárolnak, láthatták a Radio Controlled Clock vagy akár az atomóra logót a csomagoláson. Ez nagyon kényelmes, mert elég az órát az asztalra tenni, és egy idő után automatikusan beáll a pontos időre.
DCF77: hogyan működik az időjelző rendszer?

Kitaláljuk, hogyan működik, és írjunk egy dekódert Pythonban.

Különféle időszinkronizációs rendszerek léteznek. Európában a legnépszerűbb a német rendszer DCF-77Japánnak saját rendszere van JJY, az USA-ban van egy rendszer WWVB, stb. Továbbá a sztori a DCF77-ről fog szólni, mint Oroszország európai részének és a szomszédos országok egyes helyein a legrelevánsabb és a leginkább elérhető fogadtatásra (a Távol-Kelet lakóinak ellenkező véleménye lehet, ők viszont fogadni és elemezni a japán jelet;).

Az alábbiakban leírtak a DCF77-ről szólnak.

Jel vétel

A DCF77 egy hosszúhullámú állomás, amely 77.5 kHz-en működik, és AM jeleket ad. Az 50 kW teljesítményű állomás Frankfurttól 25 km-re található, 1959-ben kezdte meg a munkát, 1973-ban a pontos időponthoz a dátumra vonatkozó információkat is hozzáadták. A 77 kHz-es frekvencia hullámhossza nagyon nagy, így az antennamező méretei is nagyon megfelelőek (fotó a Wikipédiából):
DCF77: hogyan működik az időjelző rendszer?

Ilyen antennával és bemeneti teljesítménnyel a vételi körzet szinte egész Európát, Fehéroroszországot, Ukrajnát és Oroszország egy részét lefedi.

DCF77: hogyan működik az időjelző rendszer?

Bárki rögzíthet. Ehhez lépjen az online vevőhöz http://websdr.ewi.utwente.nl:8901/, válassza ki a 76.5 KHz-es frekvenciát és ott az USB modulációt. Egy képnek valahogy így kell megjelennie:

DCF77: hogyan működik az időjelző rendszer?

Ugyanitt megnyomjuk a letöltés gombot és rögzítünk egy pár perces töredéket. Természetesen, ha van egy "igazi" vevő, amely képes 77.5 kHz-es frekvencia rögzítésére, akkor használhatja.

Természetesen a pontos idejű rádiójelek interneten keresztül történő vételekor nem kapunk igazán pontos időt - a jel késleltetéssel kerül továbbításra. De a célunk csak az, hogy megértsük a jel szerkezetét, ehhez bőven elég az internetes felvétel. A való életben természetesen speciális eszközöket használnak a fogadásra és a dekódolásra, ezeket az alábbiakban tárgyaljuk.

Szóval, megkaptuk a rekordot, kezdjük el feldolgozni.

Jel dekódolás

Töltsük be a fájlt Pythonnal, és nézzük meg a szerkezetét:

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()

Tipikus amplitúdómodulációt látunk:
DCF77: hogyan működik az időjelző rendszer?

A dekódolás egyszerűsítése érdekében a jel burkológörbéjét a Hilbert transzformációval vesszük:

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

Kibontott eredmény:
DCF77: hogyan működik az időjelző rendszer?

Simítsuk ki a zajkibocsátást aluláteresztő szűrővel, egyúttal számoljuk ki az átlagértéket, később jól fog jönni az elemzéshez.

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

Eredmény (sárga vonal): egy majdnem téglalap alakú jel, amelyet meglehetősen könnyű elemezni.
DCF77: hogyan működik az időjelző rendszer?

Elemzés

Először meg kell szereznie a bitsorozatot. Maga a jelszerkezet nagyon egyszerű.
DCF77: hogyan működik az időjelző rendszer?

Az impulzusok második intervallumokra vannak osztva. Ha az impulzusok közötti távolság 0.1 s (azaz magának az impulzusnak a hossza 0.9 s), akkor a bitsorozathoz „0”-t adunk, ha a távolság 0.2 s (azaz a hossza 0.8 s), akkor hozzáadjuk „1”. Minden perc végét "hosszú" impulzus jelzi, 2 s hosszú, a bitsorozat nullázódik, és a kitöltés újra kezdődik.

A fentiek könnyen megírhatók Pythonban.

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

Ennek eredményeként bitsorozatot kapunk, példánkban két másodpercig így néz ki:

0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000

Egyébként érdekes, hogy a jelben van egy „második réteg” is. A bitsorozat is kódolva van fázis moduláció. Elméletileg ennek robusztusabb dekódolást kellene biztosítania még gyengített jel esetén is.

Utolsó lépésünk: a tényleges adatok beszerzése. A bitek átvitele másodpercenként egyszer történik, így csak 59 bitünk van, amibe elég sok információ van kódolva:
DCF77: hogyan működik az időjelző rendszer?

A bitek leírása a Wikipediaés eléggé kíváncsiak. Az első 15 bitet nem használják, bár tervezték, hogy hangosbeszélő és polgári védelmi rendszerekhez használják őket. Az A1 bit azt jelzi, hogy az óra a következő órában nyári időszámításra vált. Az A2 bit azt jelzi, hogy a következő óra hozzáadásra kerül ugrás második, amivel néha a Föld forgása szerint korrigálják az időt. A fennmaradó bitek órákat, perceket, másodperceket és dátumot kódolnak.

DCF77: hogyan működik az időjelző rendszer?

Aki önállóan szeretne kísérletezni, annak a dekódoló kód a spoiler alatt található.
Forráskód

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)

A program futtatásakor valami ehhez hasonló kimenetet fogunk látni:

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

Valójában ez az egész varázslat. Egy ilyen rendszer előnye, hogy a dekódolás rendkívül egyszerű, és bármely, a legegyszerűbb mikrokontrolleren elvégezhető. Csak megszámoljuk az impulzusok hosszát, összegyűjtünk 60 bitet, és minden perc végén megkapjuk a pontos időt. Az időszinkronizálás egyéb módszereivel (például GPS-szel, vagy ne adj isten, az internettel :) összehasonlítva az ilyen rádiós szinkronizáláshoz gyakorlatilag nincs szükség áramra - például egy átlagos otthoni időjárás-állomás körülbelül egy évig működik 2 AA elemmel. Ezért még a karórák is készülnek rádiós szinkronizálással, nem beszélve persze a faliórákról vagy az utcai állomások óráiról.

A DCF kényelme és egyszerűsége a barkácsolás szerelmeseit is vonzza. Mindössze 10-20 dollárért vásárolhatunk kész antennamodult, kész vevővel és TTL kimenettel, ami Arduino-hoz vagy más kontrollerhez köthető.
DCF77: hogyan működik az időjelző rendszer?

A már megírt Arduino-hoz és kész könyvtárak. Az viszont már ismert, hogy bármit is csinálsz a mikrokontrolleren, vagy órát vagy meteorológiai állomást kapsz. Egy ilyen eszközzel nagyon egyszerű a pontos idő megállapítása, kivéve persze, ha éppen a recepción tartózkodik. Nos, az órára felakaszthatja az „Atomic Clock” feliratot, és egyúttal elmagyarázhatja mindenkinek, hogy a készülék valóban atomóra segítségével szinkronizálódik.

Azok, akik szeretnének, akár a régi nagymama óráját is frissíthetik egy új, rádiós szinkronizálással ellátott mechanizmus telepítésével:

DCF77: hogyan működik az időjelző rendszer?

Az eBay-en a "Radio Controlled Movement" kulcsszavak használatával találhat ilyet.

És végül egy life hack azoknak, akik idáig olvastak. Még akkor is, ha a következő pár ezer kilométeren egyetlen rádiójeladó sem lesz, egy ilyen jel önmagában könnyen generálható. A Google Playen található egy „DCF77 Emulator” nevű program, amely jelet ad ki a fejhallgatóba. A szerző szerint ha körbetekerjük a fejhallgató vezetékét, akkor felfogják a jelet (vajon hogyan, mert a közönséges fejhallgató nem ad ki 77KHz-es jelet, de valószínűleg a felharmonikusoknak köszönhető a vétel). A program egyáltalán nem működött nekem Android 9-en - egyszerűen nem volt hang (vagy talán nem is hallottam - végül is 77KHz :), de talán valaki szerencsésebb lesz. Néhányan azonban teljes értékű DCF jelgenerátort készítenek, ami könnyen elvégezhető ugyanazon az Arduino-n vagy ESP32-n:

DCF77: hogyan működik az időjelző rendszer?
(forrás sgfantasytoys.wordpress.com/2015/05/13/synchronize-radio-controlled-watch-without-access)

Következtetés

A DCF rendszer nagyon egyszerűnek és kényelmesnek bizonyult. Egy egyszerű és olcsó vevő segítségével mindig és mindenhol pontos időt kaphat, természetesen a recepción. Úgy tűnik, a széles körben elterjedt digitalizáció és a „dolgok internete” ellenére is az ilyen egyszerű megoldásokra még sokáig lesz kereslet.

Forrás: will.com

Hozzászólás