DCF77:正確な時間信号伝送システムはどのように機能しますか?

こんにちはHabr。



時計やウェザーステーションを購入する多くの人々は、パッケージに電波時計のロゴや原子時計さえ見ました。 これは非常に便利です。テーブルに時計を置くだけで十分であり、しばらくすると、正確な時刻に自動的に調整されます。







それがどのように機能するかを見て、Pythonでデコーダーを書きましょう。



さまざまな時刻同期システムがあります。 ヨーロッパで最もポピュラーなのはドイツのDCF-77システム 、日本では独自のJJYシステム、アメリカではWWVBシステムなどです。 さらに、物語はDCF77についてであり、ロシアのヨーロッパ部分と近隣諸国のいくつかの場所で最も関連性があり、受信可能です(極東の居住者は反対意見を持っているかもしれませんが、彼らは順番に、日本の信号を受け入れて分析できます;)。



以下に書かれていることはすべてDCF77についてのものです。



信号受信



DCF77は、77.5KHzの周波数で動作し、振幅変調で信号を送信する長波ステーションです。 容量50 kWの駅はフランクフルトから25 kmに位置し、1959年に作業を開始しました。1973年に正確な時刻に日付情報が追加されました。 周波数77KHzの波長は非常に大きいため、アンテナフィールドの寸法も非常に適切です(Wikipediaの写真)。







このようなアンテナと電源入力により、受信エリアはヨーロッパ、ベラルーシ、ウクライナ、ロシアの一部のほぼ全域をカバーしています。







誰でも信号を記録できます。 これを行うには、オンラインレシーバーhttp://websdr.ewi.utwente.nl:8901/に移動し、76.5KHzとUSB変調の周波数を選択します。 次のような画像が開きます。







そこで、ダウンロードボタンを押して、数分の断片を記録します。 もちろん、77.5KHzの周波数を記録できる「実際の」レシーバーがある場合は、それを使用できます。



もちろん、インターネットを介して正確な時間の無線信号を受信した場合、実際の正確な時間は得られません。信号は遅れて送信されます。 しかし、私たちの目標は、信号の構造を理解することだけです;このためには、インターネット録音で十分です。 現実の世界では、もちろん、受信とデコードのための特殊なデバイスが使用されます。それらについては以下で説明します。



それで、レコードを取得したので、処理を始めましょう。



信号デコード



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」を追加します。 各分の終わりは、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
      
      





その結果、ビットのシーケンスを取得します。この例では2分間、次のようになります。



0011110110111000001011000001010000100110010101100010011000

0001111100110110001010100001010000100110010101100010011000








ところで、信号にデータの「第2層」があるのは興味深いことです。 ビットシーケンスも位相変調を使用してコード化されます。 理論的には、これにより、信号が弱くなった場合でも、より安定したデコードが提供されます。



最後のステップ:実際のデータを取得します。 ビットは1秒間に1回送信されるため、多くの情報がエンコードされる59ビットのみがあります。







これらのビットはWikipediaで説明されており、かなり好奇心are盛です。 最初の15ビットは使用されませんが、警告システムと民間防衛に使用する計画がありました。 ビットA1は、次の1時間で時計が夏時間に設定されることを示します。 ビットA2は、次の1時間で1 秒余分に追加されることを示します。これは、地球の回転に応じて時刻を修正するために使用されることがあります。 残りのビットは、時間、分、および日付をエンコードします。







自分で実験したい人のために、デコード用のコードはネタバレの下にあります。



ソースコード
 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 AAバッテリーで約1年間動作します。 そのため、腕時計でも、もちろん、壁や通りの駅について、無線同期で作られています。



DCFの便利さとシンプルさは、自家製製品の愛好家を惹きつけます。 たった10〜20ドルで、既成のレシーバーとTTL出力を備えたアンテナから既成のモジュールを購入でき、Arduinoまたは他のコントローラーに接続できます。







Arduinoについては、 既製のライブラリがすでに作成されています。 ただし、マイクロコントローラーで何をするにしても、時計か気象観測所のどちらかを取得することは既に知られています。 もちろん、レセプションエリアにいる場合を除き、このようなデバイスを使用して正確な時刻を取得するのは非常に簡単です。 さて、あなたは時計に「原子時計」という碑文を掛け、同時にそれを望むすべての人に、原子時計を使用してデバイスが本当に同期されていることを説明できます。



希望する人は、ラジオ同期を備えた新しいメカニズムをインストールすることで、古い祖母の時計をアップグレードすることもできます。







キーワード「Radio Controlled Movement」を使用して、ebayで1つを見つけることができます。



そして最後に、ここを読んだ人のためのライフハック。 次の数千kmに無線信号の送信機が1つもない場合でも、そのような信号は簡単に独立して生成できます。 Google Playには、ヘッドフォンに信号を出力する「DCF77 Emulator」というプログラムがあります。 著者によると、時計にヘッドフォンワイヤを巻き付けると、信号をキャッチします(普通のヘッドフォンは77KHzの信号を出さないが、おそらく受信は高調波から来るので、どうしたらいいのだろうか)。 私のプログラムはAndroid 9ではまったく動作しませんでした-単に音が聞こえなかった(または、おそらく聞こえなかった-結局77KHz :)が、誰かがより幸運になるかもしれません。 ただし、一部は、同じArduinoまたはESP32で簡単に実行できる本格的なDCF信号ジェネレーターです。





(ソースsgfantasytoys.wordpress.com/2015/05/13/synchronize-radio-controlled-watch-without-access



おわりに



DCFシステムは非常にシンプルで便利であることがわかりました。 シンプルで安価な受信機の助けを借りて、いつでも、どこでも、もちろん受付エリアで正確な時間を過ごすことができます。 普及したデジタル化と「モノのインターネット」にもかかわらず、このようなシンプルなソリューションは今後長い間求められているようです。



All Articles