無線タイムサーバ編
時計本体と対をなす、GPS信号を受信するためベランダに設置する別装置を作ります。
これが無線タイムサーバとなります。
GPSから受けた正確な1PPS信号(Pulse Per Second)と時刻を保存し、クライアント要求に応答します。
GPS機器は AE-GYSFDMAXB で、USART 9600 bps で通信します。
ネットワーク機器は ESP-WROOM02 で、USART 115200 bps で通信します。
タイムサーバに使うPICは2ポートのUSARTを備えてなければなりませんので、PIC18F26K22を選択しました。
いままで、2ポートのUSARTを使ったことがなかったので少し戸惑いましたが、なんのことはない、それぞれ専用のレジスタが存在するので各々必要な設定をするだけでした。
具体的にソースコードから引っ張ってきます。
TXSTA、RCSTAのステータスレジスタ、BAUDCONのボーレートコントロールそれぞれに1と2があります。
9600bps 設定は、従来からよく利用している BaudRateGen() マクロで設定。
115200bps 設定は、SPBRGH2、SPBRG2、TXSTA2、BAUDOCON2、を手動設定(107~109行は不要)しています。
受信割り込み許可レジスタも RC1IE と RC2IE の2つ、割り込みフラグも RC1IF と RC2IF の2つが用意されています。
送信用レジスタも TXREG1 と TXREG2 で2つあるので、どちらの機器に送信したいかは、どちらのレジスタに値を入れるかだけの違いになります。
送信完了フラグも TX1IF と TX2IF で2つあるので、上記のように関数を分けておけば簡単に使えます。
受信用レジスタ RCREG
と RCREG2 の2つに分かれているので処理を分けることができます。
インタラプトサービスルーチンでは、それぞれRC1IF、RC2IFのフラグをチェックするようにしておけばよいことになります。
タイムサーバはクライアントからいつ要求がくるのかわかりませんので、常にGPSからの情報を更新して待ち構えます。
とくに無線ネットワークごしなので1PPS情報をリアルタイムで引き渡すことができないので工夫が必要です。
今回は、GPS機器からくる $GPZDA 情報取得完了時刻をPPSからの距離として記録します。具体的には、1PPS信号でタイマ1をリセットしてフリーラン状態にし、$GPZDA終端でタイマ1の値を時刻とともに記録します。
そしてクライアントへの応答時には、上述$GPZDA取得時タイマ1値と応答時取得タイマ1の値を一緒に返します。
クライアント側は、要求してから応答が返るまでの時間と、応答時取得タイマ1値を利用して、PPSのタイミングを計算します。
$GPZDA取得時タイマ1値は上のタイミング計算には必要ないはずですが、調査していくうちにおかしなことに気がつき、まぎれをなくすために追加しました。
以前からNMEAセンテンスと1PPSの関係について曖昧な点がありました。
$GPZDAが指す時刻はどのPPSなのか?という点です。
昔のトラ技には、時刻情報が出た直後の1PPSがその時刻を指す、とありました。
実際にいくつかのGPSモジュールを試してきましたが、どうも1PPS出力の後にその時刻情報が出ているようなのです。
今回サンプルで30個ほど$GPZDA時刻と1PPSからの距離(1PPSからの離れ具合)のセットを取得したところ、1PPSから0.1~0.2秒以内に出てくる$GPZDA群と、0.6~0.7秒辺りに出てくる群になりました。
通信速度が9600bpsであることを考えると、0.1秒間に出力できる文字数は96バイト程度で、$GPZDAが34バイトであることを考えると少し苦しいのではないかということです(他にもたくさんの情報が出ており$GPZDAはほんの一部)。
そして、実際0.1~0.2秒群の情報で時刻合わせをしてしまうと、1秒遅れの時計になってしまいました。
つまりこの群は、2つ前の1PPSの時刻を指していることになるわけです。逆に0.6~0.7秒群は直前の1PPS時刻を指しているようで、こちらを信用して時刻合わせを行うと正確な時計ができあがります。
GPSモジュールの技術資料を見ても1PPSは±10ns(10ナノセカンド:誤差1億分の1秒)の正確さを誇りますが、NMEA情報がどの1PPSを指しているのかは記述がありません。
このあたりをよく調査していかないと、本来の使い方ではないのですが、GPSの1PPSを利用したぴったり時計は作れないということです。
ちなみに、自分の腕時計はCASIOのPROTREKで、かなり正確です。てっきりGPSを拾っているのかと勘違いしていました。
本当は、電波時計でJJY信号を定期的に拾って時刻を合わせていました。電話の117時報より1秒ほど進んでいたので、マニュアルで電波を拾って校正したところGPS時計とぴったり合いました(もちろん見た目)。
完成品。部品は少なく電源IC、ESP-WROOM02、GPSモジュール、I2C液晶ディスプレイ、コンデンサ、通電確認用LED。
裏面。
表面。