いろんな人がすでに同じ内容で書いてたりするので今更なんですが、とりあえずLAN内に独立したNTPサーバが必要な場合に、電子工作とかなしにお手軽に作る方法を記します。
なお今回の構成ではPPSは扱えないのでそれなりの精度しか出ませんが、よほど受信環境が悪くない限りは、お手軽構成としてはそれなりの精度で稼働できると思います(多分)。
必要なもの
おそらく1万円出せばなんとかなる感じかと。
- Raspberry Pi 3 Model B (本体)
- GlobalSat SiRFstarIV BU-353S4 (USB接続GPSレシーバ)
- microSDカード (とりあえず8GBぐらいの)
- Raspbian Stretch Lite (本日時点「November 2018」、なるべく新しいものを使用)
事前準備
raspi-configとかで初期セットアップとアップデートは済ませておきます。
gpsdのインストール
gpsdとgpsd-clientsをインストールします。
pi@aeon:~ $ sudo apt update ヒット:1 http://raspbian.raspberrypi.org/raspbian stretch InRelease ヒット:2 http://archive.raspberrypi.org/debian stretch InRelease パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 パッケージはすべて最新です。 pi@aeon:~ $ pi@aeon:~ $ sudo apt install gpsd gpsd-clients パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 以下の追加パッケージがインストールされます: fontconfig fontconfig-config fonts-dejavu-core gnome-icon-theme gtk-update-icon-cache hicolor-icon-theme libatk1.0-0 libatk1.0-data libavahi-client3 libblas-common libblas3 libbluetooth3 libcairo2 libcroco3 libcups2 libdatrie1 libfontconfig1 libgail-common libgail18 libgdk-pixbuf2.0-0 libgdk-pixbuf2.0-common libgfortran3 libgps22 libgraphite2-3 libgtk2.0-0 libgtk2.0-bin libgtk2.0-common libharfbuzz0b libjbig0 liblapack3 libpango-1.0-0 libpangocairo-1.0-0 libpangoft2-1.0-0 libpixman-1-0 librsvg2-2 librsvg2-common libthai-data libthai0 libtiff5 libxcb-render0 libxcb-shm0 libxcomposite1 libxcursor1 libxdamage1 libxfixes3 libxi6 libxinerama1 libxrandr2 libxrender1 python-cairo python-gobject-2 python-gps python-gtk2 python-numpy 提案パッケージ: cups-common gvfs librsvg2-bin python-gobject-2-dbg python-gtk2-doc gfortran python-dev python-nose python-numpy-dbg python-numpy-doc 以下のパッケージが新たにインストールされます: fontconfig fontconfig-config fonts-dejavu-core gnome-icon-theme gpsd gpsd-clients gtk-update-icon-cache hicolor-icon-theme libatk1.0-0 libatk1.0-data libavahi-client3 libblas-common libblas3 libbluetooth3 libcairo2 libcroco3 libcups2 libdatrie1 libfontconfig1 libgail-common libgail18 libgdk-pixbuf2.0-0 libgdk-pixbuf2.0-common libgfortran3 libgps22 libgraphite2-3 libgtk2.0-0 libgtk2.0-bin libgtk2.0-common libharfbuzz0b libjbig0 liblapack3 libpango-1.0-0 libpangocairo-1.0-0 libpangoft2-1.0-0 libpixman-1-0 librsvg2-2 librsvg2-common libthai-data libthai0 libtiff5 libxcb-render0 libxcb-shm0 libxcomposite1 libxcursor1 libxdamage1 libxfixes3 libxi6 libxinerama1 libxrandr2 libxrender1 python-cairo python-gobject-2 python-gps python-gtk2 python-numpy アップグレード: 0 個、新規インストール: 56 個、削除: 0 個、保留: 0 個。 26.7 MB のアーカイブを取得する必要があります。 この操作後に追加で 81.9 MB のディスク容量が消費されます。 <中略> pi@aeon:~ $
GlobalSat SiRFstarIV BU-353S4を繋ぐ
GlobalSat SiRFasterIV BU-353S4をRaspberry PiのUSBポートに挿して、下記コマンドで確認します。
“lsusb”コマンドを実行
pi@aeon:~ $ lsusb Bus 001 Device 005: ID 046d:c52b Logitech, Inc. Unifying Receiver Bus 001 Device 004: ID 0781:5583 SanDisk Corp. Bus 001 Device 006: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. SMC9514 Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub pi@aeon:~ $ ※Prolific Technology, Inc. LP2303 Serial Portが認識されていればOK
“ls -al /dev/ttyUSB*” コマンドを実行
pi@aeon:~ $ ls -al /dev/ttyUSB* crw-rw---- 1 root dialout 188, 0 1月 28 20:15 /dev/ttyUSB0 pi@aeon:~ $ ※他に何も繋いでなければ「/dev/ttyUSB0」が表示される
gpsdを設定する
gpsdの設定を行います。
/etc/default/gpsd の設定
pi@aeon:~ $ sudo cp -a /etc/default/gpsd{,.orig} pi@aeon:~ $ pi@aeon:~ $ sudo vi /etc/default/gpsd ## 変更内容 ## --- /etc/default/gpsd.orig 2016-11-05 07:35:14.000000000 +0900 +++ /etc/default/gpsd 2019-01-28 20:17:04.096135683 +0900 @@ -8,7 +8,7 @@ # Devices gpsd should collect to at boot time. # They need to be read/writeable, either by user gpsd or the group dialout. -DEVICES="" +DEVICES="/dev/ttyUSB0" # Other options you want to pass to gpsd -GPSD_OPTIONS="" +GPSD_OPTIONS="-N -F /var/run/gpsd.sock -b -n" pi@aeon:~ $ ※"-N -b -n"あたりが肝
/etc/systemd/system/gpsd.service の設定
pi@aeon:~ $ sudo cp -a /lib/systemd/system/gpsd.service /etc/systemd/system/ pi@aeon:~ $ pi@aeon:~ $ sudo vi /etc/systemd/system/gpsd.service ## 変更内容 ## /etc/systemd/system/gpsd.service --- /lib/systemd/system/gpsd.service 2016-11-05 07:35:14.000000000 +0900 +++ /etc/systemd/system/gpsd.service 2019-01-28 20:20:02.035553856 +0900 @@ -9,4 +9,5 @@ ExecStart=/usr/sbin/gpsd -N $GPSD_OPTIONS $DEVICES [Install] +WantedBy=multi-user.target Also=gpsd.socket pi@aeon:~ $ ※WantedByの部分が肝
gpsdの自動起動再登録、再起動
“sudo systemctl daemon-reload”でもよい気がしますが、とりあえず無効→有効にします。
gpsdの自動起動を一旦無効にする
pi@aeon:~ $ sudo systemctl disable gpsd Synchronizing state of gpsd.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install disable gpsd Removed /etc/systemd/system/sockets.target.wants/gpsd.socket. pi@aeon:~ $
gpsdの自動起動を再度有効にする
pi@aeon:~ $ sudo systemctl enable gpsd Synchronizing state of gpsd.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable gpsd Created symlink /etc/systemd/system/sockets.target.wants/gpsd.socket → /lib/systemd/system/gpsd.socket. pi@aeon:~ $
gpsdを再起動する
インストール後すでに起動しているので、”start” ではなく “restart” します。
pi@aeon:~ $ sudo systemctl restart gpsd pi@aeon:~ $ pi@aeon:~ $ sudo systemctl -l status gpsd ● gpsd.service - GPS (Global Positioning System) Daemon Loaded: loaded (/etc/systemd/system/gpsd.service; disabled; vendor preset: enabled) Active: active (running) since Mon 2019-01-28 20:22:55 JST; 5s ago Main PID: 2130 (gpsd) CGroup: /system.slice/gpsd.service mq2130 /usr/sbin/gpsd -N -N -F /var/run/gpsd.sock -b -n /dev/ttyUSB0 1月 28 20:22:55 aeon.lunatilia.net systemd[1]: Started GPS (Global Positioning System) Daemon. pi@aeon:~ $
gpsdの動作確認
“gpsmon”コマンドや”cgps -s”コマンドで、情報が取得できているか確認します。
ここでは”cgps -s”コマンドを使用しています。
pi@aeon:~ $ cgps -s lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqklqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk x Time: 2019-01-28T11:38:25.154Z xxPRN: Elev: Azim: SNR: Used: x x Latitude: 33.796493 N xx 7 39 306 21 N x x Longitude: 134.505891 E xx 8 66 310 12 N x x Altitude: 39.5 m xx 9 10 254 14 N x x Speed: 123.4 kph xx 20 08 061 21 N x x Heading: 229.4 deg (true) xx 27 57 025 10 N x x Climb: -630.0 m/min xx 16 45 082 00 N x x Status: 3D FIX (281 secs) xx 18 44 185 00 N x x Longitude Err: +/- 29 m xx 11 36 219 00 N x x Latitude Err: +/- 31 m xx 26 24 103 00 N x x Altitude Err: +/- 73 m xx 1 17 197 00 N x x Course Err: +/- 77 deg xx 10 10 086 00 N x x Speed Err: +/- 226 kph xx 30 09 320 00 N x x Time offset: -2.525 xx x x Grid Square: PM73gt xx x mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqjmqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj pi@aeon:~ $ ※Time/Latitude/Longitudeあたりの値が取得できていればとりあえずOK
chronyパッケージのインストール
NTPサーバとしてchronyをインストールします。
pi@aeon:~ $ sudo apt install chrony パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 以下の追加パッケージがインストールされます: libtomcrypt0 libtommath1 以下のパッケージが新たにインストールされます: chrony libtomcrypt0 libtommath1 アップグレード: 0 個、新規インストール: 3 個、削除: 0 個、保留: 0 個。 540 kB のアーカイブを取得する必要があります。 この操作後に追加で 1,214 kB のディスク容量が消費されます。 続行しますか? [Y/n] y <中略> pi@aeon:~ $
/etc/chrony/chrony.conf の設定
pi@aeon:~ $ sudo cp -a /etc/chrony/chrony.conf{,.orig} pi@aeon:~ $ sudo vi /etc/chrony/chrony.conf ## 変更内容 ## --- /etc/chrony/chrony.conf.orig 2017-07-23 00:24:44.000000000 +0900 +++ /etc/chrony/chrony.conf 2019-01-28 20:43:12.966559520 +0900 @@ -1,6 +1,5 @@ # Welcome to the chrony configuration file. See chrony.conf(5) for more # information about usuable directives. -pool 2.debian.pool.ntp.org iburst # This directive specify the location of the file containing ID/key pairs for # NTP authentication. @@ -30,3 +29,9 @@ # Step the system clock instead of slewing it if the adjustment is larger than # one second, but only in the first three clock updates. makestep 1 3 + +# NEMA by GPS +refclock SHM 0 refid GPS precision 1e-1 offset 0.9999 delay 0.2 + +# Allow NTP client access from local network. +allow 192.168/16 pi@aeon:~ $
chronyサービスの自動起動有効・再起動
pi@aeon:~ $ sudo systemctl enable chrony Synchronizing state of chrony.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable chrony pi@aeon:~ $ pi@aeon:~ $ sudo systemctl restart chrony pi@aeon:~ $ pi@aeon:~ $ sudo systemctl -l status chrony ● chrony.service - chrony, an NTP client/server Loaded: loaded (/lib/systemd/system/chrony.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2019-01-28 20:45:08 JST; 2s ago Docs: man:chronyd(8) man:chronyc(1) man:chrony.conf(5) Process: 4261 ExecStart=/usr/sbin/chronyd (code=exited, status=0/SUCCESS) Main PID: 4263 (chronyd) CGroup: /system.slice/chrony.service mq4263 /usr/sbin/chronyd 1月 28 20:45:07 aeon.lunatilia.net systemd[1]: Starting chrony, an NTP client/server... 1月 28 20:45:08 aeon.lunatilia.net chronyd[4263]: chronyd version 3.0 starting (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +S 1月 28 20:45:08 aeon.lunatilia.net chronyd[4263]: Frequency 1.490 +/- 26.371 ppm read from /var/lib/chrony/chrony.drift 1月 28 20:45:08 aeon.lunatilia.net systemd[1]: Started chrony, an NTP client/server. pi@aeon:~ $
時刻同期の確認
pi@aeon:~ $ chronyc sources -v 210 Number of sources = 1 .-- Source mode '^' = server, '=' = peer, '#' = local clock. / .- Source state '*' = current synced, '+' = combined , '-' = not combined, | / '?' = unreachable, 'x' = time may be in error, '~' = time too variable. || .- xxxx [ yyyy ] +/- zzzz || Reachability register (octal) -. | xxxx = adjusted offset, || Log2(Polling interval) --. | | yyyy = measured offset, || \ | | zzzz = estimated error. || | | \ MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== #* GPS 0 4 17 15 -962us[-2415us] +/- 200ms pi@aeon:~ $
systemd-timesyncdの自動起動無効
OS再起動時に外部と同期しないよう、systemd-timesyncdを自動起動無効にします。
pi@aeon:~ $ sudo systemctl disable systemd-timesyncd Removed /etc/systemd/system/sysinit.target.wants/systemd-timesyncd.service. pi@aeon:~ $
OSの再起動
一旦OSを再起動して、gpsdとchronyが自動起動しつつ、systemd-timesyncdが自動起動しないことを確認します。
pi@aeon:~ $ sudo systemctl reboot pi@aeon:~ $
OS再起動後のサービス自動起動確認
pi@aeon:~ $ sudo systemctl -l status gpsd chrony systemd-timesyncd ● gpsd.service - GPS (Global Positioning System) Daemon Loaded: loaded (/etc/systemd/system/gpsd.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2019-01-28 20:58:57 JST; 26s ago Main PID: 527 (gpsd) CGroup: /system.slice/gpsd.service mq527 /usr/sbin/gpsd -N -N -F /var/run/gpsd.sock -b -n /dev/ttyUSB0 1月 28 20:58:57 aeon.lunatilia.net systemd[1]: Started GPS (Global Positioning System) Daemon. ● chrony.service - chrony, an NTP client/server Loaded: loaded (/lib/systemd/system/chrony.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2019-01-28 20:58:57 JST; 26s ago Docs: man:chronyd(8) man:chronyc(1) man:chrony.conf(5) Process: 513 ExecStart=/usr/sbin/chronyd (code=exited, status=0/SUCCESS) Main PID: 526 (chronyd) CGroup: /system.slice/chrony.service mq526 /usr/sbin/chronyd 1月 28 20:58:57 aeon.lunatilia.net systemd[1]: Starting chrony, an NTP client/server... 1月 28 20:58:57 aeon.lunatilia.net chronyd[526]: chronyd version 3.0 starting (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +SC 1月 28 20:58:57 aeon.lunatilia.net chronyd[526]: Frequency 25.730 +/- 48.536 ppm read from /var/lib/chrony/chrony.drift 1月 28 20:58:57 aeon.lunatilia.net systemd[1]: Started chrony, an NTP client/server. Warning: systemd-timesyncd.service changed on disk. Run 'systemctl daemon-reload' to reload units. ● systemd-timesyncd.service - Network Time Synchronization Loaded: loaded (/lib/systemd/system/systemd-timesyncd.service; disabled; vendor preset: enabled) Drop-In: /lib/systemd/system/systemd-timesyncd.service.d mqdisable-with-time-daemon.conf Active: inactive (dead) Docs: man:systemd-timesyncd.service(8) pi@aeon:~ $
時刻同期の確認
pi@aeon:~ $ chronyc sources -v 210 Number of sources = 1 .-- Source mode '^' = server, '=' = peer, '#' = local clock. / .- Source state '*' = current synced, '+' = combined , '-' = not combined, | / '?' = unreachable, 'x' = time may be in error, '~' = time too variable. || .- xxxx [ yyyy ] +/- zzzz || Reachability register (octal) -. | xxxx = adjusted offset, || Log2(Polling interval) --. | | yyyy = measured offset, || \ | | zzzz = estimated error. || | | \ MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== #* GPS 0 4 377 23 -188us[ -423us] +/- 200ms pi@aeon:~ $ pi@aeon:~ $ date Tue Jan 28 21:00:51 JST 2019 pi@aeon:~ $ ※実際の時刻と照らし合わせて、合っていればOK
その他
- もし精度にこだわるなら、GPIOで接続できるみちびきのモジュールとかを手に入れたほうがいいです。
- CentOS Userland 7でも同様にできると思いますが、おそらくfake-hwclockは必須です。
(ないと時刻が乖離しすぎて同期しないと思います) - fake-hwclockでも良いですが、RTCモジュールを載せておけば若干幸せかも。
コメントを残す