DCF77: Kuidas ajasignaali süsteem töötab?

Tere Habr.

Tõenäoliselt on paljud kella või ilmajaama soetajad näinud pakendil raadio teel juhitavat kella või isegi aatomikella logo. See on väga mugav, sest peate lihtsalt kella lauale panema ja mõne aja pärast kohandub see automaatselt täpse kellaajaga.
DCF77: Kuidas ajasignaali süsteem töötab?

Mõelgem välja, kuidas see töötab, ja kirjutame Pythonis dekoodri.

Aja sünkroonimise süsteeme on erinevaid. Euroopas on kõige populaarsem Saksa süsteem DCF-77, Jaapanis on oma süsteem JJY, USA-s on süsteem WWVB, ja nii edasi. Järgmisena tuleb juttu DCF77-st, mis on kohati Venemaa Euroopa osas ja naaberriikides kõige asjakohasem ja vastuvõtvaim (Kaug-Ida elanikud võivad olla vastupidisel arvamusel, aga nemad saavad omakorda vastu võtta). ja analüüsida Jaapani signaali;).

Kõik allpool kirjutatud puudutab DCF77.

Signaali vastuvõtt

DCF77 on pikalainejaam, mis töötab sagedusel 77.5 kHz ja edastab signaale amplituudmodulatsioonis. 50KW jaam asub Frankfurdist 25 km kaugusel, see alustas tööd 1959. aastal ning 1973. aastal lisati täpsele kellaajale ka kuupäevainfo. Lainepikkus 77 KHz sagedusel on väga pikk, seega on ka antennivälja mõõtmed üsna korralikud (foto Wikipediast):
DCF77: Kuidas ajasignaali süsteem töötab?

Sellise antenni ja toitesisendiga katab vastuvõtuala peaaegu kogu Euroopa, Valgevene, Ukraina ja osa Venemaast.

DCF77: Kuidas ajasignaali süsteem töötab?

Igaüks saab signaali salvestada. Selleks minge lihtsalt võrgus olevale vastuvõtjale http://websdr.ewi.utwente.nl:8901/, valige seal sagedus 76.5KHz ja USB modulatsioon. Peaks avanema pilt, mis näeb välja umbes selline:

DCF77: Kuidas ajasignaali süsteem töötab?

Seal vajutame allalaadimisnuppu ja salvestame mitme minuti pikkuse fragmendi. Muidugi, kui teil on "päris" vastuvõtja, mis suudab salvestada 77.5 kHz sagedust, saate seda kasutada.

Interneti kaudu raadioajasignaale vastu võttes ei saa me muidugi päris täpset aega – signaal edastatakse hilinemisega. Kuid meie eesmärk on mõista ainult signaali struktuuri, selleks on Interneti-salvestusest enam kui piisav. Reaalses elus kasutatakse vastuvõtmiseks ja dekodeerimiseks muidugi spetsiaalseid seadmeid, neid käsitletakse allpool.

Niisiis, oleme salvestise kätte saanud, hakkame seda töötlema.

Signaali dekodeerimine

Laadime faili Pythoni abil ja vaatame selle struktuuri:

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

Näeme tüüpilist amplituudmodulatsiooni:
DCF77: Kuidas ajasignaali süsteem töötab?

Dekodeerimise lihtsustamiseks võtame signaali mähisjoone Hilberti teisenduse abil:

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

Suurendatud tulemus:
DCF77: Kuidas ajasignaali süsteem töötab?

Silume madalpääsfiltri abil müraemissioone ja arvutame samal ajal keskmise väärtuse, millest on hiljem parsimisel kasu.

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

Tulemus (kollane joon): peaaegu ruutlaine signaal, mida on üsna lihtne analüüsida.
DCF77: Kuidas ajasignaali süsteem töötab?

Parsimine

Kõigepealt peate saama bitijärjestuse. Signaali struktuur ise on väga lihtne.
DCF77: Kuidas ajasignaali süsteem töötab?

Impulssid on jagatud teiseks intervalliks. Kui impulsside vaheline kaugus on 0.1 s (st impulsi enda pikkus on 0.9 s), lisage bitijadale "0", kui kaugus on 0.2 s (st pikkus on 0.8 s), lisage "1". Iga minuti lõppu näitab 2 sekundi pikkune “pikk” impulss, bitijada lähtestatakse nullile ja täitmine algab uuesti.

Ülaltoodud on Pythonis lihtne kirjutada.

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

Selle tulemusel saame bittide jada, meie näites näeb see kahe sekundi jooksul välja järgmine:

0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000

Muide, on huvitav, et signaalil on ka "teine ​​kiht". Bitijada kodeeritakse ka kasutades faasimodulatsioon. Teoreetiliselt peaks see tagama tugevama dekodeerimise isegi nõrgenenud signaali korral.

