Ahoj Habr.
Možná mnozí, kdo kupují hodiny nebo meteorologickou stanici, viděli na obalu logo Radio Controlled Clock nebo dokonce Atomic Clock. Je to velmi pohodlné, stačí položit hodiny na stůl a během chvíle se automaticky nastaví na přesný čas.

Pojďme se podívat, jak to funguje, a napíšeme dekodér v jazyce Python.
Existují různé systémy synchronizace času. Nejpopulárnější v Evropě je německý systém , v Japonsku existuje jeho systém , v USA je systém , a tak dále. Dále bude řeč o DCF77, jako o nejaktuálnějším a nejdostupnějším pro příjem v některých částech evropského Ruska a sousedních zemích (obyvatelé Dálného východu mohou mít opačný názor, ovšem mohou také přijmout a analyzovat japonský signál;).
Vše, co bude napsáno dále, se bude týkat DCF77.
Příjem signálu
DCF77 je dlouhovlnná stanice pracující na frekvenci 77.5 kHz a přenášející signály v amplitudové modulaci. Stanice s výkonem 50 kW se nachází 25 km od Frankfurtu, zahájila provoz již v roce 1959, v roce 1973 byla k přesnému času přidána informace o datu. Délka vlny při frekvenci 77 kHz je velmi velká, a proto jsou rozměry anténního pole také značné (foto z Wikipedie):

Při takové anténě a dodávaném výkonu pokrývá oblast příjmu prakticky celou Evropu, Bělorusko, Ukrajinu a část Ruska.

Signál si může nahrát každý. Stačí se přihlásit do online přijímače , vybrat tam frekvenci 76.5 kHz a USB modulaci. Měla by se otevřít obrázek přibližně tohoto typu:

Tam také stiskneme tlačítko stáhnout a nahráváme fragment dlouhý několik minut. Samozřejmě, pokud máte "opravdový" přijímač, schopný nahrát frekvenci 77.5 kHz, můžete použít i ten.
Samozřejmě, když přijímáme rádiové signály přesného času přes Internet, opravdu přesný čas nezískáme — signál se přenáší se zpožděním. Naším cílem je jen pochopit strukturu signálu, k tomu jsou internetové záznamy více než dostatečné. V reálu se samozřejmě používají specializovaná zařízení pro příjem a dekódování, o nichž bude řečeno níže.
Takže jsme získali nahrávku, začneme s jejím zpracováním.
Dekódování signálu
Nahrajeme soubor pomocí Pythonu a podíváme 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:

Abychom usnadnili 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]) Výsledek v zvětšené podobě:

Zjemníme výkyvy od šumů pomocí dolnopásmového filtru, zároveň vypočítáme průměr, který se nám později bude hodit pro 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): prakticky obdélníkový signál, který se poměrně snadno analyzuje.

Parsování
Nejprve je třeba získat bitovou sekvenci. Samotná struktura signálu je velmi jednoduchá.

Impulsy jsou rozděleny do sekundových intervalů. Pokud je vzdálenost mezi impulsy 0,1 s (tj. délka samotného impulsu 0,9 s), k bitové sekvenci přidáme „0“, pokud je vzdálenost 0,2 s (tj. délka 0,8 s), přidáme „1“. Konec každé minuty je označen „dlouhým“ impulsem o délce 2 s, přičemž bitová sekvence se při tom resetuje a vyplnění začíná znovu.
Výše uvedené není těžké zapsat v jazyce Python.
sig_start, sig_stop = 0, 0
pos = 0
bits_str = ""
while pos < cnt - 4:
if A[pos] avg:
# Začátek signálu
sig_start = pos
if A[pos] > avg and A[pos+1] < avg:
# Konec signálu
sig_stop = pos
diff = sig_stop - sig_start
if diff 0.85*sample_rate and diff 1.5*sample_rate:
print(bits_str)
bits_str = ""
pos += 1
V důsledku máme bitovou sekvenci, v našem příkladu pro dvě sekundy vypadá takto:
0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000
Mimochodem je zajímavé, že signál obsahuje i „druhou vrstvu“ dat. Bitová sekvence je také zakódována pomocí . Teoreticky by to mělo zajistit odolnější dekódování i v případě oslabeného signálu.
Náš poslední krok: získat samotná data. Bity se přenášejí jednou za sekundu, takže máme celkem 59 bitů, ve kterých je zakódováno dostatek informací:

