DCF77:准确的时间信号传输系统如何工作?

哈Ha

可能有很多购买手表或气象站的人在包装上看到了无线电钟的徽标,甚至是原子钟。 这非常方便,因为将时钟放在桌子上就足够了,过一会儿它们会自动调整为准确的时间。



让我们看看它是如何工作的,并用Python编写一个解码器。

有不同的时间同步系统。 在欧洲最受欢迎的是德国的DCF-77系统 ,日本有自己的JJY系统,美国有WWVB系统,依此类推。 此外,故事将是关于DCF77的故事,DCF77是最相关的并且可以在俄罗斯欧洲部分地区和邻国的某些地方接收(远东地区的居民可能有相反的看法,但是他们反过来可以接收和分析日本的信号;)。

下面写的所有内容都与DCF77有关。

信号接收


DCF77是一个长波站,工作频率为77.5KHz,并以调幅方式发送信号。 容量为50 kW的电站位于距法兰克福25公里的地方,其始建于1959年,1973年将日期信息添加到准确的时间。 频率为77KHz时的波长非常大,因此天线场的尺寸也非常合适(来自Wikipedia的照片):



有了这样的天线和电源输入,接收区域几乎覆盖了整个欧洲,白俄罗斯,乌克兰和俄罗斯的部分地区。



每个人都可以录制信号。 为此,只需转到在线接收器http://websdr.ewi.utwente.nl:8901/ ,在此处选择76.5KHz的频率并进行USB调制。 这样的图片应该打开:



在那里,我们按下下载按钮,并记录了几分钟的片段。 当然,如果您有一个能够记录77.5KHz频率的“真实”接收器,则可以使用它。

当然,当我们通过Internet接收到准确时间的无线电信号时,我们将不会获得真正准确的时间-信号被延迟发送。 但是我们的目标仅仅是了解信号的结构;为此,Internet记录已绰绰有余。 当然,在现实生活中,会使用用于接收和解码的专用设备,下面将对其进行讨论。

因此,我们得到了记录,让我们开始处理它。

信号解码


使用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 s(即脉冲本身的长度为0.9 s),则在位序列中添加“ 0”;如果距离为0.2 s(即长度为0.8 s),则添加“ 1”。 每分钟的结束由2s长的“长”脉冲指示,位序列重置为零,然后重新开始填充。

上面的代码很容易用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个比特,其中编码了很多信息:



这些位在Wikipedia上进行了描述,并且非常好奇。 尽管已经计划将其用于预警系统和民防系统,但并未使用前15位。 位A1表示下一小时时钟将设置为夏令时。 位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或Internet禁止使用Internet :)相比,这种无线电同步实际上不需要电-例如,普通的家庭气象站使用2节AA电池可工作约一年。 因此,即使是手表,也具有无线电同步功能,更不用说墙壁或街道站了。

DCF的便捷和简单吸引了自制产品的爱好者。 仅需10至20美元,您就可以从天线上购买一个现成的模块,该天线带有现成的接收器和TTL输出,可以连接到Arduino或其他控制器。



对于Arduino,已经编写了现成的库 。 但是,众所周知,无论您在微控制器上做什么,都会得到时钟或气象站。 使用这样的设备,只要您在接待区,就可以很容易地获得准确的时间。 好了,您可以在手表上悬挂“ Atomic Clock”字样,同时向所有需要它的人解释,该设备实际上是使用原子钟同步的。

那些愿意的人甚至可以通过安装带有无线电同步功能的新机制来升级旧祖母的手表:



您可以在eBay上使用关键字“无线电遥控运动”找到一个。

最后,对于那些在这里阅读过文章的人来说,这是一个生活技巧。 即使在接下来的数千公里中没有一个无线电信号的发送器,这种信号也很容易独立产生。 Google Play有一个名为“ DCF77 Emulator”的程序,可将信号输出到耳机。 根据作者的说法,如果将耳机线缠在手表上,它们会捕获信号(我不知道是怎么回事,因为普通耳机不会给出77KHz信号,但是接收信号可能来自谐波)。 我的程序根本无法在Android 9上运行-根本没有声音(或者也许我听不到-毕竟是77KHz :),但是也许有人会更幸运。 但是,有些人使自己成为了成熟的DCF信号发生器,可以在同一Arduino或ESP32上轻松实现:


(来源sgfantasytoys.wordpress.com/2015/05/13/synchronize-radio-control-watch-without-access

结论


事实证明,DCF系统确实非常简单和方便。 借助价格便宜的简单接收器,您可以随时随地在接收区获得准确的时间。 看起来,尽管数字化和“物联网”已经广泛使用,但在很长一段时间内仍将需要这种简单的解决方案。

Source: https://habr.com/ru/post/zh-CN445470/


All Articles