NanoPi NEOにGPSモジュールを繋いでNTPサーバ

NanoPi NEO
画像は使い回し

この記事ではroot(スーパーユーザー)で実行するコマンドは行頭に#、一般ユーザーで実行するコマンドは行頭に$を付けている。Linuxの流儀であれば su - でrootになって実行するよりはsudoで実行する。# hogehoge と書いてたら一般ユーザーで sudo hogehoge を実行みたいな。

正しい現在日時の設定・表示

まず、GPS云々以前にNanoPi NEOで正しく時刻表示できるようにする。

# dpkg-reconfigure tzdata

メニューが表示されるので先ずAsiaを選択、次にTokyoを選択。
armbianのdebian Jessieならこれだけ。

表示してみる

$ timedatectl status
      Local time: Wed 2017-03-11 11:26:41 JST
  Universal time: Wed 2017-03-11 02:26:41 UTC
        RTC time: Thu 1970-01-01 01:14:48
       Time zone: Asia/Tokyo (JST, +0900)
     NTP enabled: no
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a

Local timeがJSTで表示されていてTime zoneがAsia/TokyoになっていればOK。
NanoPi NEOには時計のバックアップ(電池)が無いので一度電源が切れるとRTC timeが1970年1月1日0時に戻ってしまうが、これは無視で良い。どうしても気になるならRTCモジュールを買うなり自作するなりして追加するというのもアリだが、これからNTPやGPSで時刻を取るので正直あまり意味があるとは思えない。

RTC timeをどうしても1970年ホゲホゲから現在時刻に変更したいなら正しい時刻を取得した後に次を実行。

# hwclock -w

これでRTC timeがUniversal timeと同じ値になる。

2017年3月14日追記:
armbianのカーネルを3.4.113から4.10.0に(armbianで配布しているパッケージで)更新すると起動後のどこかのタイミングで自動的にRTC timeに時刻を入れてくれるようになるみたい。ただし、fake-hwclockを使っているようなので完全にUniversal timeに一致するわけではなく意味あるのか?という感じ。RTCをNTPに同期させるようにしてやるとほぼ正しい時刻になるのでそちらの方が良さげ。

日付と時刻が全然正しくないなら現在のNTPの状態を確認。

$ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*ntp1.jst.mfeed. 133.243.236.17   2 u  132  256  377   14.619    0.173   0.127

NTPの設定をした憶えはないが、DHCP有効ならありがたくも勝手に日本のMFEEDから取っている筈。固定IPならdebian.pool.ntp.orgから取ってる筈。
行頭に * (同期中)が表示されているのに日時が滅茶苦茶なら根本的に何かがおかしい。そうでなければ正しい日時を表示している筈。
行頭に * (同期中が付くのは1つの時刻ソースだけ)が表示されていない場合は次。NTPサーバに接続できてるならそうはならない筈だけど・・

日時表示がおかしい場合の仮対応

# apt-get install ntpdate   #必要なら
# /etc/init.d/ntp stop
# ntpdate ntp.jst.mfeed.ad.jp
# date
# /etc/init.d/ntp start
# date

ntpdを停止してntpdateで手動でntp.jst.mfeed.ad.jpから時刻を取得。
(または、ntpdate -u ntp.jst.mfeed.ad.jp ならNTPを再起動しなくても可)
dateで現在日時を確認。ここで正しい日時が表示されるならntpdを起動する。
1分ほど待ってから再度dateで現在日時を確認。
上では/etc/init.d ntp (start|stop|restart)を使っているが、systemctl (start|stop|restart) ntp.serviceでも可。
Time Zoneが変なら再度dpkg-reconfigure tzdataをやり直す。それでもダメならarmbian焼き直しが無難。

gpsd他のインストール

# apt-get install gpsd
# apt-get install gpsd-clients

もちろん纏めてapt-get install gpsd gpsd-clients でも可。

シリアルポートとgpsdの設定

GPSモジュール
1つ前の記事で購入したGPSモジュール

NanoPi NEOピン配置
©FriendlyARM.

