Kaixo Habr.
Seguruenik, erloju bat edo estazio meteorologikoa erosten duten askok Irrati Kontrolatutako Erlojua edo baita Erloju Atomikoaren logotipoa ikusi dute ontzian. Hau oso erosoa da, erlojua mahai gainean jarri besterik ez baita behar, eta pixka bat igaro ondoren automatikoki egokituko da ordu zehatzera.
Ikus dezagun nola funtzionatzen duen eta idatzi deskodetzaile bat Python-en.
Denbora sinkronizatzeko sistema desberdinak daude. Europan ezagunena Alemaniako sistema da
Jarraian idatzitako guztia DCF77ri buruzkoa izango da.
Seinalearen harrera
DCF77 77.5 kHz-ko maiztasunarekin funtzionatzen duen uhin luzeko estazioa da eta anplitude-modulazioan seinaleak igortzen ditu. 50KW-ko geltokia Frankfurtetik 25 km-ra dago, 1959an hasi zen martxan eta 1973an dataren informazioa gehitu zitzaion ordu zehatzari. 77 KHz-ko maiztasuneko uhin-luzera oso luzea da, beraz, antena-eremuaren neurriak ere nahiko duinak dira (Wikipediako argazkia):
Halako antena eta potentzia sarrerarekin, harrera-eremuak ia Europa osoa hartzen du, Bielorrusia, Ukraina eta Errusia zati bat.
Edonork graba dezake seinale bat. Horretarako, sareko hargailura joan besterik ez dago
Bertan deskargatzeko botoia sakatu eta zati bat grabatzen dugu minutu batzuetako iraupenaz. Jakina, 77.5KHz-ko maiztasuna grabatzeko gai den hargailu "benetako" bat baduzu, hori erabil dezakezu.
Noski, irrati-ordu-seinaleak Internet bidez jasoz gero, ez dugu denbora benetan zehatza jasoko - seinalea atzerapenarekin transmititzen da. Baina gure helburua seinalearen egitura ulertzea baino ez da; horretarako, Interneten grabatzea nahikoa da. Bizitza errealean, jakina, gailu espezializatuak erabiltzen dira jasotzeko eta deskodetzeko; jarraian aztertuko dira.
Beraz, grabazioa jaso dugu, has gaitezen prozesatzen.
Seinaleen Deskodeketa
Karga dezagun fitxategia Python erabiliz eta ikus dezagun bere egitura:
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()
Anplitudearen modulazio tipikoa ikusten dugu:
Deskodeketa errazteko, har dezagun seinalearen inguratzailea Hilbert transformazioa erabiliz:
analytic_signal = signal.hilbert(data)
A = np.abs(analytic_signal)
plt.plot(A[:100000])
Emaitza handitua:
Leun ditzagun zarata emisioak pasabide baxuko iragazkia erabiliz, eta aldi berean kalkula ditzagun batez besteko balioa, gero analisirako baliagarria izango dena.
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
Emaitza (lerro horia): aztertzeko erraza den uhin ia karratuaren seinalea.
Analisia
Lehenik eta behin bit-sekuentzia lortu behar duzu. Seinalearen egitura bera oso erraza da.
Pultsuak bigarren tarteetan banatzen dira. Pultsuen arteko distantzia 0.1 s bada (hau da, pultsuaren luzera bera 0.9 s da), gehitu "0" bit-sekuentziari; distantzia 0.2 s bada (hau da, luzera 0.8 s), gehitu "1". Minutu bakoitzaren amaiera pultsu "luze" batekin adierazten da, 2 s luze, bit-sekuentzia zerora berrezartzen da eta betetzea berriro hasten da.
Aurrekoa Python-en idazteko erraza da.
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
Ondorioz, bit-sekuentzia bat lortzen dugu, gure adibidean bi segundoz honelakoa da:
0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000
Bide batez, interesgarria da seinaleak datuen "bigarren geruza" ere baduela. Bit-sekuentzia ere erabiliz kodetzen da
Gure azken urratsa: benetako datuak eskuratzea. Bitak segundoko behin transmititzen dira, beraz, guztira 59 bit ditugu, eta horietan informazio dezente kodetzen da:
Bitak atalean deskribatzen dira
Beren kabuz esperimentatu nahi dutenentzat, deskodetzeko kodea spoiler azpian ematen da.
Iturburu kodea
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)
Programa exekutatzen dugunean, honen antzeko irteera ikusiko dugu:
0011110110111000001011000001010000100110010101100010011000
Tuesday, 26.03.19, 21:41
0001111100110110001010100001010000100110010101100010011000
Tuesday, 26.03.19, 21:42
Egia esan, hori da magia guztia. Sistema horren abantaila da deskodetzea oso erraza dela eta edozein mikrokontrolagailutan egin daitekeela, baita mikrokontrolagailurik sinpleenean ere. Pultsuen iraupena zenbatu besterik ez dugu, 60 bit pilatu eta minutu bakoitzaren amaieran denbora zehatza lortzen dugu. Ordua sinkronizatzeko beste metodo batzuekin alderatuta (GPS, adibidez, edo Jainkoak ez dezala Internet:), irrati-sinkronizazioak ez du ia elektrizitaterik behar; adibidez, etxeko eguraldi-estazio arrunt batek urtebete inguru irauten du 2 AA pilekin. Horregatik, eskumuturrekoak ere irrati-sinkronizazioarekin egiten dira, zer esanik ez, noski, hormetako erlojuak edo kaleko geltokietako erlojuak.
DCFren erosotasuna eta sinpletasuna brikolaje zaleak ere erakartzen ditu. 10-20 dolarren truke, prest egindako antena modulu bat erosi dezakezu prest egindako hargailu batekin eta TTL irteerarekin, Arduino edo beste kontrolagailu batera konektatu daitekeena.
Dagoeneko Arduinorako idatzita dago
Nahi dutenek amonaren erloju zaharra ere berritu dezakete irrati sinkronizazioa duen mekanismo berri bat instalatuz:
Ebay-en aurki dezakezu bat "Irradio Kontrolatutako Mugimendua" gako-hitzak erabiliz.
Eta azkenik, honaino irakurri dutenentzat bizitza hack bat. Hurrengo mila kilometroetan irrati-seinale-igorle bakar bat ere ez badago ere, ez da zaila zuk zeuk sortzea seinale hori. Google Play-n "DCF77 Emulator" izeneko programa bat dago seinalea entzungailuetara ateratzen duena. Egilearen arabera, entzungailuen kablea erlojuaren inguruan bilduz gero, seinalea jasoko dute (interesgarria da nola, entzungailu arruntek ez baitute 77KHz-ko seinalerik sortuko, baina harrera harmonikoengatik izango da ziurrenik). Android 9-n, programak ez zuen batere funtzionatu niretzat - ez zegoen soinurik (edo agian ez nuen entzun - 77KHz-koa da, azken finean:), baina agian norbaitek zorte hobea izango du. Batzuek, ordea, DCF seinale-sorgailu oso bat egiten dute, Arduino edo ESP32 berean egiteko erraza dena:
(iturria
Ondorioa
DCF sistema nahiko sinplea eta erosoa izan zen. Hargailu sinple eta merke baten laguntzaz, ordu zehatza beti eta nonahi izan dezakezu, noski harrera gunean. Badirudi digitalizazioa eta gauzen Interneta hedatuta egon arren, horrelako irtenbide sinpleak denbora luzez eskatuko direla.
Iturria: www.habr.com