Rock Pi SとChronyでPPS付きNTPサーバを作る

Rock Pi SとChronyでPPS付きNTPサーバを作る

今回は、Rock Pi SにGPSモジュールを接続し、NTPd(またはNTPsec)ではなくChronyを使ってPPS付きのNTPサーバを作成します。最近のLinuxディストリビューションではChronyが標準搭載されることが増えており、ChronyはNTPd(やNTPsec)よりも積極的に補正を行い、精度が高いとされています。以前はNTPd(やNTPsec)の統計ログとChronyの形式が異なり不便なため、「がとらぼ」の人はChronyを避けていましたが、今回はLAN用のNTPサーバで統計ログを分析する予定はないのでChronyを選ぶことにしました。

Chronyについては過去に3回ほど取り上げており、今回も基本的には同じ手順です。
Rock Pi SでのUARTとPPSの利用に関しては、他のシングルボードコンピュータでも参考になる情報があるかと思います。
先月、NanoPi NEO3をNTPサーバにする際に購入した屋外用GPSアンテナです。このアンテナはSMA端子付きでケーブルが3mです。取り付けには直径12mm以上の穴が開いたL型アングルに固定するか、内径11mmのパイプにねじ込むことができます。
今回新しく購入した屋外用GPSアンテナは、コンパクトで高さが抑えられています。SMA端子付きでケーブルが3mです。取り付けには直径11mm以上の穴が開いたL型アングルに固定するか、内径10mmのパイプにねじ込むことができます。ネジの規格にご注意ください。
このGPSモジュールはu-bloxのGPS受信チップと互換性があり、基板上にはパッチアンテナが付いておらず、SMAとIPEXのアンテナ端子が装備されています。少し怪しい製品ではありますが、過去に「新しい中華GPSモジュールとChronyで作るNTPサーバ (前編)」で紹介したGPSモジュールと同じもので、安価ながら意外と良好な性能を発揮しています。

Rock Pi SとChronyでPPS付きNTPサーバを作る 2
今回のアンテナは、自動車用のGPSアンテナよりも一回り大きい、比較的背の低いモデルです。

Rock Pi SとChronyでPPS付きNTPサーバを作る 3
アンテナの下部にはゴムカバーがありますが、このカバーは水が溜まりやすいため、使用しない方が良いでしょう。白い円盤は両面テープの保護シートです。黒いカバーを貼り付けることもできますが、10mm以上の穴があるプレートに固定することも可能です。さらに、内径10mmのパイプにねじ込んで固定することもできます。ただし、ケーブル穴の防水状態が不明なため、ゴム系接着剤を穴に流し込み固まった後にアンテナを設置するのが安全です。

Rock Pi SとChronyでPPS付きNTPサーバを作る 4
購入したGPSチップは左側の「ATGM332D」と書かれたものです。右側は「u-blox NEO-M8N」とされていますが、左側のGPSとほぼ同じ価格の1000円前後の安価な製品であるため、本物ではない可能性が高いです。シールも汚れており、信頼性に疑問があります。モジュールの基板自体は似ていますが、搭載されている部品は微妙に異なります。

右側の「NEO-M8N」と表示されたチップは、出力されるNMEAメッセージに異常があり、u-blox GPSチップ用のコマンドをシリアル通信で送信しても機能しません。もし本当にu-bloxチップであれば、u-blox用のPCアプリなどで制御できる可能性がありますが、まだ試していません。

Rock Pi SとGPSモジュールの接続

Rock Pi SとChronyでPPS付きNTPサーバを作る 1
Rock Pi SとGPSモジュールはGPIOピンを利用して接続します。

  • ピン番号17: GPSモジュールVCCに接続します
  • ピン番号20: GPSモジュールGNDに接続します
  • ピン番号23: GPSモジュールTX(送信)に接続します (RXとTXを接続)
  • ピン番号24: GPSモジュールRX(受信)に接続します (RXとTXを接続)
  • ピン番号13: GPSモジュールPPSに接続します

一般的なシングルボードコンピュータでは、右上のUART(このボードではUART0)を使用してシリアル通信を行います。しかし、Rock Pi SのUART0はデバッグ専用UARTであり、このピンにGPSモジュールなどを接続するとOSが起動しません。OSが起動した後にUART0に接続すれば通常のUARTとして使用できますが、これは不便ですし、瞬間的な停電などで再起動がかかると、OSが起動できずにダウンタイムが長引くことになります。そのため、素直にUART1(右下)などを使用するのが良いでしょう。