今回は NanoPiのGPIO 8番ピンUART1_TXとGPSモジュールのRX、NanoPiのGPIO 10番ピンUART1_RXとGPSモジュールのTXを接続。念の為にNanoPiのGPIO 6番ピンGNDとGPSモジュールのGNDを接続。GPSモジュールへの電源はUSB供給。(ピンからも取れるけど)
これでNaniPiとGPSモジュールが通信できるようになっている筈。

上のピン配置図がわかりやすい。今回使ったGNDは右端の上から3番めのピン、UART1-TXは右端の上から4番めのピン、UART1-RXは右端の上から5番めのピン。
なお、ピンと書いているけど実際には基板にはスルーホールしかないのでピンヘッダかピンソケットを取り付けて配線する。ワイヤーをハンダ直付けでもいいけど・・

GPSモジュールと接続
GPSモジュールと接続した。上の写真では既にPPSも結線している(黄色の線)。

シリアルポートの確認
今回はUART0ではなくUART1を使用しているのでデバイスは/dev/ttyS1

$ cat /dev/ttyS1

$GPホニャララという行(NMEAセンテンス)が停まらずに出続ければ正常。Ctrl+Cで終了

すでにgpsdが動いている筈だが、GPSソースとしてttyS1を使用しない状態なので設定ごと停止&削除。

# systemctl stop gpsd.socket
# systemctl disable gpsd.socket

手動でttyS1を使用してgpsdを起動する。

# gpsd /dev/ttyS1 -F /var/run/gpsd.sock

GPSのデータ受信を確認(コマンド実行から表示まで数秒かかるかも)

$ cgps -s
または
$ gpsmon
cgps

これで正常にgpsdが動くことが確認できた。
そこで、gpsdがttyS1を使って自動起動できるようにする。

gpsd設定ファイル (おそらく新規作成)

# vi /etc/gpsd
1
2
3
4
START_DAEMON="true"
USBAUTO="false"
DEVICES="/dev/ttyS1"
GPSD_OPTIONS="-n"

4行目のGPSD_OPTIONSの-nを指定し忘れるとgpsd自体は正常に起動して例えばgpsmonとかcgpsなどは使えるが、NTPのソースとして使えない。
今回はNTPサーバが目的なので、gpsd経由で時刻を取るなら絶対必要なオプション。gpsdなんか使わず直で取るならどうでもいいけど。

# vi /lib/systemd/system/gpsd.service (1行だけ変更)
EnvironmentFile=-/etc/gpsd

FreeBSDだと/etc/defaults/hogeを/etc/hogeの設定行でオーバーライドという流儀だけどLinuxってそうならないんだっけ?
defaultって名前のディレクトリの存在する意味がないような・・
それなら /etc/gpsd 作成且つ /lib/systemd/system/gpsd.service の変更じゃなく、 /etc/default/gpsd を直変更のが簡単かも。

2017年3月14日追記:
armbianのカーネルを3.4.113から4.10.0に(armbianで配布しているパッケージで)更新した場合は以下2行を実行。(更新していないなら実行しない)

# systemctl enable gpsd.socket
# systemctl start gpsd.socket

次はカーネル更新の有無に関わらず自動起動のために必ず実行。

# ln -s /lib/systemd/system/gpsd.service /etc/systemd/system/multi-user.target.wants/

システムを再起動したときにgpsdが/dev/ttyS1を使用して正しく起動することを確認。(cgps -sまたはgpsmonで表示されればOK)

ntp.conf設定

(armbianのdebian jessieでは) DHCPが有効な場合はntpdは /etc/ntp.conf を読まずに /var/lib/ntp/ntp.conf.dhcp を読むようになっているが、 /var/lib/ntp/ntp.conf.dhcp はシステム起動時に上書きされてしまうので /var/lib/ntp/ntp.conf.dhcp を編集するのは意味がない。そこでDHCP有効でも /etc/ntp.conf を読むようにしたい。

# vi /etc/dhcp/dhclient.conf
request subnet-mask, broadcast-address, time-offset, routers,
        domain-name, domain-name-servers, domain-search, host-name,
        dhcp6.name-servers, dhcp6.domain-search,
        netbios-name-servers, netbios-scope, interface-mtu,
        rfc3442-classless-static-routes;

