Sugeng Habr.
Mbokmenawa akeh sing tuku jam tangan utawa stasiun cuaca wis ndeleng Jam Kontrol Radio utawa logo Jam Atom ing kemasan. Iki trep banget, amarga sampeyan mung kudu nyelehake jam ing meja, lan sawise sawetara wektu bakal kanthi otomatis nyetel wektu sing tepat.
Ayo ngerteni cara kerjane lan nulis decoder ing Python.
Ana macem-macem sistem sinkronisasi wektu. Sing paling populer ing Eropa yaiku sistem Jerman
Kabeh sing ditulis ing ngisor iki bakal dadi babagan DCF77.
Resepsi sinyal
DCF77 minangka stasiun gelombang dawa sing beroperasi kanthi frekuensi 77.5 kHz lan ngirim sinyal kanthi modulasi amplitudo. Stasiun 50KW dumunung 25 km saka Frankfurt, wiwit operasi ing 1959, lan ing 1973 informasi tanggal ditambahake kanggo wektu pas. Dawane gelombang kanthi frekuensi 77 KHz dawa banget, mula dimensi antena uga cukup prayoga (foto saka Wikipedia):
Kanthi antena lan input daya, area resepsi nyakup meh kabeh Eropa, Belarus, Ukraina lan bagean Rusia.
Sapa wae bisa ngrekam sinyal. Kanggo nindakake iki, mung pindhah menyang panrima online
Ing kana kita pencet tombol download lan ngrekam fragmen sawetara menit. Mesthi, yen sampeyan duwe panrima "nyata" sing bisa ngrekam frekuensi 77.5KHz, sampeyan bisa nggunakake.
Mesthine, kanthi nampa sinyal wektu radio liwat Internet, kita ora bakal nampa wektu sing bener-bener akurat - sinyal kasebut ditularake kanthi wektu tundha. Nanging tujuane mung kanggo ngerti struktur sinyal kasebut, kanggo iki, rekaman Internet luwih saka cukup. Ing urip nyata, mesthi, piranti khusus digunakake kanggo nampa lan dekoding, padha bakal rembugan ing ngisor iki.
Dadi, wis entuk rekaman, ayo diproses.
Decoding sinyal
Ayo mbukak file nggunakake Python lan ndeleng strukture:
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()
Kita ndeleng modulasi amplitudo khas:
Kanggo nyederhanakake dekoding, ayo njupuk amplop sinyal nggunakake transformasi Hilbert:
analytic_signal = signal.hilbert(data)
A = np.abs(analytic_signal)
plt.plot(A[:100000])
Hasil nggedhekake:
Ayo dadi lancar metu emisi swara nggunakake saringan low-pass, lan ing wektu sing padha ngetung nilai rata-rata, kang bakal migunani mengko kanggo parsing.
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
Asil (garis kuning): sinyal gelombang meh persegi sing cukup gampang dianalisis.
Parsing
Pisanan sampeyan kudu njaluk urutan bit. Struktur sinyal dhewe banget prasaja.
Pulsa dipΓ©rang dadi interval kapindho. Yen jarak antarane pulsa yaiku 0.1 detik (yaiku dawane pulsa dhewe yaiku 0.9 detik), tambahake "0" menyang urutan bit; yen jarake 0.2 detik (yaiku dawane 0.8 detik), tambahake "1". Pungkasan saben menit dituduhake kanthi pulsa "dawa", 2s dawa, urutan bit direset menyang nul, lan ngisi diwiwiti maneh.
Ing ndhuwur iku gampang kanggo nulis ing 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
AkibatΓ©, kita entuk urutan bit, ing conto kita sajrone rong detik katon kaya iki:
0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000
Miturut cara, iku menarik yen sinyal uga duwe "lapisan kapindho" data. Urutan bit uga dienkode nggunakake
Langkah pungkasan kita: njupuk data nyata. Bit ditularake sapisan saben detik, dadi kita duwe total 59 bit, sing cukup akeh informasi sing dikode:
Bit diterangake ing
Kanggo sing pengin eksprimen dhewe, kode dekoding diwenehi ing spoiler.
Sumber kode
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)
Nalika kita mbukak program, kita bakal weruh output kaya iki:
0011110110111000001011000001010000100110010101100010011000
Tuesday, 26.03.19, 21:41
0001111100110110001010100001010000100110010101100010011000
Tuesday, 26.03.19, 21:42
Bener, iku kabeh sihir. Kauntungan saka sistem kasebut yaiku dekoding banget prasaja lan bisa ditindakake ing sembarang mikrokontroler, malah sing paling gampang. Kita mung ngetung dawa pulsa, nglumpukake 60 bit, lan ing pungkasan saben menit entuk wektu sing tepat. Dibandhingake karo cara liyane sinkronisasi wektu (GPS, contone, utawa Gusti Allah ngalang-alangi, Internet :)), sinkronisasi radio kuwi sakbenere ora mbutuhake listrik - contone, stasiun cuaca ngarep biasa mlaku kanggo bab setahun ing 2 baterei AA. Mulane, malah jam tangan digawe kanthi sinkronisasi radio, ora kanggo sebutno, mesthi, jam tangan tembok utawa jam tangan stasiun jalanan.
Penak lan kesederhanaan DCF uga narik kawigaten para penggemar DIY. Mung $ 10-20 sampeyan bisa tuku modul antena siap-digawe karo panrima siap-digawe lan output TTL, kang bisa disambungake menyang Arduino utawa controller liyane.
Wis ditulis kanggo Arduino
Sing pengin malah bisa nganyarke jam tangan mbah putri lawas kanthi nginstal mekanisme anyar kanthi sinkronisasi radio:
Sampeyan bisa nemokake siji ing ebay nggunakake tembung kunci "Gerakan Kontrol Radio".
Lan pungkasanipun, hack urip kanggo sing wis maca iki adoh. Sanajan ora ana pemancar sinyal radio siji ing saperangan ewu km sabanjure, ora angel ngasilake sinyal kasebut dhewe. Ana program ing Google Play disebut "DCF77 Emulator" sing output sinyal kanggo headphone. Miturut penulis, yen sampeyan mbungkus kabel headphone ing jam tangan, dheweke bakal njupuk sinyal kasebut (iku menarik, amarga headphone biasa ora bakal ngasilake sinyal 77KHz, nanging resepsi bisa uga amarga harmonik). Ing Android 9, program kasebut ora bisa digunakake kanggo aku - mung ora ana swara (utawa mungkin aku ora krungu - iku 77KHz, sawise kabeh:), nanging bisa uga ana wong sing luwih beruntung. Sawetara, Nanging, nggawe dhewe generator sinyal DCF lengkap, sing gampang digawe ing Arduino utawa ESP32 sing padha:
(sumber
kesimpulan
Sistem DCF ternyata pancen prasaja lan trep. Kanthi bantuan saka panrima prasaja lan mirah, sampeyan bisa duwe wektu pas tansah lan nang endi wae, mesthi ing wilayah reception. Kayane sanajan digitalisasi lan Internet of Things nyebar, solusi sing gampang kaya ngono bakal dikarepake suwe.
Source: www.habr.com