M5StickC Plus用に制作したログストレージハットにGPSモジュール(NEO-6M)を組み合わせて、GPSロガを作って見たいと思います。
前回、全体のシステム設計を終了したので、今回、ソフトウェア設計から完結まで持って行きたいと思います。
以下、ソフトウェアに関する各論を進めて行きます。
GPSモジュールからは、NMEA形式のテキストデータが約1s間隔で送信されてきます。このデータをSerial1クラスから、改行コードまで受信バッファlbuf1[max_lbuf1(=128)]へ受信して処理します。以下にその手順を示します。
手順1)では、受信データ量がmax_lbuf1を超えた所で一旦取り込みを打ち切ります。正常に受信した場合、受信データの1行分が受信バッファ以内に収まる様な、max_lbuf1を設定しておきます。通信エラー(文字化け等)で改行コードが破壊された場合等に、max_lbuf1を超える場合があります。
GPSモジュールからの応答をざっと見たところ、max_lbuf1=128で充分であろうと判断して決定しました。M5StickC Plusのメモリ(RAM)容量には余裕があるので、念のため、もう少し大きな値を設定しても良いです。
なお、NMEA形式のテキストデータはカンマ(,)区切りです。受信したテキストデータの先頭から所望の回数、カンマを探して行けば必要なデータ位置に到達することができます。
「$GPRMC」を見つけた時、抜き出した日時をM5StickC PlusのRTCに転送(同期)しておくと、NTPが使えなくても正しい時刻を設定可能です。
→ 空さえ見えれば正確な時間を刻むことのできる、衛星電波時計
GPSモジュールが送信してくる日時は協定世界時(UTC)なので、日本標準時(JST)へ換算するには+9時間する必要があります。この時、日付が変わってしまうと、時→日→月→年までキャリ(/ボロウ)が上がることに注意してください。
この処理は、日本標準時以外のタイムゾーンへ変更することも考えて、負の調整値や、時未満の調整値にも対応しておく事とします。
GPSモジュールの送信してくるテキストデータの中には、固定小数を返す場合があります。特に測位データに関しては、こちらで検討した様に固定小数を整数化して取り込みます。
今回使用したGPSモジュール(NEO-6M)は、小数点以下のゼロ(0)を省略しないので、小数点(.)を削除して詰めてしまえば、atoi()関数で読み込むことができます。小数点を無視するatoi()関数をatoi_fix()関数として、以下にアルゴリズムを示します。
atoi_fix()関数アルゴリズム:
例えば、以下の様な値が返ります。
atoi_fix ("123.45")=12,345
atoi_fix ("9876.54321")=987,654,321
もし、小数点以下のゼロを省略する仕様のGPSモジュールを接続した場合、以下の様に、期待した値で取り込めないことに留意しておいてください。
atoi_fix ("24.6800")=246,800
atoi_fix ("24.68")=2,468
小数点以下のゼロが省略されてしまったことで、いずれも数値24.68を表す文字列なのに、異なる値に変換されてしまう例として示しました。
完成したプログラムを以下にリンクします。
完成プログラム:gps_logger.ino
コンパイルしてM5StickC Plusへ書き込むと、シリアルモニタから、こちらと同じコマンドを受け付けています。
こちらの回路図に従ってGPSロガ装置を構築し、実験に移りましょう。I2C EEPROM周りの回路にログストレージハットを使う場合、以下の接続表でも同じ装置が構成可能です。
M5StickC Plus | 接続 | ログストレージハット | 接続 | GPSモジュール |
拡張I/Oポート | ⇔ | ピンヘッダ | ||
3V3 | → | VCC | ||
GND | ⇔ | GND | ||
G36/G25(RXD) | ← | TX | ||
× | RX |
以下図に実験中の様子を示します。
1時間ほど徒歩で移動してログを取得してみました。一応、モバイルバッテリを用い、電源強化して実験しました。帰ってから、装置をPCにUSBで接続して、以下の通り、記録したレコードを読み出しました。
実験サンプル:【 】内はシリアルモニタからの送信データ
【listb】
:
LOG+ 0x00d0: 0x7fda,'GD',00000056DDDDDDDDTTTTTTTT
LOG+ 0x00e0: 0x7fdb,'GP',NNNNNNNNEEEEEEEEffffffee
:
: (中略)
:
LOG+ 0x2830: 0x8250,'GD',00920641DDDDDDDDTTTTTTTT
LOG+ 0x2840: 0x8251,'GP',NNNNNNNNEEEEEEEE000002e8
LOG: found 645 records
OK: listb: eep_radr=0x2850, eep_ridx=0x8252
当方の存在地点が判ってしまう個人情報は秘匿しています。後ほど、このログから地図上の地点へ変換するので、ファイルに落としておきましょう。
ログデータから地図上の地点へ変換するには、「轍 Wadachi」というフリーソフトウェアを使いました。このソフトウェアは、NMEA形式のログファイルをインポートして地図に表示可能です。
GPSロガによる位置情報のデータは、以下の様に変換されて行きます。
GPSロガの位置情報変遷:
元々NMEA形式1)なのに、一旦数値化2)して、記録3)して、最後にまたNMEA形式5)に戻しています……。一見無駄な遠回りに見えますが、記憶容量の小さなEEPROMにデータを記録する為の戦略的遠回りです。
NMEA形式ファイルをインポートする時、轍が見るデータは「$GPRMC」と「$GPGGA」だと思われます。
今回のGPSロガでは、標高データも記録しているので、「$GPRMC」および「$GPGGA」を再現する事にしました。
【listb】コマンドで表示されたテキストデータから、’GD’/’GP’レコードを抜き出して、「$GPRMC」/「$GPGGA」データを再現するスクリプトを拙作Olive+で作成しました。以下にリンクしておきます。
変換スクリプト:gps_eep2nmea.olv
※スクリプト(.olv)を実行するには拙作Olive+をWindowsにインストールしてください。
【listb】コマンドで読み出したログレコード(テキストデータ)をgps_eep2nmea.txtと言う名前のファイル名で用意して、変換スクリプト(gps_eep2nmea.olv)を実行すると、gps_eep2nmea_out.logと言う名前でNMEA形式のログファイルが出力されます。
轍のウインドウにドラッグ&ドロップするか、「ファイルメニュー ⇒ インポート」で取り込んで、「ブラウザでプレビュー」ボタンを押してみてください。
さて、実験の最初に歩き回って取得したログから、轍で表示した地図データを以下図に示します。
当方の位置情報を秘匿するため、洋上の何もない地点に平行移動してあります(1^_^;)。通常は上の画面にちゃんと、地図や衛星写真などが表示されますので、ご自身でお試しください。
考察:
実用的には、安定して衛星からの電波を受信できるように運用する事が第一義のようです。
正直、もう少し安定して測位できるもの、と思っていました。1,000円を切るGPSモジュールでは、この辺りが限界なのでしょうか??