Салом Хабр.
Эҳтимол, бисёре аз онҳое, ки соат ё истгоҳи обу ҳаво мехаранд, дар бастабандӣ Соати Радиои идорашаванда ё ҳатто логотипи Atomic Clock-ро дидаанд. Ин хеле қулай аст, зеро ба шумо танҳо соатро ба рӯи миз гузоштан лозим аст ва пас аз чанде он ба таври худкор ба вақти дақиқ мувофиқат мекунад.
Биёед бифаҳмем, ки он чӣ гуна кор мекунад ва дар Python декодер нависед.
Системаҳои гуногуни ҳамоҳангсозии вақт вуҷуд доранд. Дар Аврупо маъмултарин системаи Олмон аст
Ҳама чизе, ки дар зер навишта шудааст, дар бораи DCF77 хоҳад буд.
Қабули сигнал
DCF77 як истгоҳи мавҷи дарозест, ки бо басомади 77.5 кГц кор мекунад ва сигналҳоро дар модулятсияи амплитуда интиқол медиҳад. Истгоҳи 50 кВт дар 25 км аз Франкфурт ҷойгир аст, он соли 1959 ба кор шурӯъ кард ва дар соли 1973 маълумот оид ба таърихи дақиқ ба вақти дақиқ илова карда шуд. Дарозии мавҷ дар басомади 77 КГс хеле дароз аст, аз ин рӯ андозаҳои майдони антенна низ хеле мувофиқанд (акс аз Википедиа):
Бо чунин мавҷгир ва вуруди нерӯи барқ, минтақаи қабул қариб тамоми Аврупо, Беларус, Украина ва як қисми Русияро фаро мегирад.
Ҳар як шахс метавонад сигналро сабт кунад. Барои ин, танҳо ба қабулкунандаи онлайн равед
Дар он ҷо мо тугмаи зеркашӣро пахш мекунем ва порчаро чанд дақиқа сабт мекунем. Албатта, агар шумо қабулкунаки "воқеӣ" дошта бошед, ки қодир ба сабти басомади 77.5 кГц аст, шумо метавонед онро истифода баред.
Албатта, бо қабули сигналҳои вақти радио тавассути Интернет, мо вақти воқеан дақиқро қабул намекунем - сигнал бо таъхир интиқол дода мешавад. Аммо ҳадафи мо танҳо фаҳмидани сохтори сигнал аст, барои ин, сабти интернет беш аз кофӣ аст. Дар ҳаёти воқеӣ, албатта, дастгоҳҳои махсус барои қабул ва рамзкушоӣ истифода мешаванд, онҳо дар поён муҳокима хоҳанд шуд.
Пас, мо сабтро гирифтем, биёед коркарди онро оғоз кунем.
Рамзи рамзгузории сигнал
Биёед файлро бо Python бор кунем ва сохтори онро бубинем:
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()
Мо модуляцияи маъмулии амплитударо мебинем:
Барои содда кардани рамзкушоӣ, биёед лифофаи сигналро бо истифода аз табдили Ҳилберт гирем:
analytic_signal = signal.hilbert(data)
A = np.abs(analytic_signal)
plt.plot(A[:100000])
Натиҷаи васеъшуда:
Биёед бо истифода аз филтри пастгузар партовҳои садоро ҳамвор кунем ва дар айни замон арзиши миёнаро ҳисоб кунем, ки баъдтар барои таҳлил муфид хоҳад буд.
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
Натиҷа (хати зард): сигнали мавҷи тақрибан мураббаъ, ки таҳлилаш хеле осон аст.
Таҳлил
Аввал шумо бояд пайдарпайии битро гиред. Худи сохтори сигнал хеле содда аст.
Набзҳо ба фосилаҳои дуюм тақсим карда мешаванд. Агар масофаи байни импулсҳо 0.1 сония бошад (яъне дарозии худи импулс 0.9 сония бошад), ба пайдарпаии бит “0” илова кунед; агар масофа 0.2 сония (яъне дарозӣ 0.8 сония) бошад, “1” илова кунед. Анҷоми ҳар як дақиқа бо як набзи "дароз" нишон дода мешавад, ки 2 сония тӯл мекашад, пайдарпаии бит ба сифр барқарор карда мешавад ва пуркунӣ дубора оғоз мешавад.
Навиштани дар боло бо 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
Дар натиҷа, мо пайдарпайии битҳоро мегирем, дар мисоли мо барои ду сония чунин менамояд:
0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000
Дар омади гап, ҷолиб он аст, ки сигнал инчунин "қабати дуюми" маълумот дорад. Пайдарпаии бит низ бо истифода аз рамзгузорӣ карда мешавад
Қадами охирини мо: гирифтани маълумоти воқеӣ. Битҳо дар як сония як маротиба интиқол дода мешаванд, аз ин рӯ мо ҳамагӣ 59 бит дорем, ки дар онҳо маълумоти зиёде рамзгузорӣ шудааст:
Лаҷом дар
Барои онҳое, ки мехоҳанд мустақилона озмоиш кунанд, рамзи рамзкушоӣ дар зери спойлер дода шудааст.
Рамзи манбаъ
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)
Вақте ки мо барномаро иҷро мекунем, мо натиҷаи ба ин монандро мебинем:
0011110110111000001011000001010000100110010101100010011000
Tuesday, 26.03.19, 21:41
0001111100110110001010100001010000100110010101100010011000
Tuesday, 26.03.19, 21:42
Дар асл, ин ҳама ҷоду аст. Бартарии ин гуна система дар он аст, ки рамзкушоӣ бениҳоят содда аст ва онро дар ҳама гуна микроконтроллер ҳатто соддатарин иҷро кардан мумкин аст. Мо танҳо дарозии импулсҳоро ҳисоб мекунем, 60 бит ҷамъ мекунем ва дар охири ҳар дақиқа мо вақти дақиқро мегирем. Дар муқоиса бо усулҳои дигари ҳамоҳангсозии вақт (масалан, GPS, ё Худо накунад, Интернет:), чунин ҳамоҳангсозии радио амалан нерӯи барқро талаб намекунад - масалан, як истгоҳи муқаррарии обу ҳаво тақрибан як сол бо 2 батареяи АА кор мекунад. Аз ин рӯ, ҳатто соатҳои дастӣ бо синхронизатсияи радио сохта мешаванд, албатта, соатҳои деворӣ ё соатҳои истгоҳи кӯчаро қайд намекунанд.
Бароҳатӣ ва соддагии DCF инчунин мухлисони DIYро ҷалб мекунад. Ба маблағи ҳамагӣ 10-20 доллар шумо метавонед як модули антеннаи тайёрро бо қабулкунаки тайёр ва баромади TTL, ки метавонад ба Arduino ё дигар контроллер пайваст шавад, харед.
Аллакай барои Arduino навишта шудааст
Онҳое, ки мехоҳанд ҳатто соатҳои бибии кӯҳнаи худро бо насби механизми нав бо синхронизатсияи радио такмил диҳанд:
Шумо метавонед онро дар ebay бо истифода аз калимаҳои калидӣ "Ҳаракати радиои идорашаванда" пайдо кунед.
Ва ниҳоят, лайф-хак барои онҳое, ки то имрӯз хондаанд. Хатто агар дар ду-ду хазор километри наздик ягон радиосигнал фиристанда набошад хам, худи хамин гуна сигналро хосил кардан душвор нест. Дар Google Play барномае мавҷуд аст, ки "DCF77 Emulator" ном дорад, ки сигналро ба гӯшмонакҳо мебарорад. Ба гуфтаи муаллиф, агар шумо сими гӯшмонакҳоро дар атрофи соат печонед, онҳо сигналро қабул мекунанд (чи тавр ҷолиб аст, зеро гӯшмонакҳои оддӣ сигнали 77 кГц тавлид намекунанд, аммо қабул эҳтимол аз гармоника аст). Дар Android 9, барнома барои ман тамоман кор накард - танҳо садо набуд (ё шояд ман онро нашунидам - ин 77 кГц аст, дар ниҳоят :)), аммо шояд касе барори беҳтаре дошта бошад. Аммо, баъзеҳо худро як генератори сигнали DCF месозанд, ки онро дар ҳамон Arduino ё ESP32 сохтан осон аст:
(сарчашма
хулоса
Системаи DCF воқеан хеле содда ва қулай шуд. Бо ёрии приёмник оддӣ ва арзон шумо метавонед ҳамеша ва дар ҳама ҷо, албатта, дар минтақаи қабул вақти дақиқ дошта бошед. Чунин ба назар мерасад, ки ҳатто сарфи назар аз рақамикунонии васеъ ва Интернети ашё, чунин ҳалли оддӣ барои муддати тӯлонӣ талаб карда мешавад.
Манбаъ: will.com