DCF77: Kaip veikia laiko signalo sistema?

Sveiki, Habr.

Tikriausiai daugelis įsigyjančių laikrodį ar orų stotį ant pakuotės yra matę radijo bangomis valdomo laikrodžio ar net atominio laikrodžio logotipą. Tai labai patogu, nes tereikia pastatyti laikrodį ant stalo, o po kurio laiko jis automatiškai prisitaikys prie tikslaus laiko.
DCF77: Kaip veikia laiko signalo sistema?

Išsiaiškinkime, kaip tai veikia, ir parašykite dekoderį „Python“.

Yra įvairių laiko sinchronizavimo sistemų. Populiariausia Europoje yra vokiška sistema DCF-77, Japonija turi savo sistemą JJY, JAV yra sistema WWVB, ir taip toliau. Toliau pasakojimas bus apie DCF77, kaip aktualiausią ir priimtiniausią kai kuriose Rusijos europinės dalies ir kaimyninių šalių vietose (Tolimųjų Rytų gyventojai gali turėti priešingą nuomonę, tačiau jie, savo ruožtu, gali priimti ir analizuoti japonų signalą;).

Viskas, kas parašyta žemiau, bus apie DCF77.

Signalo priėmimas

DCF77 yra ilgųjų bangų stotis, veikianti 77.5 kHz dažniu ir perduodanti signalus amplitudės moduliavimu. 50KW stotis yra 25 km nuo Frankfurto, ji pradėjo veikti 1959 m., o 1973 m. prie tikslaus laiko buvo pridėta datos informacija. 77 KHz dažnio bangos ilgis yra labai ilgas, todėl antenos lauko matmenys taip pat yra gana padorūs (nuotrauka iš Vikipedijos):
DCF77: Kaip veikia laiko signalo sistema?

Su tokia antena ir maitinimo įvadu priėmimo zona apima beveik visą Europą, Baltarusiją, Ukrainą ir dalį Rusijos.

DCF77: Kaip veikia laiko signalo sistema?

Bet kas gali įrašyti signalą. Norėdami tai padaryti, tiesiog eikite į internetinį imtuvą http://websdr.ewi.utwente.nl:8901/, ten pasirinkite dažnį 76.5KHz ir USB moduliaciją. Turėtų būti atidarytas vaizdas, kuris atrodo maždaug taip:

DCF77: Kaip veikia laiko signalo sistema?

Ten paspaudžiame atsisiuntimo mygtuką ir įrašome kelių minučių trukmės fragmentą. Žinoma, jei turite „tikrą“ imtuvą, galintį įrašyti 77.5 KHz dažnį, galite jį naudoti.

Žinoma, priimdami radijo laiko signalus internetu tikrai tikslaus laiko negausime – signalas perduodamas su vėlavimu. Tačiau mūsų tikslas yra tik suprasti signalo struktūrą, tam daugiau nei pakanka interneto įrašo. Realiame gyvenime, žinoma, gauti ir dekoduoti naudojami specializuoti įrenginiai, jie bus aptarti toliau.

Taigi, mes gavome įrašą, pradėkime jį apdoroti.

Signalo dekodavimas

Įkelkime failą naudodami Python ir pamatykime jo struktūrą:

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

Matome tipišką amplitudės moduliaciją:
DCF77: Kaip veikia laiko signalo sistema?

Norėdami supaprastinti dekodavimą, paimkime signalo apvalkalą naudodami Hilberto transformaciją:

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

Padidintas rezultatas:
DCF77: Kaip veikia laiko signalo sistema?

Išlyginkime triukšmo emisiją naudodami žemųjų dažnių filtrą ir tuo pačiu apskaičiuokime vidutinę reikšmę, kuri vėliau pravers analizuojant.

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

Rezultatas (geltona linija): beveik kvadratinės bangos signalas, kurį gana lengva analizuoti.
DCF77: Kaip veikia laiko signalo sistema?

Analizuojama

Pirmiausia turite gauti bitų seką. Pati signalo struktūra labai paprasta.
DCF77: Kaip veikia laiko signalo sistema?

Impulsai skirstomi į antrąjį intervalą. Jei atstumas tarp impulsų yra 0.1 s (t. y. paties impulso ilgis yra 0.9 s), prie bitų sekos pridėkite „0“, jei atstumas yra 0.2 s (t. y. ilgis 0.8 s), pridėkite „1“. Kiekvienos minutės pabaiga rodoma „ilgu“ impulsu, 2 s, bitų seka iš naujo nustatoma į nulį ir pildymas prasideda iš naujo.

Aukščiau pateiktą informaciją lengva parašyti naudojant Python.

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

Dėl to gauname bitų seką, mūsų pavyzdyje dvi sekundes ji atrodo taip:

0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000

