DCF77: kako radi sustav signalizacije vremena?

Pozdrav Habr.

Vjerojatno su mnogi koji kupe sat ili meteorološku stanicu na pakiranju vidjeli logotip radijskog sata ili čak atomskog sata. Ovo je vrlo zgodno, jer samo trebate staviti sat na stol, a nakon nekog vremena on će se automatski prilagoditi točnom vremenu.
DCF77: kako radi sustav signalizacije vremena?

Shvatimo kako to radi i napišimo dekoder u Pythonu.

Postoje različiti sustavi sinkronizacije vremena. Najpopularniji u Europi je njemački sustav DCF-77, Japan ima svoj vlastiti sustav JJY, u SAD-u postoji sustav Wwvb, i tako dalje. Zatim će priča biti o DCF77, kao najrelevantnijem i najpristupačnijem za prijem u nekim mjestima u europskom dijelu Rusije i susjednim zemljama (stanovnici Dalekog istoka mogu imati suprotno mišljenje, međutim, oni, zauzvrat, mogu primiti i analizirati japanski signal;).

Sve dolje napisano bit će o DCF77.

Prijem signala

DCF77 je dugovalna postaja koja radi na frekvenciji od 77.5 kHz i emitira signale u amplitudnoj modulaciji. Stanica od 50KW nalazi se 25 km od Frankfurta, počela je s radom 1959. godine, a 1973. godine uz točno vrijeme dodan je podatak o datumu. Valna duljina na frekvenciji od 77 KHz je vrlo velika, pa su i dimenzije polja antene sasvim pristojne (fotografija s Wikipedije):
DCF77: kako radi sustav signalizacije vremena?

S takvom antenom i ulaznom snagom prijemno područje pokriva gotovo cijelu Europu, Bjelorusiju, Ukrajinu i dio Rusije.

DCF77: kako radi sustav signalizacije vremena?

Svatko može snimiti signal. Da biste to učinili, samo idite na mrežni prijemnik http://websdr.ewi.utwente.nl:8901/, tamo odaberite frekvenciju 76.5KHz i USB modulaciju. Trebala bi se otvoriti slika koja izgleda otprilike ovako:

DCF77: kako radi sustav signalizacije vremena?

Tamo pritisnemo gumb za preuzimanje i snimimo fragment dug nekoliko minuta. Naravno, ako imate "pravi" prijemnik koji može snimati frekvenciju od 77.5 KHz, možete ga koristiti.

Naravno, primanjem radijskih vremenskih signala putem interneta nećemo dobiti istinski točno vrijeme - signal se odašilje s odgodom. Ali naš cilj je samo razumjeti strukturu signala, za to je više nego dovoljna snimka s Interneta. U stvarnom životu, naravno, za prijem i dekodiranje koriste se specijalizirani uređaji, o kojima će biti riječi u nastavku.

Dakle, dobili smo snimku, krenimo u obradu.

Dekodiranje signala

Učitajmo datoteku koristeći Python i pogledajmo njenu 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()

Vidimo tipičnu modulaciju amplitude:
DCF77: kako radi sustav signalizacije vremena?

Da pojednostavimo dekodiranje, uzmimo omotnicu signala koristeći Hilbertovu transformaciju:

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

Uvećani rezultat:
DCF77: kako radi sustav signalizacije vremena?

Izgladimo emisije buke pomoću niskopropusnog filtra, au isto vrijeme izračunajmo prosječnu vrijednost, koja će kasnije biti korisna za analizu.

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

Rezultat (žuta linija): signal gotovo pravokutnog vala koji je vrlo lako analizirati.
DCF77: kako radi sustav signalizacije vremena?

Raščlanjivanje

Prvo morate dobiti niz bitova. Sama struktura signala je vrlo jednostavna.
DCF77: kako radi sustav signalizacije vremena?

Impulsi su podijeljeni u sekundne intervale. Ako je udaljenost između impulsa 0.1s (tj. duljina samog impulsa je 0.9s), dodajte "0" nizu bitova; ako je udaljenost 0.2s (tj. duljina je 0.8s), dodajte "1". Kraj svake minute označen je "dugim" pulsom, dugim 2 s, niz bitova se vraća na nulu i punjenje počinje iznova.

Gore navedeno je lako napisati u 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

Kao rezultat toga, dobivamo niz bitova, u našem primjeru za dvije sekunde izgleda ovako:

0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000

