[注意書きあり] MacOSでGPSレシーバを使って時刻合わせ
注意書き
この記事の公開後、改めて検証するために屋外の圏外になる場所で動作させたところ、FT8の送信のタイミングでGPSレシーバが停止するという現象が発生しました。現場で、手元にあったパッチンコアをケーブルにはめてみたりしましたが、応急処置では対処できず、現時点でもこの問題は解決していません。
一応、この記事は継続して公開しますが、上記の問題を抱えていることをご了承の上、お読み下さい。
なお、別の方法で時刻合わせする記事も公開していますので、そちら合わせてご参照頂ければと思います。
以下、公開済みの本文
FT8を運用するにあたって、PCの時刻合わせは非常に重要です。家庭内であればWi-Fiで、スマホが圏内であればテザリングを利用して、PCをインターネットに接続してNTPで時刻合わせるすることができます。しかしPOTAやSOTAのような移動運用時は、必ずしも携帯の電波が届くとは限りません。
また、場合によってはスマホを忘れた、スマホのバッテリーが切れた、充電ケーブルを忘れた、などのトラブルも考えられます。
しかし、空が開けていればGPS/GNSSの信号を利用して精度よく時刻合わせすることができます。最近はUSB接続できる安価なGPSレシーバが市販されている他、ハンディ機をGPSレシーバとして動作させることもできます。
前提
FT8を運用する際はPCが必要となりますが、一般的にはWindows PCが利用されており、雑誌やウェブの記事もWindows環境が対象のものがメインです。私はFT8をMacBook Airで運用していますので、MacOSでGPSレシーバを使って時刻合わせする方法を調査しました。
参考になった情報として、KC9WIB局がメーリングリストに投稿したgspdとChronyControlを組み合わせる方法が見つかりました。
ChronyControlはchrony (chronydデーモン・chronycクライアント) のMacOS用フロントエンドのようです。動作確認のために色々と触ってみましたが、個人的には肌に合いませんでした。
やはりCUIがシンプルでベストということで、gpsdと素のchronyを組み合わせることにしました。
gpsd
gpsdはシリアル接続されたGPSレシーバからの信号を処理するソフトウェアです。gpsmonコマンドで受信した信号をモニタリングすることもできます (後述)。オープンソースソフトウェアですので無料で利用できます。
chrony
chronyはNTPに対応した時刻同期サービスです。NTPサーバやgpsdから受信した信号を処理して時刻同期するchronydデーモンと、これと連携・制御するchronycクライアントから構成されます。chronyもgpsdと同じくオープンソースソフトウェアです。
注意点
以下、MacOSのターミナルでコマンドを実行します。プロンプトは%で表記しています。また、可読性を優先して、コマンドを実行した行の下に空行を入れるなど、適宜編集しています。
また、sudoコマンド実行時にパスワードを要求される場合がありますが、このプロンプトは省略しています。
ソフトウェアの設定
WSJT-X
FT8用のソフトとしてWSJT-Xをインストールしている場合、インストーラのReadMe.txtに従ってplistファイルを/Library/LaunchDaemonsにsudo cpしたかと思いますが、このファイルに変更を加えます。
具体的には、shmmniとshmsegの値を追加します。
% sudo vi /Library/LaunchDaemons/com.wsjtx.sysctl.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.wsjtx.sysctl</string>
<key>Program</key>
<string>/usr/sbin/sysctl</string>
<key>ProgramArguments</key>
<array>
<string>/usr/sbin/sysctl</string>
<string>kern.sysv.shmmax=52428800</string>
<string>kern.sysv.shmall=25600</string>
<string>kern.sysv.shmmni=128</string>
<string>kern.sysv.shmseg=32</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
保存したらMacを再起動しましょう。記事によってはlaunchctlコマンドで再読み込みできるとありますが、私の環境ではエラーになりました。
再起動後、設定が反映されているか確認します。
% sysctl -a | grep kern.sysv
kern.sysv.shmmax: 52428800
kern.sysv.shmmin: 1
kern.sysv.shmmni: 128
kern.sysv.shmseg: 32
kern.sysv.shmall: 25600
plistで設定した値が表示されていればOKです。
HomeBrew
HomeBrewはMacOSで利用できるパッケージ管理システムです。MacOS上で仕事をしているプログラマにはお馴染だと思います。
ターミナルに以下のコマンドをコピペすればインストールできます。最新のインストール方法は上記ウェブサイトを参照して下さい。
% /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
gpsd
まずはHomeBrewが提供するbrewコマンドで、gpsdをインストールします。
% brew update
% brew install gpsd
USBポートにGPSレシーバを接続すると、MacOSからはUSBシリアルデバイスとして認識されます。通常は/dev/tty.usbmodem* というファイル名になります。以下に、USBハブを介してGPSレシーバを接続した時の例を示します。
% ls /dev/tty.usbmodem*
/dev/tty.usbmodem11101
このデバイスファイルを引数に、gpsdを起動します。ここではPIDファイルも作成しています。
% sudo gpsd -n --pidfile /var/run/gpsd.pid /dev/tty.usbmodem11101
明示的にオプションを渡さない限り、gpsdはバックグラウンドで実行されますので、特に表示されずプロンプトが戻れば成功です。念のために信号を受信しているかgpsmonコマンドで確認してみます。
% gpsmon
このスクショのように、リアルタイムに受信データが表示されていればOKです。gpsmonを終了するには、キーボードからq→Enterと順に入力して下さい。
chrony
次にchronyをインストールし、設定ファイルを作成します。以下に設定ファイルの例を示します。詳細はchronyのマニュアルを当たって下さい。ポイントは、下記の3点です。
bindcmdaddressはchronyc (後述) から参照されるので、ネットワークアドレスではなくUNIXドメインソケットを指定
refclockでGPSから時刻データを取得するよう設定
他PCから参照されるNTPサーバとしては動作させない
% brew install chrony
% sudo vi /etc/chrony.conf
pool pool.ntp.org iburst
pidfile /var/run/chrony/chronyd.pid
driftfile /var/db/chrony/chrony.drift
bindcmdaddress /opt/homebrew/var/run/chrony/chronyd.sock
log tracking measurements statistics
logdir /var/log/chrony
maxupdateskew 100.0
dumponexit
dumpdir /var/db/chrony
rtcsync
# gpsd
refclock SHM 0 refid GPS
makestep 1 3
設定ファイルを作成したら、chronydを起動します。
% sudo chronyd
gpsdと同じくchronydもバックグラウンドで実行されますので、エラーメッセージが表示されなければOKです。Macがインターネットに接続されていれば、NTPサーバに接続して時刻合わせが自動で行われます。
この起動時に/var/run/chronyディレクトリがないというエラーが表示される場合は、このディレクトリを作成し、chmodで権限を設定してから再度実行します。
% sudo mkdir /var/run/chrony
% sudo chown root:wheel /var/run/chrony
% sudo chronyd
chronydが動作しているか、chronycコマンドで確認してみましょう。引数にtrackingを渡して実行します。以下に実行例を示します。
% sudo chronyc tracking
Reference ID : 85F3EEF3 (ntp-a2.nict.go.jp)
Stratum : 2
Ref time (UTC) : Sat May 25 05:34:51 2024
System time : 0.000415727 seconds slow of NTP time
Last offset : -0.000235692 seconds
RMS offset : 0.001010206 seconds
Frequency : 0.191 ppm slow
Residual freq : +0.531 ppm
Skew : 8.455 ppm
Root delay : 0.019880097 seconds
Root dispersion : 0.000715398 seconds
Update interval : 64.2 seconds
Leap status : Normal
NICTのNTPサーバに接続して同期していることを確認できました。GPSレシーバからの信号が認識されているか確認するには、sourcesを引数に渡して実行します。
% sudo chronyc sources
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
#x GPS 0 4 377 10 -927ms[ -927ms] +/- 200ms
^- x.ns.gin.ntt.net 2 6 377 20 -3512us[-3504us] +/- 83ms
^- time.cloudflare.com 3 6 377 20 +1662us[+1670us] +/- 67ms
^* ntp-a2.nict.go.jp 1 6 377 20 +133us[ +141us] +/- 10ms
^- time.cloudflare.com 3 6 377 21 +272us[ +280us] +/- 69ms
GPSの行があることが確認できます。
動作確認
以下のような手順で、GPSで時刻合わせができることを確認します。
Wi-Fi切断
Wi-Fiをoffにしてネットワーク接続を切断し、NTPで時刻同期できないようにします。
chronyc起動
引数を渡さずにchronycを起動するとchronycのシェルが起動し、インタラクティブにchronydを操作することができるようになります。
% sudo chronyc
chrony version 4.5
Copyright (C) 1997-2003, 2007, 2009-2023 Richard P. Curnow and others
chrony comes with ABSOLUTELY NO WARRANTY. This is free software, and
you are welcome to redistribute it under certain conditions. See the
GNU General Public License version 2 for details.
chronyc>
onofflineコマンド
chronydにオフラインになったことを通知します。正常に実行された場合は200 OKが返されます。エラーが発生した場合、200 OK以外が返されます。以降のコマンドも同様です。
chronyc> onoffline
200 OK
reselectコマンド
chronydにソースを再選択させますが、実行しなくてもよいかも知れません (要検証) 。
chronyc> reselect
200 OK
trackingコマンド
信号ソースとしてGPSが選択されたことを確認します。これには少し時間が掛かることがあり、しばらくNTPサーバの情報が表示されることがあります。そのような場合は1〜2分待ってから再度trackingを実行してみましょう。
chronyc> tracking
Reference ID : 47505300 (GPS)
Stratum : 1
Ref time (UTC) : Sat May 25 06:14:19 2024
System time : 0.902774870 seconds slow of NTP time
Last offset : +0.004733979 seconds
RMS offset : 0.277205676 seconds
Frequency : 0.345 ppm slow
Residual freq : +158.457 ppm
Skew : 1.046 ppm
Root delay : 0.200000003 seconds
Root dispersion : 0.104125388 seconds
Update interval : 16.0 seconds
Leap status : Normal
makestepコマンド
この時点で時刻同期がなされるようになりますが、通常、chronyは1秒の時刻のズレを12秒掛けて修正します。1分のズレの修正には12分掛かります。
強制的に時刻を同期させたい場合は、makestepコマンドを実行します。
chronyc> makestep
200 OK
これで時刻が同期 (修正) されたことを確認できると思います。
Wi-Fi再接続
GPS信号で時刻が同期されることを確認したら、Wi-Fiに接続し直します。オンラインになったことをonofflineコマンドでchronydに通知しておきましょう。
chronyc> onoffline
200 OK
quitコマンド
暫く放置しておけば、NTPから時刻同期するようになります。quitコマンドでchronycを終了しましょう。
chronyc> quit
%
オフセット調整
この状態でも一応使えるには使えますが、処理された後のGPS信号には多少のズレ (オフセット) が発生しています。これを補正しましょう。
makestepコマンド
オンラインになっていることを確認したら、chronyc makestepコマンドで時刻を合わせます。この時、オフラインになっていてNTPサーバに接続できていないと以下の操作の意味がなくなりますので注意が必要です。
% sudo chronyc makestep
200 OK
gpsmon
gpsmonを起動し、画面下寄りのNAV_DOPにあるTOFFの値を確認します。gpsdを起動してしばらく待ち、この値が落ちついた頃の値を用いましょう。gpsmonのスクショを再掲します。
この例では、およそ60m秒強のオフセットが生じていることを確認できます。
sourcestatsコマンド
chronyc sourcestatsコマンドで、このオフセット分だけGPSの信号が遅れていることを確認します。
% sudo chronyc sourcestats
Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev
==============================================================================
GPS 9 5 124 +39.724 21.687 +64ms 503us
time.cloudflare.com 8 4 265 -7.503 46.506 -744us 1795us
time.cloudflare.com 8 5 264 -9.226 33.019 -1312us 1197us
ntp-b2.nict.go.jp 8 5 266 -2.305 14.751 -12us 406us
x.ns.gin.ntt.net 8 7 265 +0.697 13.443 +1107us 759us
TOFFの値とほぼ同じ程度の値が、GPS行のOffset値として表示されています。
sourcesコマンド
ついでに時刻のソースを一覧するchronyc sourcesコマンドを実行してみましょう。
% sudo chronyc sources
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
#x GPS 0 4 377 14 +65ms[ +65ms] +/- 533us
^- time.cloudflare.com 3 6 377 46 -5983us[-6028us] +/- 73ms
^- time.cloudflare.com 3 6 377 46 +1819us[+1774us] +/- 68ms
^* ntp-b2.nict.go.jp 1 6 377 44 +275us[ +227us] +/- 8318us
^- x.ns.gin.ntt.net 2 6 377 45 +1629us[+1582us] +/- 87ms
GPS行を見ると、行頭が #x となっています。2文字目の x はデータにエラーがあることを示唆しています。おそらく時刻のソースとしてはオフセットが大きすぎるということでしょう。
/etc/chrony.conf編集
chronyの設定ファイルで、GPS信号のオフセットを指定できます。ファイル末尾のGPSを記述しているrefclockにオプション offset を追加します。
% sudo vi /etc/chrony.conf
(上は省略)
# gpsd
refclock SHM 0 refid GPS offset 0.06
makestep 1 3
chronyd再起動
設定ファイルの変更を保存したら、chronydを再起動します。
% sudo chronyc shutdown
% sudo chronyd
sourcestatsコマンド
しばらく待ってから、chronyc sourcestatsコマンドでオフセットがどうなったか確認します。
% chronyc sourcestats
Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev
==============================================================================
GPS 11 7 157 +0.367 7.257 +443ns 319us
time.cloudflare.com 7 5 200 +8.446 87.417 -13ms 1353us
time.cloudflare.com 7 4 201 +26.870 132.938 -8112us 2496us
x.ns.gin.ntt.net 7 5 200 +4.347 13.934 -13ms 255us
ntp-b2.nict.go.jp 7 4 200 +12.518 51.985 -11ms 1328us
60ミリ秒近くあったオフセットが、400ナノ秒まで小さくなりました。
サービス終了
chronyd
基本的にchronydは起動しっぱなしで問題ありません。もしプロセスを終了したい場合は、chrony.confで指定しているpidfileを利用します。
% sudo kill `cat /var/run/chronyd.pid`
あるいはchronycのshutdownコマンドで終了させることもできます。
% sudo chronyc shutdown
gpsd
GPSレシーバをUSBポートから外すとデバイスファイルは削除され、当然、gpsdは信号を受信できなくなります。再度同じUSBポートにGPSレシーバを接続し、同じデバイスファイルが作成されても、以前のプロセスからはGPS信号を受信できないようです。また、以前のプロセスが残ったままでは、再度gpsdを起動してもGPS信号を受信できないようです。
つまり、GPSレシーバを外した後は面倒ですがgpsdを終了する必要があります。起動時に--pidfileオプションで指定したPIDファイルを利用します。
% sudo kill `cat /var/run/gpsd.pid`
運用手順
ここまで長々と書いてきましたが、これでようやく運用できるようになりました。通常は以下のような流れになるかと思います。
GPSレシーバを接続
既存gpsdプロセスがあればkill
gpsd起動
既存chronydプロセスがなければchronyd起動
1〜2分待つ (その間に機器のセットアップ)
FT8運用
gpsdプロセスをkill
GPSレシーバを外す
TODO
デバイス認識・自動起動/終了
Linuxのudevのように、GPSレシーバが接続/取り外しされたことを認識して自動でgpsdを起動/終了するようにしたいのですが、その方法が見つかていません。調査を継続します。
また、chronydはMacOSの起動と同時に起動してもよさそうです。通常であればbrew services startで登録できそうなのですが、brew services listにchronydがないので、他の方法が必要です。
スクリプト化
PIDファイルがあった場合は起動前にkillする等、自動起動の前段階としてこのあたりをうまく処理してくれるようなスクリプトがあると便利そうです。
GPSレシーバ
今回は以下のGPSレシーバで動作を確認しました。
市販品
Amazonで購入可能な、安価なUSB接続タイプのGPSレシーバです。そのままMacに接続すればUSBシリアルデバイスとして認識されます。
レシーバはUSB給電で動作しますので、それ自体のバッテリー切れを心配しなくてよいのはメリットです。車載での利用が想定されているのか分かりませんが、ケーブルがとても長いので、もしかしたらパッチンコアを装着した方がよさそうです。
TH-D75
KENWOODの最新ハンディ機であるTH-D75はGPSレシーバとして動作させることができます。PCとUSB-Cケーブルで接続すると、こちらもUSBシリアルデバイスとして認識されます。
設定方法は MENU -> GPS -> 基本設定 -> 動作モード (403) で GPSレシーバーを選択し、再起動します。しばらく待つと受信したGPS信号を画面上に表示します。
こちらはGPSレシーバを追加で持ち歩かなくて済むのがメリットです。GPSレシーバーモードにするとトランシーバとしては動作しなくなりますので、アマチュアバンドのモニタリングなどはできなくなります。また、当然のことながらハンディ機のバッテリー切れに注意が必要です。