Beje, įdomu tai, kad signalas turi ir „antrą duomenų sluoksnį“. Bitų seka taip pat užkoduota naudojant fazės moduliacija. Teoriškai tai turėtų užtikrinti patikimesnį dekodavimą net ir susilpnėjusio signalo atveju.

Paskutinis žingsnis: gauti faktinius duomenis. Bitai perduodami kartą per sekundę, todėl iš viso turime 59 bitus, kuriuose užkoduota gana daug informacijos:
DCF77: Kaip veikia laiko signalo sistema?

Bitai aprašyti Vikipedija, ir jie yra gana smalsūs. Pirmieji 15 bitų nenaudojami, nors planuota juos panaudoti perspėjimo sistemoms ir civilinei gynybai. Bitas A1 rodo, kad kitą valandą laikrodis persijungs į vasaros laiką. Bitas A2 rodo, kad papildomas šuolis antras, kuris kartais naudojamas laikui reguliuoti pagal Žemės sukimąsi. Likę bitai koduoja valandas, minutes, sekundes ir datą.

DCF77: Kaip veikia laiko signalo sistema?

Norintiems eksperimentuoti savarankiškai, dekodavimo kodas pateikiamas po spoileriu.
Šaltinio kodas

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)

Kai paleisime programą, pamatysime išvestį, panašią į šį:

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

Tiesą sakant, tai yra visa magija. Tokios sistemos privalumas yra tas, kad dekodavimas yra itin paprastas ir gali būti atliekamas bet kokiu, net ir paprasčiausiu mikrovaldikliu. Tiesiog suskaičiuojame impulsų ilgį, sukaupiame 60 bitų ir kiekvienos minutės pabaigoje gauname tikslų laiką. Lyginant su kitais laiko sinchronizavimo būdais (pavyzdžiui, GPS, arba neduok Dieve, internetas:), tokiam radijo sinchronizavimui elektros energijos praktiškai nereikia – pavyzdžiui, įprasta namų orų stotis veikia apie metus nuo 2 AA baterijų. Todėl net rankiniai laikrodžiai gaminami su radijo sinchronizavimu, jau nekalbant, žinoma, sieniniai ar gatvės stoties laikrodžiai.

DCF patogumas ir paprastumas taip pat vilioja „pasidaryk pats“ entuziastus. Vos už 10-20 USD galima įsigyti jau paruoštą antenos modulį su jau paruoštu imtuvu ir TTL išėjimu, kurį galima prijungti prie Arduino ar kito valdiklio.
DCF77: Kaip veikia laiko signalo sistema?

Jau parašyta Arduino paruoštos bibliotekos. Tačiau jau žinoma, kad nesvarbu, ką darytumėte su mikrovaldikliu, jūs gaunate arba laikrodį, arba oro stotį. Su tokiu įrenginiu tiksliai laiką sužinoti tikrai nesunku, žinoma, jei esate registratūroje. Na, o ant laikrodžio galite pasikabinti užrašą „Atominis laikrodis“ ir tuo pačiu visiems paaiškinti, kad įrenginys tikrai sinchronizuojamas naudojant atominį laikrodį.

Norintys gali net atnaujinti savo seną močiutės laikrodį sumontavę naują mechanizmą su radijo sinchronizacija:

DCF77: Kaip veikia laiko signalo sistema?

Jį galite rasti ebay naudodami raktinius žodžius „Radio Controlled Movement“.

Ir galiausiai, gyvenimo hack tiems, kurie skaitė iki šiol. Net jei artimiausius porą tūkstančių km nėra nė vieno radijo signalo siųstuvo, tokį signalą sukurti pačiam nesunku. „Google Play“ yra programa „DCF77 Emulator“, kuri išveda signalą į ausines. Anot autoriaus, apvyniojus ausinių laidą aplink laikrodį, jos paims signalą (įdomu, kaip, nes paprastos ausinės neduos 77KHz signalo, bet priėmimas tikriausiai yra dėl harmonikų). „Android 9“ programa man visiškai neveikė - tiesiog nebuvo garso (o gal aš jo negirdėjau - juk tai 77KHz:), bet gal kam nors pasiseks. Tačiau kai kurie iš jų sukuria visavertį DCF signalo generatorių, kurį lengva padaryti naudojant tą patį Arduino arba ESP32:

DCF77: Kaip veikia laiko signalo sistema?
(šaltinis sgfantasytoys.wordpress.com/2015/05/13/synchronize-radio-controlled-watch-without-access)

išvada

DCF sistema pasirodė tikrai gana paprasta ir patogi. Paprasto ir pigaus imtuvo pagalba galite visada ir visur turėti tikslų laiką, žinoma, priimamajame. Panašu, kad net nepaisant plačiai paplitusios skaitmenizacijos ir daiktų interneto, tokie paprasti sprendimai bus paklausūs dar ilgai.

Šaltinis: www.habr.com

Добавить комментарий