Saluton Habr.
Verŝajne multaj, kiuj aĉetas horloĝon aŭ veterstacion, vidis la Radio-Regitan Horloĝon aŭ eĉ la emblemon de Atoma Horloĝo sur la pakaĵo. Ĉi tio estas tre oportuna, ĉar vi nur bezonas meti la horloĝon sur la tablon, kaj post iom da tempo ĝi aŭtomate adaptiĝos al la ĝusta horo.

Ni eltrovu kiel ĝi funkcias kaj skribu malĉifrilon en Python.
Ekzistas malsamaj temposinkronigaj sistemoj. La plej populara en Eŭropo estas la germana sistemo , Japanio havas sian propran sistemon , en Usono ekzistas sistemo , kaj tiel plu. Poste, la rakonto estos pri DCF77, kiel la plej grava kaj alirebla por akcepto en kelkaj lokoj en la eŭropa parto de Rusio kaj najbaraj landoj (loĝantoj de la Malproksima Oriento povas havi la kontraŭan opinion, tamen ili, siavice, povas ricevi; kaj analizu la japanan signalon;).
Ĉio skribita sube temas pri la DCF77.
Signala ricevo
DCF77 estas longonda stacio funkciiganta ĉe frekvenco de 77.5 kHz kaj elsendante signalojn en amplitudmodulado. La 50KW-stacio situas 25 km de Frankfurto, ĝi ekfunkciis en 1959, kaj en 1973 datinformoj estis aldonitaj al la preciza horo. La ondolongo ĉe frekvenco de 77 KHz estas tre longa, do la dimensioj de la antenkampo ankaŭ estas sufiĉe decaj (foto el Vikipedio):

Per tia anteno kaj elektra enigo, la akceptejo kovras preskaŭ la tutan Eŭropon, Belorusion, Ukrainion kaj parton de Rusio.

Ĉiu povas registri signalon. Por fari tion, simple iru al la interreta ricevilo , elektu la frekvencon 76.5KHz kaj USB-moduladon tie. Bildo devus malfermiĝi, kiu aspektas kiel ĉi tio:

Tie ni premas la elŝutbutonon kaj registras fragmenton dum kelkaj minutoj. Kompreneble, se vi havas "realan" ricevilon kapablan registri la 77.5KHz-frekvencon, vi povas uzi tion.
Kompreneble, ricevante radio-horajn signalojn per interreto, ni ne ricevos vere precizan tempon - la signalo estas elsendita kun malfruo. Sed nia celo estas nur kompreni la strukturon de la signalo; por tio, la interreta registrado estas pli ol sufiĉa. En la reala vivo, kompreneble, specialigitaj aparatoj estas uzataj por ricevi kaj malkodi; ili estos diskutitaj sube.
Do, ni ricevis la registradon, ni komencu prilabori ĝin.
Signalo Malkodado
Ni ŝarĝu la dosieron per Python kaj vidu ĝian strukturon:
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()
Ni vidas tipan amplitudmoduladon:

Por simpligi malkodigon, ni prenu la signalkoverton uzante la Hilbert-konverton:
analytic_signal = signal.hilbert(data)
A = np.abs(analytic_signal)
plt.plot(A[:100000])
Pligrandigita rezulto:

Ni glatigu bruemisiojn per malalta filtrilo, kaj samtempe kalkulu la averaĝan valoron, kiu estos utila poste por analizado.
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
Rezulto (flava linio): preskaŭ kvadrata ondo-signalo, kiu estas sufiĉe facile analizebla.

Analizado
Unue vi devas akiri la bitan sinsekvon. La signala strukturo mem estas tre simpla.

La pulsoj estas dividitaj en duajn intervalojn. Se la distanco inter pulsoj estas 0.1s (t.e. la longo de la pulso mem estas 0.9s), aldonu "0" al la bitosekvenco; se la distanco estas 0.2s (t.e. la longo estas 0.8s), aldonu "1". La fino de ĉiu minuto estas indikita per "longa" pulso, 2s longa, la bita sekvenco estas rekomencigita al nulo, kaj plenigo komenciĝas denove.
La supre estas facile skribi en 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
Kiel rezulto, ni ricevas sekvencon de bitoj, en nia ekzemplo dum du sekundoj ĝi aspektas jene:
0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000
Cetere, estas interese, ke la signalo ankaŭ havas "duan tavolon" de datumoj. La bita sekvenco ankaŭ estas ĉifrita uzante . En teorio, tio devus disponigi pli fortikan malkodigon eĉ en la kazo de malfortigita signalo.
Nia lasta paŝo: akiri la realajn datumojn. Bitoj estas elsenditaj unufoje en sekundo, do ni havas entute 59 bitoj, en kiuj sufiĉe multe da informoj estas koditaj:

