cgpsで時間は更新されるのに緯度経度が更新されない。
はじめに
Raspberry Pi 3BとAliExplessで買ったU-blox7のGPS受信機でGPSロガーを作ろうとしたことでハマった問題です。日本語の記事が全く見当たらなかったので、海外の掲示板を見てわかった情報等々を備忘録がてら残しておきます。メイン環境でも発生したのでRaspberry Piに限った症状ではないと思われます。
症状
cgpsとPythonのライブラリであるgps3において、受信環境の良いところでもプログラム実行時の緯度経度から更新されない、あるいは0,0から更新されないという症状です。たちが悪いことにGPSの時間はPythonプログラム上でもcgps上でもきっちり更新されており、単に受信していないわけではないようです。一方でgpsmonでは緯度経度がしっかり更新されており、件の症状が発生しません。
原因
gps3の不具合のようです。そもそもgps3はきちんと整備がなされてないようで(要出典)、更新され続けているgpsdに追いつくことができていないそうです。cgpsの不具合も内部でgps3を使用しているからだと思われます。
ではなぜgpsmonは正常に更新されているのかというと、gpsmonはgps3を使用せずgpsdから直接情報を得ているからです。(gpsdはアダプタからのメッセージをlocalhostのポート2947に転送するので、gpsmonはそこを直接tcpで読みに行っているようです。)
解決策
解決策ですが、cgpsやgps3を使わないことしかないようです。Pythonコードではgpsdに依存しない、serialとMicropygpsなどの使用を検討してください。
gpsdは消してしまったほうがいい
で、ここまでは割と簡単にたどり着けました。とりあえずgpsが値を受信しているかを確認したいのであれば、シリアル通信をcuなりminicomなりで読みに行けばいいわけです。来ている文はNMEAのはずなので比較的容易に解読できます。
まずはgpsdを止めないとcuなりminicomなりにビジーだと怒られてしまうので、止めます。serialライブラリとかを使うときも再起動して有効になってると怒られるので無効にするといいと思います。
sudo systemctl stop gpsd.socket
sudo systemctl disable gpsd.socket
そしてcuやminicomをつかってserialを見に行きます。
cu -l /dev/ttyACM0 -s 9600
minicom -D /dev/ttyACM0 -b 9600
実行するとGPSから来ているNMEA が表示されますが、なかにはGPTXTのみ正常に表示され、ほかはバイナリ形式/xXXの形で表示されてしまう場合もあると思います。これはgpsdがU-blox内の設定記憶用ROMを勝手に書き換えてしまい、バイナリモードになっていることが原因です。
直し方
WindowsマシンにU-centerというU-blox公式のユーティリティソフトをインストールし、ROMの設定を初期化してください。接続方法に応じてシリアル変換ケーブルを用いてUSBでマシンに接続し、デバイスドライバからCOMポートを確認、U-centerの左上にあるコネクタボタンのドロップダウンからCOMポートとボーレートを選択(ステッキのようなボタンで自動選択もできます。)してコネクタボタンを押します。正常に接続されると緑色になりますから、右側のフロッピーと赤いマークがついているボタンを押せばROMの設定が初期化されます。受信テストができるので、右下にNMEAと表示されていることを確認しましょう。
せっかく直しても使用環境にgpsdが居座っているとまた勝手にROMを書き換え余計なお世話をする可能性がありますから、gpsdは消してしまったほうがいいです。
最後に
備忘録的に書いたので画像が全く無くて申し訳ないです。日本語の情報があまりに少なすぎたので(調べ方が悪い?)同じところでハマる人を救済したくて書きました。エンジニアでもないのにすみません。
基本的にシリアルで扱うようなデバイスは、Pythonで使うならserialから直接読みに行ったほうが良いです。あまりにも煩雑なのはしょうがないですが、思わぬ場所の落とし穴でつまずくのはもったいないです。私は1週間発狂しました。
Discussion