Inače, zanimljivo je da signal ima i "drugi sloj" podataka. Niz bitova je također kodiran pomoću fazna modulacija. U teoriji, ovo bi trebalo omogućiti robusnije dekodiranje čak i u slučaju oslabljenog signala.

Naš posljednji korak: dobivanje stvarnih podataka. Bitovi se prenose jednom u sekundi, tako da imamo ukupno 59 bitova, u kojima je kodirano dosta informacija:
DCF77: kako radi sustav signalizacije vremena?

Bitovi su opisani u Wikipedija, i prilično su znatiželjni. Prvih 15 bitova se ne koristi, iako je bilo planova da se koriste za sustave upozorenja i civilnu obranu. Bit A1 označava da će se sat prebaciti na ljetno računanje vremena u sljedećih sat vremena. Bit A2 označava da je dodatni preskočna druga, koji se ponekad koristi za podešavanje vremena prema rotaciji Zemlje. Preostali bitovi kodiraju sate, minute, sekunde i datum.

DCF77: kako radi sustav signalizacije vremena?

Za one koji žele sami eksperimentirati, kod za dekodiranje nalazi se ispod spojlera.
Izvorni kod

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)

Kada pokrenemo program, vidjet ćemo izlaz sličan ovome:

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

Zapravo, to je sva čarolija. Prednost ovakvog sustava je što je dekodiranje izuzetno jednostavno i može se raditi na svakom, pa i najjednostavnijem mikrokontroleru. Jednostavno izbrojimo duljinu impulsa, skupimo 60 bitova i na kraju svake minute dobijemo točno vrijeme. U usporedbi s drugim načinima sinkronizacije vremena (GPS, na primjer, ili ne daj Bože, Internet :), takva radijska sinkronizacija ne zahtijeva praktički nikakvu struju - primjerice, obična kućna meteorološka stanica radi oko godinu dana na 2 AA baterije. Stoga se čak i ručni satovi izrađuju s radijskom sinkronizacijom, a da ne spominjemo, naravno, zidne satove ili satove za ulične postaje.

Pogodnost i jednostavnost DCF-a također privlače DIY entuzijaste. Za samo 10-20 dolara možete kupiti gotov antenski modul s gotovim prijemnikom i TTL izlazom, koji se može spojiti na Arduino ili neki drugi kontroler.
DCF77: kako radi sustav signalizacije vremena?

Već napisano za Arduino gotove knjižnice. No, već je poznato da što god radili na mikrokontroleru, na kraju dobijete ili sat ili meteorološku stanicu. S takvim uređajem dobivanje točnog vremena je zaista jednostavno, naravno pod uvjetom da se nalazite na recepciji. Pa, možete objesiti natpis "Atomski sat" na svoj sat, a istovremeno objasniti svima da je uređaj stvarno sinkroniziran pomoću atomskog sata.

Oni koji žele mogu čak i nadograditi svoj stari bakin sat ugradnjom novog mehanizma s radio sinkronizacijom:

DCF77: kako radi sustav signalizacije vremena?

Možete ga pronaći na ebayu koristeći ključne riječi “Radio Controlled Movement”.

I na kraju, life hack za one koji su do sada pročitali. Čak i ako u sljedećih nekoliko tisuća km nema niti jednog odašiljača radio signala, nije teško sami generirati takav signal. Na Google Playu postoji program pod nazivom “DCF77 Emulator” koji šalje signal u slušalice. Prema autoru, ako žicu slušalica omotate oko sata, one će pokupiti signal (zanimljivo je kako, jer obične slušalice neće proizvesti signal od 77 KHz, ali je prijem vjerojatno zbog harmonika). Na Androidu 9 program mi uopće nije radio - jednostavno nije bilo zvuka (ili ga možda nisam čuo - ipak je 77 KHz :), ali možda će netko imati više sreće. Neki, međutim, sami prave punopravni generator DCF signala, što je lako napraviti na istom Arduinu ili ESP32:

DCF77: kako radi sustav signalizacije vremena?
(izvor sgfantasytoys.wordpress.com/2015/05/13/synchronize-radio-controlled-watch-without-access)

Zaključak

Pokazalo se da je DCF sustav zaista prilično jednostavan i praktičan. Uz pomoć jednostavnog i jeftinog prijemnika možete uvijek i svugdje imati točno vrijeme, naravno u recepciji. Čini se da će čak i unatoč raširenoj digitalizaciji i Internetu stvari, ovakva jednostavna rješenja još dugo biti tražena.

Izvor: www.habr.com

Dodajte komentar