ArmbianのOSイメージ

8月中旬に最新のArmbianソースを使って、Rock Pi S用のDebian Bookworm OSイメージをビルドしました。PPSやタイマー周りは、これまで通りNTPサーバ向けの設定でビルドしています。OSイメージは以下で共有します。

置き場所(Google Drive):
Armbian-unofficial_24.8.0-trunk_Rockpi-s_bookworm_current_6.6.46.zip

PPSデバイスの有効化

Armbianでは、デバイスツリーによるデバイス周りの設定の追加や変更が比較的簡単に行えます。今回は、デバイスツリーソースでRock Pi SのGPIO0_C0 GPIO13番ピンをGPIO-PPSとして利用する設定を作成しました。

# vim ~/pps-overlay.dts (新規作成)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
/dts-v1/;
/plugin/;

/ {
    compatible = "rockchip,rk3308";
    fragment@0 {
        target-path = "/";
        __overlay__ {
            pps: pps@0 {
                compatible = "pps-gpio";
                gpios = <&gpio0 16 0>;
                assert_falling_edge;
            };
        };
    };
};

重要なのは11行目です。今回はピン番号13を使用しますが、これはGPIO0のGPIO番号16番に対応しているため、このように記述します。もしピン番号15を使用する場合は、GPIO0のGPIO番号17番に対応するので、&gpio0 17 0のように記述します。対応表がないと理解しづらい部分です。

最近のArmbianには、デバイスツリーのソースを変換・配置・設定を自動で行うツールが含まれています。

# armbian-add-overlay ~/pps-overlay.dts

これにより、変換されたpps-overlay.dtboファイルがboot/overlay-userディレクトリに配置され、/boot/armbianEnv.txtに次の1行が追加されます。

user_overlays=pps-overlay

システムを再起動することでGPIO13番ピンに紐付いた/dev/pps0が生成されます。

# dmesg | grep pps
[    0.254397] pps_core: LinuxPPS API ver. 1 registered
[    0.254406] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[    9.320594] pps pps0: new PPS source pps@0.-1
[    9.320742] pps pps0: Registered IRQ 44 as PPS source
[   23.940029] pps_ldisc: PPS line discipline registered


# lsmod
Module                  Size  Used by
pps_ldisc              16384  2
sunrpc                483328  1
8723ds               1327104  0
cfg80211              802816  1 8723ds
hci_uart              135168  0
btqca                  20480  1 hci_uart
btrtl                  28672  1 hci_uart
btintel                40960  1 hci_uart
btbcm                  20480  1 hci_uart
pps_gpio               12288  1
bluetooth             663552  6 btrtl,btqca,btintel,hci_uart,btbcm
rfkill                 24576  4 bluetooth,cfg80211
rockchip_rng           16384  0
rng_core               16384  1 rockchip_rng
cpufreq_dt             16384  0
lz4hc                  12288  0
lz4                    12288  0
zram                   32768  3
binfmt_misc            20480  1
dm_mod                126976  0
ip_tables              28672  0
x_tables               36864  1 ip_tables
autofs4                40960  2
realtek                32768  1
dwmac_rk               28672  0
stmmac_platform        20480  1 dwmac_rk
stmmac                233472  3 stmmac_platform,dwmac_rk
pcs_xpcs               20480  1 stmmac

lsmod コマンドを使って、pps_gpio モジュールが表示されることを確認します。なお、上記の lsmod の結果は、NTPサーバーの動作に不要なカーネルモジュールを /etc/modprobe.d/blacklist-rockpi-s.conf でブラックリストに登録済みの状態です。ブラックリストに登録していない場合は、表示されるモジュールがこれよりも多くなります。

# apt install pps-tools
# ppstest /dev/pps0
trying PPS source "/dev/pps0"
found PPS source "/dev/pps0"
ok, found 1 source(s), now start fetching data...
source 0 - assert 1724375360.627367312, sequence: 120015 - clear  0.000000000, sequence: 0
source 0 - assert 1724375361.710659761, sequence: 120016 - clear  0.000000000, sequence: 0
source 0 - assert 1724375362.794035625, sequence: 120017 - clear  0.000000000, sequence: 0
source 0 - assert 1724375363.877368518, sequence: 120018 - clear  0.000000000, sequence: 0