requestの行の最後から", ntp-servers"を削除。それ以外は触らない。

固定IPの場合は何も考えずに/etc/ntp.confを変更する。

# vi /etc/ntp.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
driftfile /var/lib/ntp/ntp.drift
statsdir  /var/log/ntpstats/

server ntp1.jst.mfeed.ad.jp #210.173.160.27
server ntp2.jst.mfeed.ad.jp #210.173.160.57
server ntp3.jst.mfeed.ad.jp #210.173.160.87
#server ntp1.v6.mfeed.ad.jp #2001:3a0:0:2001::27:123
#server ntp2.v6.mfeed.ad.jp #2001:3a0:0:2005::57:123
#server ntp3.v6.mfeed.ad.jp #2001:3a0:0:2006::87:123

restrict -4 default ignore
restrict -6 default ignore

restrict 127.0.0.1
restrict ::1

restrict 192.168.0.0 mask 255.255.255.248 nomodify notrap
#restrict 2000:****:****:****:: mask ffff:ffff:ffff:ffff:: nomodify notrap

restrict -4 210.173.160.27 mask 255.255.255.255 nomodify notrap noquery
restrict -4 210.173.160.57 mask 255.255.255.255 nomodify notrap noquery
restrict -4 210.173.160.87 mask 255.255.255.255 nomodify notrap noquery
#restrict -6 2001:3a0:0:2001::27:123 nomodify notrap noquery
#restrict -6 2001:3a0:0:2005::57:123 nomodify notrap noquery
#restrict -6 2001:3a0:0:2006::87:123 nomodify notrap noquery

server 127.127.28.0 minpoll 4 maxpoll 4
fudge 127.127.28.0 refid NMEA

GPS関係は最後の2行だけ。
今回は時刻ソースをgpsdのNMEAにしたので127.127.28.0。「がとらぼ」の以前の記事ではgpsd経由じゃなくシリアルポート直取りのNMEAだったので127.127.20.0。
最終行のrefidの後は識別用の任意の文字列。ネットで検索して他所様のGPS & NTP関連のページを見るとこの値を"GPS"にしてる人が多いけど今回はGPSのNMEAとPPSの2つを時刻ソースとして使う予定で、ここで設定するのはNMEAなので"GPS"ではなく"NMEA"とした。前回は、この値を"GPS"にしているが、そちらの記事ではGPSのNMEAだけを時刻ソースとして使用したのでわざわざ"NMEA"と明示する必要がなかったから。

armbianインストール後に特に触っていなければdriftファイルがおそらく存在しないので作成する。すでに存在するなら下2行のコマンド実行は不要。

# touch /var/lib/ntp/ntp.drift
# chown ntp:ntp /var/lib/ntp/ntp.drift

ntpdを再起動して確認

# /etc/init.d/ntp restart

ntp再起動から30秒以上待ってからntpq -pで確認する。

$ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
+ntp1.jst.mfeed. 133.243.236.17   2 u    5   64   37   15.058   -2.814   1.082
+ntp2.jst.mfeed. 133.243.236.17   2 u    4   64   37   14.191   -2.522   0.135
-ntp3.jst.mfeed. 133.243.236.17   2 u    7   64   37   14.111   -3.586   0.430
*SHM(0)          .NMEA.           0 l    4   16  377    0.000   -0.291   0.126

上の結果はNMEAとMFEEDの公開NTPサーバとのoffsetが200程度あったのでその分を反映(time1 0.200を設定追加)させている。

fudge 127.127.28.0 time1 0.200 refid NMEA

PPSをソースにせずNMEAだけというならNMEAの遅延の程度が不明なので、このようにNTPサーバ(上の例ならMFEED)の時刻に寄せてしまうというのもあり。
または、正確な時刻を得る環境があってNMEAの遅延を測定できるならその値を反映させる。
できればしばらくoffsetの様子を見ながら0.200なんてアバウトじゃなくもう少し細かく。

PPSは次の記事で。

関連記事: