Salam Habr.
Yəqin ki, saat və ya hava stansiyası alanların çoxu qablaşdırmada Radio ilə idarə olunan saatı və ya hətta Atom Saatının loqosunu görüblər. Bu çox rahatdır, çünki saatı stolun üstünə qoymaq kifayətdir və bir müddət sonra o, avtomatik olaraq dəqiq vaxta uyğunlaşacaq.

Bunun necə işlədiyini anlayaq və Python-da dekoder yazaq.
Müxtəlif vaxt sinxronizasiya sistemləri var. Avropada ən populyarı Alman sistemidir Yaponiyanın öz sistemi var , ABŞ-da bir sistem var , və s. Bundan əlavə, hekayə DCF77 haqqında olacaq, çünki Rusiyanın Avropa hissəsinin bəzi yerlərində və qonşu ölkələrdə qəbul üçün ən uyğun və əlçatandır (Uzaq Şərqin sakinləri əks fikirdə ola bilər, lakin onlar da öz növbəsində Yapon siqnalını qəbul edin və təhlil edin;).
Aşağıda yazılan hər şey DCF77 haqqında olacaq.
Siqnal qəbulu
DCF77 77.5 KHz tezliyində işləyən və AM siqnallarını ötürən uzundalğalı stansiyadır. 50 kVt gücündə olan stansiya Frankfurtdan 25 km aralıda yerləşir, 1959-cu ildə işə başlamış, 1973-cü ildə tarix haqqında məlumat dəqiq vaxta əlavə edilmişdir. 77 kHz tezliyində dalğa uzunluğu çox böyükdür, buna görə anten sahəsinin ölçüləri də çox layiqdir (Vikipediyadan foto):

Belə bir antenna və giriş gücü ilə qəbul zonası demək olar ki, bütün Avropanı, Belarusiyanı, Ukraynanı və Rusiyanın bir hissəsini əhatə edir.

Hər kəs qeyd edə bilər. Bunu etmək üçün onlayn qəbulediciyə getmək kifayətdir , orada 76.5KHz tezliyini və USB modulyasiyasını seçin. Şəkil belə görünməlidir:

Eyni yerdə yükləmə düyməsini sıxırıq və bir neçə dəqiqəlik bir fraqmenti qeyd edirik. Əlbəttə ki, 77.5 kHz tezliyi qeyd edə bilən "real" qəbulediciniz varsa, ondan istifadə edə bilərsiniz.
Əlbəttə ki, İnternet üzərindən dəqiq vaxt radio siqnallarını qəbul edərək, həqiqətən dəqiq vaxt əldə etməyəcəyik - siqnal gecikmə ilə ötürülür. Ancaq məqsədimiz yalnız siqnalın strukturunu başa düşməkdir, bunun üçün İnternet qeydi kifayət qədərdir. Real həyatda, əlbəttə ki, qəbul və dekodlaşdırma üçün xüsusi cihazlar istifadə olunur, onlar aşağıda müzakirə olunacaq.
Beləliklə, qeydi aldıq, onu emal etməyə başlayaq.
Siqnalın dekodlanması
Faylı Python ilə yükləyək və onun strukturuna baxaq:
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()
Tipik bir amplituda modulyasiyasını görürük:

Deşifrəni asanlaşdırmaq üçün Hilbert transformasiyasından istifadə edərək siqnal zərfini götürürük:
analytic_signal = signal.hilbert(data)
A = np.abs(analytic_signal)
plt.plot(A[:100000])
Genişləndirilmiş nəticə:

Gəlin aşağı ötürücü filtrdən istifadə edərək səs-küy emissiyalarını hamarlayaq, eyni zamanda orta dəyəri hesablayaq, sonra təhlil etmək üçün lazımlı olacaq.
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
Nəticə (sarı xətt): analiz etmək kifayət qədər asan olan demək olar ki, düzbucaqlı siqnal.

Təhlil
Əvvəlcə bit ardıcıllığını əldə etməlisiniz. Siqnal quruluşunun özü çox sadədir.

Nəbzlər ikinci intervallara bölünür. İmpulslar arasındakı məsafə 0.1s olarsa (yəni impulsun uzunluğu 0.9s-dir), bit ardıcıllığına “0” əlavə edirik, əgər məsafə 0.2s (yəni uzunluq 0.8s) olarsa, əlavə edirik “1”. Hər dəqiqənin sonu "uzun" nəbzlə göstərilir, 2 s uzunluğunda, bit ardıcıllığı sıfırlanır və doldurulma yenidən başlayır.
Yuxarıdakıları Python-da yazmaq asandır.
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
Nəticədə, bitlərin ardıcıllığını alırıq, nümunəmizdə iki saniyə belə görünür:
0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000
Yeri gəlmişkən, maraqlıdır ki, siqnalda məlumatların "ikinci təbəqəsi" də var. Bit ardıcıllığı da ilə kodlanır . Teorik olaraq, bu, zəifləmiş siqnal vəziyyətində belə daha güclü dekodlaşdırma təmin etməlidir.
Son addımımız: faktiki məlumatları əldə edin. Bitlər saniyədə bir dəfə ötürülür, ona görə də bizdə kifayət qədər çox məlumat kodlaşdırılan cəmi 59 bit var:

