Hello Habr.
Mungkin ramai yang membeli jam tangan atau stesen cuaca telah melihat Jam Kawalan Radio atau logo Jam Atom pada bungkusan. Ini sangat mudah, kerana anda hanya perlu meletakkan jam di atas meja, dan selepas beberapa ketika ia akan menyesuaikan secara automatik dengan masa yang tepat.
Mari kita fikirkan cara ia berfungsi dan tulis penyahkod dalam Python.
Terdapat sistem penyegerakan masa yang berbeza. Yang paling popular di Eropah ialah sistem Jerman
Semua yang ditulis di bawah adalah mengenai DCF77.
Penerimaan isyarat
DCF77 ialah stesen gelombang panjang yang beroperasi pada frekuensi 77.5 kHz dan menghantar isyarat dalam modulasi amplitud. Stesen 50KW terletak 25 km dari Frankfurt, ia mula beroperasi pada tahun 1959, dan pada tahun 1973 maklumat tarikh telah ditambah pada masa yang tepat. Panjang gelombang pada frekuensi 77 KHz adalah sangat panjang, jadi dimensi medan antena juga agak baik (foto dari Wikipedia):
Dengan antena dan input kuasa sedemikian, kawasan penerimaan meliputi hampir seluruh Eropah, Belarus, Ukraine dan sebahagian daripada Rusia.
Sesiapa sahaja boleh merakam isyarat. Untuk melakukan ini, hanya pergi ke penerima dalam talian
Di sana kami menekan butang muat turun dan merekodkan serpihan selama beberapa minit. Sudah tentu, jika anda mempunyai penerima "sebenar" yang mampu merakam frekuensi 77.5KHz, anda boleh menggunakannya.
Sudah tentu, dengan menerima isyarat masa radio melalui Internet, kami tidak akan menerima masa yang benar-benar tepat - isyarat dihantar dengan kelewatan. Tetapi matlamat kami hanya untuk memahami struktur isyarat; untuk ini, rakaman Internet adalah lebih daripada mencukupi. Dalam kehidupan sebenar, sudah tentu, peranti khusus digunakan untuk menerima dan menyahkod; ia akan dibincangkan di bawah.
Jadi, kami telah menerima rakaman itu, mari kita mula memprosesnya.
Penyahkodan Isyarat
Mari muatkan fail menggunakan Python dan lihat strukturnya:
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()
Kami melihat modulasi amplitud biasa:
Untuk memudahkan penyahkodan, mari ambil sampul isyarat menggunakan transformasi Hilbert:
analytic_signal = signal.hilbert(data)
A = np.abs(analytic_signal)
plt.plot(A[:100000])
Hasil yang diperbesarkan:
Mari lancarkan pelepasan hingar menggunakan penapis laluan rendah, dan pada masa yang sama mengira nilai purata, yang akan berguna kemudian untuk penghuraian.
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
Keputusan (garisan kuning): isyarat gelombang hampir persegi yang agak mudah untuk dianalisis.
Menghuraikan
Mula-mula anda perlu mendapatkan urutan bit. Struktur isyarat itu sendiri sangat mudah.
Denyutan dibahagikan kepada selang kedua. Jika jarak antara nadi ialah 0.1s (iaitu panjang nadi itu sendiri ialah 0.9s), tambah "0" pada jujukan bit; jika jaraknya ialah 0.2s (iaitu panjangnya ialah 0.8s), tambah "1". Penghujung setiap minit ditunjukkan oleh nadi "panjang", panjang 2s, jujukan bit ditetapkan semula kepada sifar, dan pengisian bermula semula.
Perkara di atas mudah untuk ditulis dalam 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
Akibatnya, kami mendapat urutan bit, dalam contoh kami selama dua saat ia kelihatan seperti ini:
0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000
Ngomong-ngomong, menarik bahawa isyarat itu juga mempunyai "lapisan kedua" data. Urutan bit juga dikodkan menggunakan
Langkah terakhir kami: mendapatkan data sebenar. Bit dihantar sekali sesaat, jadi kami mempunyai sejumlah 59 bit, di mana agak banyak maklumat dikodkan:
Bit diterangkan dalam
Bagi mereka yang ingin mencuba sendiri, kod penyahkodan diberikan di bawah spoiler.
Kod sumber
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)
Apabila kita menjalankan program, kita akan melihat output yang serupa dengan ini:
0011110110111000001011000001010000100110010101100010011000
Tuesday, 26.03.19, 21:41
0001111100110110001010100001010000100110010101100010011000
Tuesday, 26.03.19, 21:42
Sebenarnya, itu semua keajaiban. Kelebihan sistem sedemikian ialah penyahkodan adalah sangat mudah dan boleh dilakukan pada mana-mana, walaupun mikropengawal yang paling mudah. Kami hanya mengira panjang denyutan, mengumpul 60 bit, dan pada penghujung setiap minit kami mendapat masa yang tepat. Berbanding dengan kaedah penyegerakan masa yang lain (GPS, contohnya, atau Allah melarang, Internet :)), penyegerakan radio sedemikian hampir tidak memerlukan elektrik - contohnya, stesen cuaca rumah biasa berjalan selama kira-kira setahun menggunakan 2 bateri AA. Oleh itu, walaupun jam tangan dibuat dengan penyegerakan radio, apatah lagi, sudah tentu, jam tangan dinding atau jam tangan stesen jalanan.
Kemudahan dan kesederhanaan DCF juga menarik minat peminat DIY. Dengan hanya $10-20 anda boleh membeli modul antena siap pakai dengan penerima siap pakai dan output TTL, yang boleh disambungkan kepada Arduino atau pengawal lain.
Sudah ditulis untuk Arduino
Mereka yang ingin juga boleh menaik taraf jam tangan nenek lama mereka dengan memasang mekanisme baharu dengan penyegerakan radio:
Anda boleh mendapatkannya di ebay menggunakan kata kunci "Pergerakan Terkawal Radio".
Dan akhirnya, hack kehidupan untuk mereka yang telah membaca sejauh ini. Walaupun tidak ada satu pemancar isyarat radio dalam beberapa ribu km akan datang, tidak sukar untuk menjana isyarat sedemikian sendiri. Terdapat program di Google Play yang dipanggil "DCF77 Emulator" yang mengeluarkan isyarat kepada fon kepala. Menurut penulis, jika anda membungkus wayar fon kepala di sekeliling jam tangan, mereka akan mengambil isyarat (menarik caranya, kerana fon kepala biasa tidak akan menghasilkan isyarat 77KHz, tetapi penerimaan mungkin disebabkan oleh harmonik). Pada Android 9, program itu tidak berfungsi sama sekali untuk saya - tiada bunyi (atau mungkin saya tidak mendengarnya - 77KHz, selepas semua:), tetapi mungkin seseorang akan bernasib baik. Sesetengah, bagaimanapun, menjadikan diri mereka sebagai penjana isyarat DCF sepenuhnya, yang mudah dibuat pada Arduino atau ESP32 yang sama:
(sumber
Kesimpulan
Sistem DCF ternyata sangat mudah dan mudah. Dengan bantuan penerima yang mudah dan murah, anda boleh mempunyai masa yang tepat sentiasa dan di mana-mana, sudah tentu di kawasan penerimaan tetamu. Nampaknya walaupun pendigitalan meluas dan Internet of Things, penyelesaian mudah seperti itu akan menjadi permintaan untuk masa yang lama.
Sumber: www.habr.com