次に、pps-tools をインストールし、/dev/pps0 をデバイスとして指定してテストを実行します。1秒ごとに1行ずつ表示され、問題がないことを確認したら、[Ctrl]+[C] で終了します。

シリアルポートUART1の有効化と設定

Rock Pi Sでは、UART0がデバッグUARTとして設定されており、UART0にGPSモジュールなどを接続した状態で電源を入れるかシステムを再起動すると、OSが起動しないことがあります。Armbianでは、UART0が ttyS0 として有効化されているのですが、このポートを使用するとOSが起動しないため、UART1(それ以降)をGPSモジュールとの通信用に使用するのが良いでしょう。今回はUART1を使用することにしますが、Rock Pi S用Armbian BookWormではUART1(ttyS1)が無効になっているため、これを有効化する必要があります。(次)

# vim ~/uart1-overlay.dts (新規作成)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
/dts-v1/;
/ {
    compatible = "rockchip,rk3308-uart\0snps,dw-apb-uart";
    fragment@0 {
        target-path = "/serial@ff0b0000";
        __overlay__ {
            status = "okay";
        };
    };
};
# armbian-add-overlay ~/uart1-overlay.dts

これにより、変換されたuart1-overlay.dtboファイルがboot/overlay-userディレクトリ下に配置され、/boot/armbianEnv.txtのuser_overlays行が次のようになります。

user_overlays=pps-overlay uart1-overlay

システムを再起動することでUART1の/dev/ttyS1が有効化されます。

# stty -F /dev/ttyS1 9600  ←RockPi Sのシリアル速度をGPSモジュールのシリアル速度に合わせる
# cat /dev/ttyS1

NMEAメッセージが表示され続けることを確認できれば成功です。[Ctrl]+[C]で終了します。

/dev/pps0と/dev/ttyS1を後述のgpsdとchronyが利用できるようにします。

# vim /etc/udev/rules.d/10-gps.rules (新規ファイル作成)
1
2
KERNEL=="ttyS1",MODE="0666"
KERNEL=="pps0",MODE="0666"
この設定はシステムを再起動しないと適用されません。
手動で即時有効にするのは
# chmod 0666 /dev/ttyS1
# chmod 0666 /dev/pps0

シリアルポートのgettyを停止・無効化します。

# systemctl stop serial-getty@ttyS0.service
# systemctl disable serial-getty@ttyS0.service

# systemctl stop serial-getty@ttyS1.service
# systemctl disable serial-getty@ttyS1.service

# systemctl stop serial-getty@ttyS2.service
# systemctl disable serial-getty@ttyS2.service

# systemctl stop serial-getty@ttyS3.service
# systemctl disable serial-getty@ttyS3.service

# systemctl stop serial-getty@ttyS4.service
# systemctl disable serial-getty@ttyS4.service

# systemctl stop serial-getty@ttyS5.service
# systemctl disable serial-getty@ttyS5.service

# systemctl stop serial-getty@ttyS6.service
# systemctl disable serial-getty@ttyS6.service

# systemctl stop serial-getty@ttyS7.service
# systemctl disable serial-getty@ttyS7.service
実行は、GPSモジュールと通信するttyS1だけでも良いかもしれません。

gpsdのインストールと設定

chrony はGPSモジュールから送信されるNMEAメッセージを直接読み取ることができないため、gpsd を使って受信し、メモリ共有で chrony に日時を渡すようにします。そのために、gpsd と gpsd-clients をインストールします。

# apt update
# apt install gpsd gpsd-clients
gpsdの設定ファイルは/etc/default/gpsdです。
1
2
3
4
START_DAEMON="true"
USBAUTO="false"
DEVICES="/dev/ttyS1"
GPSD_OPTIONS="-n -s 9600"
gpsdを再起動します。
$ sudo systemctl restart gpsd.socket
gpsdが正常に動作し、GPSモジュールから衛星データを受信しているか確認するには、 gpsmoncgps -s コマンドを実行します。表示される日時や座標が正しければ、正常に動作しています。

chronyの設定

