Hallo Habr.
Seker baie wat 'n horlosie of 'n weerstasie koop, het die radiobeheerde klok of selfs Atomic Clock-logo op die verpakking gesien. Dit is baie gerieflik, want dit is genoeg om die horlosie op die tafel te sit, en na 'n rukkie sal dit outomaties aanpas by die presiese tyd.
Kom ons vind uit hoe dit werk en skryf 'n dekodeerder in Python.
Daar is verskillende tydsinchronisasiestelsels. Die gewildste in Europa is die Duitse stelsel
Alles wat hieronder geskryf word, gaan oor DCF77.
Sein ontvangs
Die DCF77 is 'n langgolfstasie wat op 77.5KHz werk en AM-seine uitsaai. Die stasie met 'n kapasiteit van 50 kW is 25 km van Frankfurt geleΓ«, dit het in 1959 begin werk, in 1973 is inligting oor die datum by die presiese tyd gevoeg. Die golflengte by 'n frekwensie van 77 kHz is baie groot, so die afmetings van die antennaveld is ook baie ordentlik (foto van Wikipedia):
Met so 'n antenna en insetkrag dek die ontvangsarea byna die hele Europa, Wit-Rusland, OekraΓ―ne en 'n deel van Rusland.
Enigeen kan opneem. Om dit te doen, gaan net na die aanlyn ontvanger
Op dieselfde plek druk ons ββdie aflaai-knoppie en neem 'n fragment van 'n paar minute lank op. Natuurlik, as jy 'n "regte" ontvanger het wat 'n frekwensie van 77.5 kHz kan opneem, kan jy dit gebruik.
Natuurlik, wanneer ons akkurate tydradioseine oor die internet ontvang, sal ons nie 'n werklik akkurate tyd kry nie - die sein word met 'n vertraging versend. Maar ons doel is net om die struktuur van die sein te verstaan, hiervoor is die internetopname meer as genoeg. In die werklike lewe word natuurlik gespesialiseerde toestelle vir ontvangs en dekodering gebruik, hulle sal hieronder bespreek word.
So, ons het die rekord ontvang, kom ons begin dit verwerk.
Sein dekodering
Kom ons laai die lΓͺer met Python en sien die struktuur daarvan:
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()
Ons sien 'n tipiese amplitudemodulasie:
Om dekodering te vereenvoudig, neem ons die seinkoevert deur die Hilbert-transformasie te gebruik:
analytic_signal = signal.hilbert(data)
A = np.abs(analytic_signal)
plt.plot(A[:100000])
Uitgebreide resultaat:
Kom ons maak geraasvrystellings glad met 'n laagdeurlaatfilter, bereken terselfdertyd die gemiddelde waarde, dit sal later handig te pas kom vir ontleding.
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
Resultaat (geel lyn): 'n byna reghoekige sein wat redelik maklik is om te ontleed.
Ontleding
Eerstens moet jy die bietjie volgorde kry. Die seinstruktuur self is baie eenvoudig.
Die pulse word in tweede intervalle verdeel. As die afstand tussen pulse 0.1s is (m.a.w. die lengte van die puls self is 0.9s), voeg ons "0" by die bisreeks, as die afstand 0.2s is (d.w.s. die lengte is 0.8s), voeg ons by "1". Die einde van elke minuut word aangedui deur 'n "lang" puls, 2 s lank, die bisreeks word na nul teruggestel, en die vulling begin weer.
Bogenoemde is maklik om in Python te skryf.
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
As gevolg hiervan kry ons 'n reeks stukkies, in ons voorbeeld vir twee sekondes lyk dit so:
0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000
Terloops, dit is interessant dat daar ook 'n "tweede laag" data in die sein is. Die bissekwensie word ook geΓ«nkodeer met
Ons laaste stap: kry die werklike data. Bits word een keer per sekonde oorgedra, so ons het net 59 bisse, waarin heelwat inligting geΓ«nkodeer is:
Die stukkies word beskryf in
Vir diegene wat op hul eie wil eksperimenteer, word die dekoderingskode onder die bederf gegee.
Bronkode
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)
Deur die program te laat loop, sal ons iets soos hierdie uitset sien:
0011110110111000001011000001010000100110010101100010011000
Tuesday, 26.03.19, 21:41
0001111100110110001010100001010000100110010101100010011000
Tuesday, 26.03.19, 21:42
Eintlik is dit al die magic. Die voordeel van so 'n stelsel is dat dekodering uiters eenvoudig is, en op enige, die mees ongekompliseerde mikrobeheerder gedoen kan word. Ons tel net die lengte van die pulse, versamel 60 bisse, en aan die einde van elke minuut kry ons die presiese tyd. In vergelyking met ander metodes van tydsinchronisasie (GPS, byvoorbeeld, of God verbied, die internet :), benodig sulke radiosinchronisasie feitlik nie elektrisiteit nie - byvoorbeeld, 'n gewone tuisweerstasie werk vir ongeveer 'n jaar op 2 AA-batterye. Daarom word selfs polshorlosies met radiosinchronisasie gemaak, om nie eers te praat van muurhorlosies of straatstasiehorlosies nie.
Die gerief en eenvoud van die DCF lok ook selfdoen-entoesiaste. Vir slegs $10-20 kan jy 'n klaargemaakte antennamodule koop met 'n klaargemaakte ontvanger en 'n TTL-uitset wat aan 'n Arduino of ander beheerder gekoppel kan word.
Vir Arduino reeds geskryf en
Diegene wat wil, kan selfs die ou ouma se horlosie opgradeer deur 'n nuwe meganisme met radiosinchronisasie te installeer:
Jy kan een op ebay vind deur die sleutelwoorde "Radio Controlled Movement" te gebruik.
En laastens, 'n life hack vir diegene wat tot dusver gelees het. Selfs al is daar nie 'n enkele radiosein-sender in die volgende paar duisend kilometer nie, is so 'n sein maklik om op jou eie te genereer. Daar is 'n program op Google Play genaamd "DCF77 Emulator" wat 'n sein na die oorfone uitstuur. Volgens die skrywer, as jy die koptelefoondraad om die klok draai, sal hulle die sein vang (ek wonder hoe, want gewone oorfone sal nie 'n 77KHz sein uitstuur nie, maar waarskynlik is die ontvangs te wyte aan harmonieke). Die program het glad nie vir my op Android 9 gewerk nie - daar was eenvoudig geen klank nie (of miskien het ek dit nie gehoor nie - 77KHz, immers :), maar miskien sal iemand meer gelukkig wees. Sommige maak hulself egter 'n volwaardige DCF-seingenerator, wat maklik is om op dieselfde Arduino of ESP32 te doen:
(bron
Gevolgtrekking
Die DCF-stelsel blyk regtig eenvoudig en gerieflik te wees. Met die hulp van 'n eenvoudige en goedkoop ontvanger kan jy altyd en oral die presiese tyd hΓͺ, natuurlik in die ontvangsarea. Dit blyk dat selfs ten spyte van die wydverspreide digitalisering en die "Internet van Dinge", sulke eenvoudige oplossings nog lank in aanvraag sal wees.
Bron: will.com