Meie viimane samm: tegelike andmete hankimine. Bite edastatakse üks kord sekundis, seega on meil kokku 59 bitti, millesse on kodeeritud üsna palju teavet:
DCF77: Kuidas ajasignaali süsteem töötab?

Bite on kirjeldatud artiklis Wikipedia, ja nad on üsna uudishimulikud. Esimesed 15 bitti ei kasutata, kuigi neid oli plaanis kasutada hoiatussüsteemide ja tsiviilkaitse jaoks. Bit A1 näitab, et kell lülitub järgmise tunni jooksul suveajale. Bit A2 näitab, et täiendav hüpe teiseks, mida mõnikord kasutatakse aja reguleerimiseks vastavalt Maa pöörlemisele. Ülejäänud bitid kodeerivad tunde, minuteid, sekundeid ja kuupäeva.

DCF77: Kuidas ajasignaali süsteem töötab?

Neile, kes soovivad omal käel katsetada, on dekodeerimiskood antud spoileri all.
Lähtekood

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)

Kui käivitame programmi, näeme väljundit, mis on sarnane sellele:

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

Tegelikult on see kõik maagia. Sellise süsteemi eeliseks on see, et dekodeerimine on ülilihtne ja seda saab teha mis tahes, isegi kõige lihtsama mikrokontrolleriga. Lihtsalt loendame impulsside pikkuse, kogume 60 bitti ja iga minuti lõpus saame täpse aja. Võrreldes teiste aja sünkroniseerimise meetoditega (GPS näiteks või jumal hoidku Internet:), ei vaja selline raadiosünkroniseerimine praktiliselt üldse elektrit – näiteks tavaline kodune ilmajaam töötab umbes aasta 2 AA patareiga. Seetõttu tehakse raadiosünkroniseerimisega isegi käekellasid, rääkimata muidugi seina- või tänavajaamakelladest.

DCF-i mugavus ja lihtsus köidavad ka isetegemise entusiaste. Vaid 10-20 dollari eest saab osta valmis vastuvõtja ja TTL väljundiga valmis antennimooduli, mille saab ühendada Arduino või muu kontrolleriga.
DCF77: Kuidas ajasignaali süsteem töötab?

Arduino jaoks juba kirjutatud valmis raamatukogud. Küll aga on juba teada, et ükskõik, mida sa mikrokontrolleriga ka ei teeks, saad lõpuks kas kella või ilmajaama. Sellise seadmega on täpse aja kättesaamine tõesti lihtne, eeldusel muidugi, et oled vastuvõtualal. Noh, saate riputada oma kellale kirja “Aatomkell” ja samal ajal kõigile selgitada, et seade on tõesti aatomkella abil sünkroonitud.

Soovijad saavad oma vana vanaema käekella isegi uuendada, paigaldades uue raadiosünkroniseerimisega mehhanismi:

DCF77: Kuidas ajasignaali süsteem töötab?

Selle leiate ebayst märksõnade "Radio Controlled Movement" abil.

Ja lõpetuseks elulugu neile, kes on siiani lugenud. Isegi kui lähema paari tuhande km jooksul pole ainsatki raadiosignaali saatjat, pole sellist signaali ise keeruline tekitada. Google Plays on programm nimega "DCF77 Emulator", mis väljastab signaali kõrvaklappidesse. Autori sõnul võtavad kõrvaklappide juhe ümber kella kinni (huvitav, kuidas, sest tavalised kõrvaklapid ei tooda 77KHz signaali, kuid vastuvõtt on tõenäoliselt tingitud harmoonilistest). Android 9 puhul ei töötanud programm minu jaoks üldse - heli lihtsalt polnud (või võib-olla ma ei kuulnud seda - see on ju 77KHz:), aga võib-olla läheb kellelgi paremini õnne. Mõned aga teevad end täisväärtuslikuks DCF-signaaligeneraatoriks, mida on lihtne teha samal Arduino või ESP32 peal:

DCF77: Kuidas ajasignaali süsteem töötab?
(allikas sgfantasytoys.wordpress.com/2015/05/13/synchronize-radio-controlled-watch-without-access)

Järeldus

DCF-süsteem osutus tõesti üsna lihtsaks ja mugavaks. Lihtsa ja soodsa ressiiveri abil saad alati ja igal pool täpse kellaaja, loomulikult vastuvõtualal. Tundub, et isegi laialt levinud digitaliseerimisest ja asjade internetist hoolimata on selliste lihtsate lahenduste järele nõudlus veel kaua.

Allikas: www.habr.com

Lisa kommentaar