最近のLinuxでは、NTPの標準としてChronyが採用されることが増えています。Chronyの設定ファイルは通常 /etc/chrony/chrony.conf にあります。

 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
# NTP Servers (mfeed)
server ntp1.jst.mfeed.ad.jp
server ntp2.jst.mfeed.ad.jp
server ntp3.jst.mfeed.ad.jp
server ntp1.v6.mfeed.ad.jp
server ntp2.v6.mfeed.ad.jp
server ntp3.v6.mfeed.ad.jp

# Access loopback address
allow 127.0.0.1
allow ::1

# Allow access from your IPv4,IPv6 networks 
allow 192.168.0.0/24
allow 2001:xxxx:xxxx:xxxx::/64

# Allow mfeed servers but restrict their actions
allow 210.173.160.27
allow 210.173.160.57
allow 210.173.160.87
allow 2001:3a0:0:2001::27:123
allow 2001:3a0:0:2005::57:123
allow 2001:3a0:0:2006::87:123

# NMEA GPS 
refclock SHM 0 refid NMEA 

# PPS (Pulse Per Second)
refclock PPS /dev/pps0 refid PPS lock NMEA
chronyを再起動します。
$ sudo systemctl restart chrony
PPSを使う場合は、最初の時刻合わせに時間がかかるためchrony 起動後しばらく待ちます。
$ chronyc sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
#x NMEA                          0   4   377    22   +413ms[ +413ms] +/- 2700us
#* PPS                           0   4   370    72  +9308ns[  +13us] +/- 3294ns
^- ntp1.jst.mfeed.ad.jp          2  10   377   115  -1347us[-1332us] +/-   61ms
^- ntp2.jst.mfeed.ad.jp          2  10   377   788   -193us[ -246us] +/-   52ms
^- ntp3.jst.mfeed.ad.jp          2  10   377    53   -385us[ -385us] +/-   61ms
^- ntp1.v6.mfeed.ad.jp           2  10   377   498  -1075us[-1068us] +/-   55ms
^- ntp2.v6.mfeed.ad.jp           2  10   377   655  -1998us[-2029us] +/-   54ms
^- ntp3.v6.mfeed.ad.jp           2  10   377   785  -1297us[-1352us] +/-   75ms
$ chronyc tracking
Reference ID    : 50505300 (PPS)
Stratum         : 1
Ref time (UTC)  : Fri Aug 23 14:09:03 2024
System time     : 38248.757812500 seconds slow of NTP time
Last offset     : +0.000002095 seconds
RMS offset      : 0.000305083 seconds
Frequency       : 26.998 ppm fast
Residual freq   : +0.008 ppm
Skew            : 0.082 ppm
Root delay      : 0.000000001 seconds
Root dispersion : 0.000023679 seconds
Update interval : 16.0 seconds
Leap status     : Normal

このような表示になります。
GPSから時刻を取得しているため、最上位のStratum 1として表示されます。Stratumの数字が大きくなるほど、大本の時刻ソースからの間にホストが増えることを示します。これは、伝言ゲームのように、間に入る人が増えるほど伝言が不正確になるのと似ています。
PPS (パルスパーセカンド)での秒合わせにより、誤差はナノ秒単位に迫ります。

時刻の正確さが求められる環境では、GPSのPPS信号を利用して時刻合わせを行うNTPサーバがLAN内に1台は必須です。NTPサーバは、ネットワーク内の全てのデバイスが同じ正確な時刻を持つようにするための重要な役割を果たします。GPSのPPS信号は、高精度な時刻合わせを可能にし、ネットワーク全体の時刻のずれを最小限に抑えることができます。この記事のようにシングルボードコンピュータを使用すれば、GPSモジュールとPPS機能を搭載したNTPサーバのセットが、6〜7千円程度で手に入ります。この価格で一式を揃えることができるため、コストパフォーマンスに優れており、多くの企業や技術者にとって非常におすすめです。高精度な時刻同期が求められるシステムには、このようなNTPサーバの導入を検討してみる価値があります。

関連記事:

記事へのコメント

いただいたコメントは管理人が確認した後に記事の 下部(ここ)に公開されます。
コメントスパム対策: 2022年4月以降、コメント内にリンクURLを含めると自動破棄されます。(記録されません)