Салам Хабр.
Саат же аба ырайы станциясын сатып алгандардын көбү таңгагында Радио башкарылуучу саатты же атүгүл атомдук сааттын логотибин көргөн болуш керек. Бул абдан ыңгайлуу, анткени саатты столдун үстүнө коюу керек, бир аз убакыттан кийин ал автоматтык түрдө так убакытка ылайыкталат.

Келгиле, анын кантип иштээрин аныктап көрөлү жана Pythonдо декодер жазалы.
Ар кандай убакыт синхрондоштуруу системалары бар. Европада эң популярдуусу немис системасы , Япониянын өзүнүн системасы бар , АКШда система бар , жана башка. Кийинки, окуя DCF77 жөнүндө болот, анткени Россиянын европалык бөлүгүнүн айрым жерлеринде жана коңшу мамлекеттерде кабыл алуу үчүн эң актуалдуу жана жеткиликтүү (Ыраакы Чыгыштын тургундары карама-каршы пикирге ээ болушу мүмкүн, бирок алар өз кезегинде жана япон сигналын талдоо;).
Төмөндө жазылгандардын баары DCF77 жөнүндө болот.
Сигнал кабыл алуу
DCF77 — 77.5 кГц жыштыкта иштеген жана амплитудалык модуляцияда сигналдарды берүүчү узун толкун станциясы. 50KW станциясы Франкфурттан 25 км алыстыкта жайгашкан, ал 1959-жылы иштей баштаган жана 1973-жылы датасы тууралуу маалымат так убакытка кошулган. 77 кГц жыштыктагы толкун узундугу абдан узун, антенна талаасынын өлчөмдөрү да абдан татыктуу (Википедиядан алынган сүрөт):

Мындай антенна жана электр киргизүү менен кабыл алуу зонасы дээрлик Европаны, Белоруссияны, Украинаны жана Орусиянын бир бөлүгүн камтыйт.

Ар бир адам сигнал жаздыра алат. Бул үчүн, жөн гана онлайн ресиверге барыңыз , ал жерде 76.5KHz жыштыгын жана USB модуляциясын тандаңыз. Төмөнкүдөй көрүнгөн сүрөт ачылышы керек:

Ал жерден биз жүктөп алуу баскычын басып, бир нече мүнөткө созулган фрагментти жаздырабыз. Албетте, эгер сизде 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 бит бар, аларда абдан көп маалымат коддолгон:

Биттер сүрөттөлгөн , жана алар абдан кызык. Алгачкы 15 бит колдонулбайт, бирок аларды эскертүү системалары жана жарандык коргонуу үчүн колдонуу пландалган. Бит A1 саат кийинки саатта жайкы убакытка өзгөрөрүн көрсөтөт. Bit A2 кошумча экенин көрсөтүп турат , ал кээде Жердин айлануусуна ылайык убакытты тууралоо үчүн колдонулат. Калган биттер сааттарды, мүнөттөрдү, секунддарды жана күндү коддойт.

Өз алдынча эксперимент жасоону каалагандар үчүн декоддоо коду спойлердин астында берилген.
Баштапкы код
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 долларга сиз Arduino же башка контроллерге туташтырылган даяр кабылдагыч жана TTL чыгышы бар даяр антенна модулун сатып алсаңыз болот.

Arduino үчүн мурунтан эле жазылган . Бирок, микроконтроллерде эмне кылбаңыз, сизде саат же метеостанция пайда болоору буга чейин белгилүү. Мындай аппарат менен так убакытты алуу чындап эле оңой, албетте, сиз кабыл алуу зонасында болсоңуз. Макул, сиз саатыңызга "Атомдук саат" деген жазууну илип койсоңуз болот, ошол эле учурда бардыгына аппарат атомдук сааттын жардамы менен синхрондоштурулганын түшүндүрө аласыз.
Каалоочулар радио синхрондоштуруу менен жаңы механизмди орнотуу менен эски чоң энесинин саатын жаңырта алышат:

Сиз "Radio Controlled Movement" деген ачкыч сөздөрдү колдонуп, ebay сайтынан таба аласыз.
Акырында, бул жерге чейин окугандар үчүн жашоонун хакы. Бир нече миң километрдин ичинде бир дагы радио өткөргүч жок болсо да, аны өз алдынча жасоо оңой. Google Play'де кулакчындарга сигнал чыгаруучу "DCF77 Emulator" деп аталган тиркеме бар. Автордун айтымында, эгер сиз кулакчындын кабелин сааттын айланасына ороп койсоңуз, ал сигналды кабыл алат (кадимки кулакчындар 77 кГц сигнал чыгарбагандыктан, бирок бул гармоникадан улам болушу мүмкүн). Менин саатымда... Android 9-программа такыр иштеген жок — жөн гана үн жок болчу (же балким, мен жөн гана уга алган жокмун — ал 77 кГц, баары бир :)), бирок балким, башка бирөөнүн бактысына туш болот. Бирок, кээ бир адамдар өздөрүнүн толук кандуу DCF сигнал генераторун курушат, аны Arduino же ESP32 аркылуу жасоо оңой:

(булак )
жыйынтыктоо
DCF системасы чынында эле абдан жөнөкөй жана ыңгайлуу болуп чыкты. Жөнөкөй жана арзан ресивердин жардамы менен сиз так убакытты ар дайым жана бардык жерде, албетте кабыл алуу зонасында ала аласыз. Кеңири жайылган санариптештирүү жана нерселердин интернетине карабастан, мындай жөнөкөй чечимдер көпкө суроо-талапка ээ болот окшойт.
Source: www.habr.com
