DCF77: jak funguje systém časové signalizace?

Ahoj Habr.

Pravděpodobně mnoho lidí, kteří si koupí hodinky nebo meteorologickou stanici, vidělo na obalu logo rádiem řízených hodin nebo dokonce atomových hodin. To je velmi pohodlné, protože hodiny stačí položit na stůl a po chvíli se automaticky přizpůsobí přesnému času.
DCF77: jak funguje systém časové signalizace?

Pojďme zjistit, jak to funguje, a napsat dekodér v Pythonu.

Existují různé systémy synchronizace času. Nejoblíbenější v Evropě je německý systém DCF-77, Japonsko má svůj vlastní systém JJY, v USA existuje systém WWVB, a tak dále. Dále se příběh bude týkat DCF77, jako nejrelevantnějšího a nejdostupnějšího pro příjem na některých místech v evropské části Ruska a sousedních zemích (obyvatelé Dálného východu mohou mít opačný názor, ale oni zase mohou přijímat a analyzovat japonský signál;).

Vše napsané níže se bude týkat DCF77.

Příjem signálu

DCF77 je dlouhovlnná stanice pracující na frekvenci 77.5 kHz a vysílající signály v amplitudové modulaci. Stanice o výkonu 50 kW se nachází 25 km od Frankfurtu, provoz zahájila v roce 1959 a v roce 1973 byla k přesnému času přidána informace o datu. Vlnová délka na frekvenci 77 KHz je velmi dlouhá, takže rozměry pole antény jsou také celkem slušné (foto z Wikipedie):
DCF77: jak funguje systém časové signalizace?

S takovou anténou a příkonem pokrývá oblast příjmu téměř celou Evropu, Bělorusko, Ukrajinu a část Ruska.

DCF77: jak funguje systém časové signalizace?

Nahrát signál může kdokoli. Chcete-li to provést, přejděte do online přijímače http://websdr.ewi.utwente.nl:8901/, vyberte tam frekvenci 76.5KHz a USB modulaci. Měl by se otevřít obrázek, který vypadá asi takto:

DCF77: jak funguje systém časové signalizace?

Tam stiskneme tlačítko stahování a nahrajeme fragment dlouhý několik minut. Samozřejmě, pokud máte „skutečný“ přijímač schopný nahrávat frekvenci 77.5 kHz, můžete jej použít.

Přijímáním rádiových časových signálů přes internet samozřejmě nezískáme skutečně přesný čas – signál je přenášen se zpožděním. Naším cílem je ale pouze porozumět struktuře signálu, k tomu nám internetová nahrávka bohatě postačí. V reálném životě se pro příjem a dekódování samozřejmě používají specializovaná zařízení, o kterých bude řeč níže.

Nahrávku jsme tedy obdrželi, můžeme ji začít zpracovávat.

Dekódování signálu

Načteme soubor pomocí Pythonu a podívejme se na jeho strukturu:

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

Vidíme typickou amplitudovou modulaci:
DCF77: jak funguje systém časové signalizace?

Pro zjednodušení dekódování, vezmeme obálku signálu pomocí Hilbertovy transformace:

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

Zvětšený výsledek:
DCF77: jak funguje systém časové signalizace?

Vyhlaďme emise hluku pomocí dolnopropustného filtru a zároveň vypočítejme průměrnou hodnotu, která se bude hodit později při parsování.

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

Výsledek (žlutá čára): téměř obdélníkový signál, který lze celkem snadno analyzovat.
DCF77: jak funguje systém časové signalizace?

Analýza

Nejprve musíte získat bitovou sekvenci. Samotná struktura signálu je velmi jednoduchá.
DCF77: jak funguje systém časové signalizace?

Impulzy jsou rozděleny do sekundových intervalů. Pokud je vzdálenost mezi pulzy 0.1 s (tj. délka samotného pulzu je 0.9 s), přidejte k bitové sekvenci „0“; pokud je vzdálenost 0.2 s (tj. délka je 0.8 s), přidejte „1“. Konec každé minuty je indikován „dlouhým“ pulzem v délce 2 s, sekvence bitů je vynulována a plnění začíná znovu.

Výše uvedené je snadné napsat v Pythonu.

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

V důsledku toho dostaneme sekvenci bitů, v našem příkladu to po dobu dvou sekund vypadá takto:

0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000