Bitlər -də təsvir edilmişdir və olduqca maraqlıdırlar. İlk 15 bit istifadə edilmir, baxmayaraq ki, onlardan ictimai çıxış və mülki müdafiə sistemləri üçün istifadə etmək planları var idi. Bit A1 növbəti saatda saatın yay vaxtına keçəcəyini bildirir. Bit A2 növbəti saatın əlavə olunacağını göstərir , bəzən Yerin fırlanmasına uyğun olaraq vaxtı düzəltmək üçün istifadə olunur. Qalan bitlər saatları, dəqiqələri, saniyələri və tarixi kodlayır.

Özbaşına sınaq keçirmək istəyənlər üçün deşifrə kodu spoylerin altında verilir.
Mənbə kodu
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)
Proqramı işlədəndə belə bir nəticə görəcəyik:
0011110110111000001011000001010000100110010101100010011000
Tuesday, 26.03.19, 21:41
0001111100110110001010100001010000100110010101100010011000
Tuesday, 26.03.19, 21:42
Əslində, bütün sehr budur. Belə bir sistemin üstünlüyü ondan ibarətdir ki, dekodlaşdırma son dərəcə sadədir və istənilən, ən sadə mikrokontrollerdə edilə bilər. Biz sadəcə impulsların uzunluğunu sayırıq, 60 bit yığırıq və hər dəqiqənin sonunda dəqiq vaxtı alırıq. Vaxt sinxronizasiyasının digər üsulları ilə müqayisədə (məsələn, GPS və ya Allah qorusun, İnternet :), belə radio sinxronizasiyası praktiki olaraq elektrik tələb etmir - məsələn, adi bir ev meteoroloji stansiyası 2 AA batareyasında təxminən bir il işləyir. Buna görə də, hətta qol saatları da radio sinxronizasiyası ilə hazırlanır, əlbəttə ki, divar saatları və ya küçə stansiyası saatlarını qeyd etmirəm.
DCF-nin rahatlığı və sadəliyi də DIY həvəskarlarını cəlb edir. Cəmi 10-20 dollara siz hazır qəbuledicisi və Arduino və ya digər nəzarətçiyə qoşula bilən TTL çıxışı olan hazır anten modulu ala bilərsiniz.

Arduino üçün artıq yazılmış və . Bununla belə, artıq məlumdur ki, mikrokontrollerdə nə edirsinizsə, siz ya saat, ya da hava stansiyası alırsınız. Belə bir cihazla, əlbəttə ki, qəbul zonasında olmasanız, dəqiq vaxtı əldə etmək həqiqətən asandır. Yaxşı, "Atom Saatı" yazısını saata asa bilərsiniz və eyni zamanda hər kəsə cihazın həqiqətən atom saatı ilə sinxronlaşdırıldığını izah edə bilərsiniz.
Arzu edənlər hətta radio sinxronizasiyası olan yeni mexanizm quraşdıraraq köhnə nənənin saatını təkmilləşdirə bilərlər:

Siz ebay-da "Radio Controlled Movement" açar sözlərindən istifadə edərək tapa bilərsiniz.
Və nəhayət, bura qədər oxuyanlar üçün bir həyat fırıldağı. Bir neçə min kilometr məsafədə bir dənə də olsun radio ötürücü olmasa belə, özünüz yaratmaq asandır. Google Play-də qulaqlıqlara siqnal verən "DCF77 Emulator" adlı bir tətbiq var. Müəllif iddia edir ki, qulaqlıq kabelini saatın ətrafına sarsanız, siqnalı tutacaq (maraqlıdır, necə, çünki adi qulaqlıqlar 77 kHz siqnal çıxarmır, amma bu, yəqin ki, harmoniklərə bağlıdır). Mənim saatımda... Android 9-cu proqram heç işləmədi — sadəcə səs yox idi (ya da bəlkə də mən onu eşidə bilmirdim — axı 77 kHz-dir :)), amma bəlkə başqası daha şanslı olar. Lakin bəzi insanlar Arduino və ya ESP32 istifadə edərək asanlıqla hazırlana bilən öz tam hüquqlu DCF siqnal generatorunu qururlar:

(mənbə )
Nəticə
DCF sistemi həqiqətən olduqca sadə və rahat oldu. Sadə və ucuz qəbuledicinin köməyi ilə siz həmişə və hər yerdə, əlbəttə ki, qəbul zonasında dəqiq vaxta sahib ola bilərsiniz. Belə görünür ki, hətta geniş yayılmış rəqəmsallaşmaya və “Əşyaların İnterneti”nə baxmayaraq, belə sadə həllər hələ uzun müddət tələb olunacaq.
Mənbə: www.habr.com