La bitoj estas priskribitaj en , kaj ili estas sufiĉe scivolemaj. La unuaj 15 bitoj ne estas uzataj, kvankam estis planoj uzi ilin por avertsistemoj kaj civila defendo. Bito A1 indikas, ke la horloĝo ŝanĝos al somera horo en la venonta horo. Bito A2 indikas ke plia , kiu foje estas uzata por ĝustigi la tempon laŭ la tera rotacio. La ceteraj bitoj kodas horojn, minutojn, sekundojn kaj daton.

Por tiuj, kiuj volas eksperimenti memstare, la malkoda kodo estas donita sub la spoiler.
Fontkodo
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)
Kiam ni rulas la programon, ni vidos eligon similan al ĉi tio:
0011110110111000001011000001010000100110010101100010011000
Tuesday, 26.03.19, 21:41
0001111100110110001010100001010000100110010101100010011000
Tuesday, 26.03.19, 21:42
Efektive, tio estas la tuta magio. La avantaĝo de tia sistemo estas, ke malkodado estas ekstreme simpla kaj povas esti farita sur iu ajn, eĉ la plej simpla mikroregilo. Ni simple kalkulas la longecon de la pulsoj, amasigas 60 bitojn, kaj fine de ĉiu minuto ni ricevas la ĝustan tempon. Kompare kun aliaj metodoj de temposinkronigado (GPS, ekzemple, aŭ Dio gardu, Interreto:), tia radiosinkronigado postulas preskaŭ neniun elektron - ekzemple, regula hejma veterstacio funkcias dum proksimume jaro per 2 AA-kuirilaroj. Sekve, eĉ brakhorloĝoj estas faritaj kun radio-sinkronigo, sen mencii, kompreneble, murhorloĝoj aŭ strataj stacidomoj.
La komforto kaj simpleco de DCF ankaŭ altiras DIY-entuziasmulojn. Por nur $ 10-20 vi povas aĉeti pretan antenan modulon kun preta ricevilo kaj TTL-eligo, kiu povas esti konektita al Arduino aŭ alia regilo.

Jam skribita por Arduino . Tamen, oni jam scias, ke ne gravas, kion vi faras sur mikroregilo, vi finas kun aŭ horloĝo aŭ veterstacio. Kun tia aparato, akiri la precizan tempon estas vere facila, kondiĉe, kompreneble, ke vi estas en la akceptejo. Nu, vi povas pendigi la surskribon "Atoma Horloĝo" sur via horloĝo, kaj samtempe klarigi al ĉiuj, ke la aparato estas vere sinkronigita per atoma horloĝo.
Tiuj, kiuj deziras, povas eĉ ĝisdatigi la horloĝon de sia malnova avino instalante novan mekanismon kun radiosinkronigado:

Vi povas trovi unu ĉe ebay uzante la ŝlosilvortojn "Radiokontrolita Movado".
Kaj fine, vivtruko por tiuj, kiuj legis ĝis ĉi tie. Eĉ se ne estas ununura radiosendilo ene de kelkaj mil kilometroj, estas facile generi unu mem. Ekzistas aplikaĵo en Google Play nomata "DCF77 Emulator" kiu elsendas signalon al aŭdiloj. La aŭtoro asertas, ke se vi volvas la aŭdilkablon ĉirkaŭ la horloĝo, ĝi kaptos la signalon (mi scivolas kiel, ĉar ordinaraj aŭdiloj ne produktas 77 kHz-signalon, sed verŝajne pro harmonoj). Sur mia horloĝo... Android Programo 9 tute ne funkciis — simple ne estis sono (aŭ eble mi simple ne povis aŭdi ĝin — ĝi estas 77 kHz, finfine. :)), sed eble iu alia havos pli bonan ŝancon. Kelkaj homoj tamen konstruas sian propran plenkreskan DCF-signalgeneratoron, kiun facile eblas fari per Arduino aŭ ESP32:

(fonto )
konkludo
La DCF-sistemo montriĝis vere sufiĉe simpla kaj oportuna. Helpe de simpla kaj malmultekosta ricevilo, vi povas havi la ĝustan horon ĉiam kaj ĉie, kompreneble en la akceptejo. Ŝajnas, ke eĉ malgraŭ disvastigita cifereciĝo kaj Interreto de Aĵoj, tiaj simplaj solvoj estos postulataj dum longa tempo.
fonto: www.habr.com