Mimochodem, je zajímavé, že signál má také „druhou vrstvu“ dat. Bitová sekvence je také zakódována pomocí fázová modulace. Teoreticky by to mělo zajistit robustnější dekódování i v případě oslabeného signálu.

Náš poslední krok: získání skutečných dat. Bity jsou přenášeny jednou za sekundu, takže máme celkem 59 bitů, ve kterých je zakódováno poměrně hodně informací:
DCF77: jak funguje systém časové signalizace?

Bity jsou popsány v Wikipediaa jsou docela zvědaví. Prvních 15 bitů se nepoužívá, i když se plánovalo jejich použití pro varovné systémy a civilní obranu. Bit A1 udává, že se hodiny v příští hodině změní na letní čas. Bit A2 označuje, že další skok druhý, který se někdy používá k úpravě času podle rotace Země. Zbývající bity kódují hodiny, minuty, sekundy a datum.

DCF77: jak funguje systém časové signalizace?

Pro ty, kteří chtějí experimentovat sami, je pod spoilerem uveden dekódovací kód.
Zdrojový kó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)

Když program spustíme, uvidíme výstup podobný tomuto:

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

Vlastně to je celé kouzlo. Výhodou takového systému je, že dekódování je extrémně jednoduché a lze jej provést na jakémkoli, i na tom nejjednodušším mikrokontroléru. Jednoduše spočítáme délku pulsů, nashromáždíme 60 bitů a na konci každé minuty dostaneme přesný čas. Oproti jiným způsobům synchronizace času (např. GPS nebo nedej bože internet:) taková rádiová synchronizace nevyžaduje prakticky žádnou elektřinu - například běžná domácí meteostanice běží zhruba rok na 2 AA baterie. Proto se i náramkové hodinky vyrábí s rádiovou synchronizací, nemluvě samozřejmě o nástěnných nebo pouličních nádražních.

Pohodlí a jednoduchost DCF také přitahuje kutily. Za pouhých 10-20 $ si můžete koupit hotový anténní modul s hotovým přijímačem a TTL výstupem, který lze připojit k Arduinu nebo jinému ovladači.
DCF77: jak funguje systém časové signalizace?

Již napsáno pro Arduino hotové knihovny. Je však již známo, že ať už na mikrokontroléru děláte cokoli, skončíte buď u hodin, nebo u meteostanice. S takovým zařízením je zjištění přesného času opravdu snadné, samozřejmě za předpokladu, že jste v prostoru recepce. No, můžete si na hodinky pověsit nápis „Atomic Clock“ a zároveň všem vysvětlit, že zařízení je skutečně synchronizováno pomocí atomových hodin.

Ti, kteří si přejí, mohou dokonce upgradovat hodinky své staré babičky instalací nového mechanismu s rádiovou synchronizací:

DCF77: jak funguje systém časové signalizace?

Můžete jej najít na ebay pomocí klíčových slov „Radio Controlled Movement“.

A nakonec life hack pro ty, kteří dočetli až sem. I když v příštích několika tisících km není jediný vysílač rádiového signálu, není těžké takový signál vygenerovat sami. Na Google Play existuje program s názvem „DCF77 Emulator“, který vysílá signál do sluchátek. Podle autora, pokud omotáte drátek sluchátek kolem hodinek, signál zachytí (je zajímavé jak, protože běžná sluchátka signál 77KHz nevydají, ale příjem je pravděpodobně způsoben harmonickými). Na Androidu 9 mi program vůbec nefungoval - prostě tam nebyl žádný zvuk (nebo jsem ho možná neslyšel - koneckonců je to 77 kHz:), ale možná bude mít někdo větší štěstí. Některé si však dělají plnohodnotný generátor signálu DCF, který lze snadno vyrobit na stejném Arduinu nebo ESP32:

DCF77: jak funguje systém časové signalizace?
(zdroj sgfantasytoys.wordpress.com/2015/05/13/synchronize-radio-controlled-watch-without-access)

Závěr

Systém DCF se ukázal být opravdu docela jednoduchý a pohodlný. Pomocí jednoduchého a levného přijímače můžete mít přesný čas vždy a všude, samozřejmě v prostoru recepce. Zdá se, že i přes rozšířenou digitalizaci a internet věcí budou taková jednoduchá řešení ještě dlouho žádaná.

Zdroj: www.habr.com

Přidat komentář