Bity jsou popsány v , a jsou docela zajímavé. Prvních 15 bitů se nepoužívá, přičemž byly plány využít je pro varovné systémy a civilní obranu. Bit A1 označuje, že hodiny budou příští hodinu přepnuty na letní čas. Bit A2 naznačuje, že v příští hodině bude přidána , která se někdy používá k úpravě času v souladu s otáčením Země. Ostatní bity kódují hodiny, minuty, sekundy a datum.

Pro ty, kteří si chtějí vyzkoušet experimentování, je níže pod spoilerem uveden kód pro dekódování.
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 = ('Neděle', 'Pondělí', 'Úterý', 'Středa', 'Čtvrtek', 'Pátek', 'Sobota', 'Neděle')
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)
Po spuštění programu uvidíme přibližně takový výstup:
0011110110111000001011000001010000100110010101100010011000
Úterý, 26.03.19, 21:41
0001111100110110001010100001010000100110010101100010011000
Úterý, 26.03.19, 21:42
A to je veškerá magie. Výhodou tohoto systému je, že dekódování je velmi jednoduché a může být prováděno na jakémkoli, i nejjednodušším mikrokontroléru. Jednoduše počítáme délku impulsů, shromažďujeme 60 bitů a na konci každé minuty dostáváme přesný čas. Ve srovnání s jinými způsoby synchronizace času (například GPS, nebo nedej bože Internet:), má taková rádiová synchronizace prakticky nulovou spotřebu energie — pro příklad, běžná domácí meteostanice funguje přibližně rok na 2 AA baterie. Proto se rádiová synchronizace používá i v náramkových hodinách, a to nemluvím o nástěnných nebo veřejných.
Pohodlí a jednoduchost DCF přitahuje i nadšence do DIY. V průběhu 10–20 USD si můžete koupit hotový modul s anténou a přijímačem s TTL výstupem, který lze připojit k Arduino nebo jinému řízení.

Pro Arduino už byly napsány a Je třeba říci, že jakmile se něco dělá s mikrokontrolérem, vyjde buď hodiny, nebo meteorologická stanice. S takovým zařízením není obtížné získat přesný čas, pokud jste tedy v oblasti příjmu. A na hodiny můžete umístit nápis „Atomové hodiny“ a zároveň vysvětlovat všem zájemcům, že zařízení se skutečně synchronizuje pomocí atomových hodin.
Zájemci mohou dokonce upgradovat staré hodinky po babičce tím, že do nich nainstalují nový mechanismus s rádiovou synchronizací:

Takový lze najít na ebay pod klíčovými slovy „Radio Controlled Movement“.
A nakonec, tip pro ty, kteří dočetli až sem. I když se v nejbližších několika tisících km nenachází žádný vysílač rádiového signálu, není obtížné takový signál vygenerovat sami. V Google Play je aplikace s názvem „DCF77 Emulator“, která vysílá signál na sluchátka. Podle tvrzení autora, pokud obtočíte kabel sluchátek kolem hodin, zachytí signál (zajímavé, jak to, protože obyčejná sluchátka nevydají signál 77 kHz, ale pravděpodobně je příjem zajištěn harmonickými frekvencemi). U mě na Androidu 9 aplikace úplně nefungovala — prostě nebyl žádný zvuk (možná jsem ho neslyšel — 77 kHz:), ale možná někdo jiný bude mít více štěstí. Někteří si přesto vyrábějí i plnohodnotný generátor signálů DCF, který není obtížné vyrobit i na Arduino nebo ESP32:

(zdroj )
Závěr
Systém DCF se ukázal jako opravdu jednoduchý a pohodlný. S 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 oblasti příjmu. Myslím, že i přes všudypřítomnou digitalizaci a „internet věcí“ budou taková jednoduchá řešení ještě dlouho žádána.
Zdroj: habr.com
