電波時計が電波を受信しにくい場所でも時刻合わせを可能にする装置を Raspberry Pi を使って作る方法を紹介します.
はじめに
電波時計は 40kHz または 60kHz の電波を使って送られてくる時刻情報に基づいて時間を補正しています.NTP で時刻を正確に合わせた Raspberry Pi から電波を発生させることで,今まで電波時計の恩恵にあずかれなかった時計も時刻を正確にすることができます.
Raspberry Pi 3 や Zero W は無線 LAN に対応していますので,使い勝手としては,Wi-Fi式電波時計用リピータ (P18-NTPWR)と同等のものを実現できます.
回路
作る回路はこんな感じです.LTC1799 を使って 40kHz の信号を発生させておき,その信号と Raspberry Pi の GPOP4 の信号の AND をとって,アンテナをドライブします.
日経 Linux の『ラズパイで電波を送り電波時計を合わせよう』という記事のように Raspberry Pi のみで 40kHz を生成することもできますが,必要以上に消費電力が増加してしまうため,実用性を考えると 40kHz はこのように外部で生成した方がおすすめです.
必要な部品
必要な部品はこんな感じ.
秋月電子 で入手するもの
- 1kHz~30MHz オシレータ LTC1799 モジュール
-
電波時計で使われる 40kHz の出力を発生させる発信器です.
発信回路作ればもっと安価にできますが,手間を考えてこちらを選択しました.
- 多回転半固定ボリューム たて型
-
上記のモジュールと接続して周波数を調整するのに使用します.
- 4回路2入力 NAND ゲート
-
2入力の NAND ゲートが 4 個入った IC です.Raspberry Pi が駆動する IO と発信器の出力を AND するために使用します.
使う周波数が低い(40kHz)なので,3.3V に対応していれば,どれでも良いです.
- NchパワーMOSFET
-
アンテナをドライブするのに使用します.
- 2種ポリウレタン銅線
-
アンテナ用の線です.巻きやすくて切れにくいのでおすすめです.
eBay で入手するもの
- Ferrite Rod Bar Loopstick
-
アンテナ用のフェライトバーです.
もし,リンク先の商品が無い場合は「Ferrite Rod Bar」で検索すると同様のものが見つかると思います.
アンテナの作成
フェライトバーにポリウレタン銅線を巻き付けてアンテナを作ります.
一重ではなく二重に巻く必要があります.一重分の長さしか巻かないと電波の出力が弱かったり電流が流れすぎて発熱したりしますので,頑張って二重に巻きましょう.
巻き終わったら,瞬間接着剤を垂らして固定すれば完成.
基板実装
回路図に従って素子を配線します.
完成したら可変抵抗が 21.7kΩ になるように調整します.これでほぼ 40kHz が出力されるようになるはずです.オシロが手元にあれば,LTC1799 の OUT 端子の出力が 40kHz になることを確認しておくと良いです.
写真では,5V ラインにヒューズを追加していますが,これは 5V ラインがショートしたときの安全対策なので無くても OK です.
ソフト
下記のようなコードを書きます.
NICT が公開している『標準電波の出し方について』というページと照らし合わせていただくと,やっていることは理解できると思います.
Raspberry Pi の GPIO4 端子を回路図の GPOI4 という端子に接続してやれば標準電波を出力するようになります.
GPIO4 以外の端子を使う場合は,GPIP_PORT の部分を適宜修正します.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
#!/usr/bin/python # coding: utf-8 # # JJY タイムコードを出力するスクリプト. # GPIO に H を出力する事で 40kHz パルスが停止する回路を想定 # しています. import RPi.GPIO as GPIO import datetime import time # JJY 時刻符号を出力する端子 GPIP_PORT = 4 def set_pin(mode): GPIO.output(GPIP_PORT, mode) def send_bit(bit): if bit == -1: # マーカ set_pin(1) time.sleep(0.2) set_pin(0) time.sleep(0.799) elif bit == 0: # 0 set_pin(1) time.sleep(0.799) set_pin(0) time.sleep(0.2) elif bit == 1: # 1 set_pin(1) time.sleep(0.499) set_pin(0) time.sleep(0.5) def send_bcd(num, count, parity=0): for i in range(count): bit = (int(num) >> ((count-1) - i)) & 0x1 send_bit(bit) parity ^= bit return parity def send_datetime(now): now = datetime.datetime.now() minute = now.minute hour = now.hour day = now.toordinal() - datetime.date(now.year, 1, 1).toordinal() + 1 year = now.year % 100 wday = now.isoweekday() % 7 sec = now.second usec = now.microsecond min_parity = 0 hour_parity = 0 ############################################################ send_bit(-1) # 10分位のBCD min_parity = send_bcd(minute/10, 3, min_parity) send_bit(0) # 1分位のBCD min_parity = send_bcd(minute%10, 4, min_parity) send_bit(-1) ############################################################ send_bit(0) send_bit(0) # 10時位のBCD hour_parity = send_bcd(hour/10, 2, hour_parity) send_bit(0) # 1時位のBCD hour_parity = send_bcd(hour%10, 4, hour_parity) send_bit(-1) ############################################################ send_bit(0) send_bit(0) # 累計日数100日位のBCD send_bcd(day/100, 2) send_bit(0) # 累計日数10日位のBCD send_bcd((day%100) / 10, 4) send_bit(-1) ############################################################ # 累計日数1日位のBCD send_bcd(day%10, 4) send_bit(0) send_bit(0) # パリティ send_bit(hour_parity) send_bit(min_parity) send_bit(0) send_bit(-1) ############################################################ send_bit(0) # 西暦年10年位のBCD send_bcd((year%100)/10, 4) # 西暦年1年位のBCD send_bcd(year%10, 4) send_bit(-1) ############################################################ # 曜日のBCD send_bcd(wday, 3) send_bit(0) send_bit(0) send_bit(0) send_bit(0) send_bit(0) send_bit(0) # マーカ set_pin(1) time.sleep(0.2) set_pin(0) # 0.8 秒残しておき,次回呼び出しタイミングの調整代とする GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) GPIO.setup(GPIP_PORT, GPIO.OUT) set_pin(0) while True: now = datetime.datetime.now() minute = now.minute sec = now.second usec = now.microsecond # 0 秒になるまで待つ time.sleep(60 - (sec + usec/1000000.0)) send_datetime(now + datetime.timedelta(minutes=1)) |
組み立て
基板むき出しのままだと見た目がわるいので,適当なケースに収納します.
私の場合,IKEA の DRAGAN を使用しました.
電源ケーブルを通すための穴を開け,ケーブルホルダでアンテナを固定してやればこんな感じにわりと
綺麗に収まります.
2週間ほど運用してますが,今のところ快調です.Raspberry Pi Zero W とか使えば5千円もあれば十分できますので,電波時計が合わずに困っている方にはおすすめです.
補足
箱の温度が少し上がっていたので,サーモグラフィーで調べててみました.
アンテナ自体も発熱していますが Raspberry Pi の本体よりは低く,温度上昇としては10℃程度にとどまり問題なさそうです.
コメント
こんにちは、興味津々で読ませてもらっています、プログラムも知らない私です、こんな私でも
サイトを参考にして、見よう見まねで、作っても良いですか?(作れるかどうかも分からない)
使用しているICは、何でしょうか?
本文に追記しました.NAND が入っているものであれば何でも良いと思います.
情報ありがとうございます。助かります。とりあえず、eBayでフィライト注文しました。
大変参考になりました。ありがとうございます。
当方の腕時計、目覚まし時計は、受信している様子でしたが、
最終的になぜか更新されないため、原因を探りました。
そこで、年内通算日を以下のように修正したところ、
無事に受信・更新されるようになりました。
年内通算日は1月1日が「1」になりますので、
46行目の「datetime.date(now.year, 1, 1)」は、
「datetime.date(now.year – 1, 12, 31)」が正しいかと思います。
カレンダーを自前で持っている時計は、
おそらく日付と曜日の照合をしているためエラーとなりましたが、
日付表示のない時計は異常が出ないかもしれませんね。
コメントありがとうございます.
その通りですね.
本文の方は修正させていただきます.
Nch FETは負荷のGND側につけるのが通例だと思います。
この回路でも動作しますが、アンテナコイルにかかる電圧分GNDからFETのソース電位が浮きますので、ゲート・ソース電圧が3.3Vでは無く、(3.3-コイルにかかる電圧)Vとなってしまい、うまくONに成りきらない時間が存在します。
(実際手元でこのページの通りの回路を組むと、アンテナ用の電源が5Vに対して実際の出力が3V程度(アンテナの代わりに390Mの抵抗をかませ、そこにかかる電圧)になっています。FETをGND側に入れれば問題なく5Vかかりました。)
FETの位置を変更するだけで、プログラムに変更は必要ありません。
参考までによろしくお願いします。
> Nch FETは負荷のGND側につけるのが通例だと思います。
そうですね.なんか理由あったけ?と考えてみましたが特になさそうなので,
GND 側に付けるのが良さそうです.
指摘ありがとうございます.
> FETの位置を変更するだけで、プログラムに変更は必要ありません。
アンテナの発熱が増すと思いますので,熱くなっていたら 150行目を次のようにして,
送信間隔を2分おきにすると良いかもしれません.
time.sleep(60*2 – (sec + usec/1000000.0))
電波時計のリピターを検索していたらたどり着きました。
# GPIO に H を出力する事で 40kHz パルスが停止する回路を想定しています.
となっていますがANDをとっていてN-MOSなのでゲートがHI(3.3V)の時に電流が流れるので
Hの時にパルス発生じゃないでしょうか?
それかN-MOSでVgsが4VのFETですがちゃんと電流が流れたでしょうか?
またソースをGND、ドレイン-5V間にコイルをつなげないと折角の5Vがつかえないともったいないいと思います。
これらが解決したら製作したいと思います。
ご指摘の通りです.
上の方で別の方からも回路図の不備を指摘いただいており,何か辺だと思い直して調べてみたところ,実際に使っている回路と回路図が違っていました.
回路図を修正しましたので,確認お願いします.
>それかN-MOSでVgsが4VのFETですがちゃんと電流が流れたでしょうか?
こちらは問題ないです.3.3V でも 10A 程度は流せるので,今回の目的では 3.3V ドライブでも
目的は果たせます.
さっそくの返信ありがとうございます。
ラズパイも初めて触るので心配ですが
トライしようと思います。
40KHz Or 60KHzは74HC00がNAND4回路入りなので
2回路でAND、もう残りでXTALで発信させようと思います。
こんにちは。私も現在NTPリピーターを自作している最中で非常に参考にさせていただいています。アンテナ用のポリウレタン線の線径は何mmのものをお使いでしょうか?
0.29mmの物を使っています。太いタイプも試しましたが、こちらの方が電波の飛びが良かったです。
購入するのは高価なので、何とか自作を考えていましたら、こちらにたどり着きました。
素晴らしい情報をありがとうございます。
プログラミングは初心者でして、申し訳ありませんが、教えてください。
下記のエラーが出てしまいます。
何が原因でしょうか。
お手数お掛けしますが、よろしくお願いします。
Traceback (most recent call last):
File “/home/pi/time.py”, line 152, in
send_datetime(now + datetime.timedelta(minutes=1))
File “/home/pi/time.py”, line 59, in send_datetime
min_parity = send_bcd(minute/10, 3, min_parity)
File “/home/pi/time.py”, line 37, in send_bcd
bit = (num >> ((count-1) – i)) & 0x1
TypeError: unsupported operand type(s) for >>: ‘float’ and ‘int’
コードが Python 3.x に対応していなかったので修正しました.
再度コードをコピペしてみてください.
修正内容としては send_bcd 関数のなかで num を int(num) に変更しています.
早々のご対応ありがとうございます。
正常に動作しています。
他の記事も参考にさせていただきたいと思います。
はじめまして、素晴らしい記事をありがとうございます!
私もこちらの記事を見てリピーター作成に挑戦してみようと思っています。
大変恐縮ですが、ご質問がございます:
・基板の写真を見ると、アンテナのコネクタ付近に小さい部品(ダイオード?)が3個あります。回路図にはこの部品は見当たらないように思えるのですが、これらは何のためについているものでしょうか?
・ヒューズは必須ではないとの事ですが、参考までにご使用のヒューズをお教えいただけませんでしょうか?
はじめまして.
ダイオードは試行錯誤する過程で付けたモノで,記載した回路図の場合は不要な部品になります.
ヒューズ周りの部品は下記を使っています.
http://akizukidenshi.com/catalog/g/gP-09745/
http://akizukidenshi.com/catalog/g/gP-07136/
お返事ありがとうございます。
フェライトロッドが届くまでしばらくかかりそうですが、それまでにいろいろ実験してみようと思います。
はじめまして
とても参考になる記事で非常に助かります。
家の中では電波時計が全く受信できない環境のため、私も是非作ろうと秋月で部品を調達したのですが、制作にあたりアンテナについていくつかわからない事があるので教えて下さい。
通常運用時5Vラインの消費電力はどの程度になるでしょうか?
このアンテナでどの位電波が飛ぶのでしょうか?
よろしければ教えて頂けるとありがたいです。
電源ラインは,Raspberry Pi も含めて1A程度になります.
電波の飛びは環境にも依存すると思いますが,普通の一戸建てで二階の隅に設置した状態で,一階の反対側の時計でもなんとか受信できています.同じ階であればほぼ問題ない感じです.
コメントありがとうございました。
やはり結構大きな電流が流れるのですね。
お陰様でアンテナ部分以外は完成しており、簡易オシロで綺麗なJJY信号が出ているところまでは確認できたのですが、電波に疎くてこのアンテナの出力が微弱無線なのかどうか判らなかったのですが、せいぜい自宅範囲内の出力なのですね。
DIYソーラーでほったらかしで運用しようかと思っていたのですが、あまり電力の無駄遣いをしたくないので、深夜の2時から4時の間だけ出力するように調整しようと思います。
初めまして。
タイムコードを音声信号として出力するJavaScriptでのシミュレータを作成した経験があり、余らせているスマホやPCが何台かあるため、これを利用して「Raspberry PiのGPOP4の信号とのANDをとる」という部分の代わりにオーディオ入力からの音声信号でON/OFFさせたいと考えているのですが、どのような回路にしたらよいでしょう。
入力された音声信号は周波数の判別などは無しで、単純に音量レベルを閾値としてだいたい50%以上ならON、それ以下ならOFFというものにできればと思っています。
はじめまして。
このエントリの記事を参考にさせて頂き、ESP32で同じ回路を組みました。
プログラムは今から書くのですが、ハードの方はCPU以外はほぼそのまま使用させて頂きました。(ESP32のリセットのために、USB-シリアル変換のRTSをESP32のリセットピン(EN)に接続するというようなものは追加しています)
ありがとうございましたm(_ _)m
大変参考になる記事をありがとうございます。
一点質問させてください。アンテナですが、フェライトバーに直接ポリウレタン銅線を巻き付けているのでしょうか。間に何か挟む必要があるのか気になっておりました。
直接ポリウレタン導線を巻き付けています.
早速のお返事ありがとうございます。
直接巻きつけるやり方で試してみようと思います!
とても参考になる記事をありがとうございます。
当方の電波時計も室内では同期せずただのクォーツ時計となっているため、何か良い方法は無いかと探していたところこちらの記事にたどり着きました。
余っている部品もあり早速作ろうかとおもうのですが、一つ質問させて頂いてもよろしいでしょうか。
こちらで作成しているアンテナですがコイルの巻数はどれ位でしょうか。それか巻数ではなく直径と巻幅、二重巻き出来る分の巻数でしょうか。よろしければ教えて頂けますと助かります。
タイマIC555が余っているので40kHz生成に使おうかとテストしていますが、NANDが2個余っているのでこちらで発振回路を作っても良いですね。色々楽しめそうです。
回路図を見て作るのは慣れていません。
申し訳ありませんが、部品間の接続を部品図で描くことはできますか?
組み立てられた基板の裏面を見せてもらえても役に立ちそうです。