GNSS
Logger
バイク用GNSSロガー

概要
バイク用に作ったGNSSロガーです。
2024年、思い立って二輪免許を取りバイクを買いました。そして「お手軽にバイクで走った場所記録できればいいのになぁ」と思いロガーを探しました。
が、探してもなかなかいい製品がなく、GoogleのTimelineがデバイス保存になってしまったタイミングでもあり、じゃあ自分で作るかぁとなり製作。
2024年、思い立って二輪免許を取りバイクを買いました。そして「お手軽にバイクで走った場所記録できればいいのになぁ」と思いロガーを探しました。
が、探してもなかなかいい製品がなく、GoogleのTimelineがデバイス保存になってしまったタイミングでもあり、じゃあ自分で作るかぁとなり製作。

買ったバイク
とりあえずの方針
- 小型軽量、お手軽、カバンや荷物入れに放り込める。
- USB接続で電源供給。バックアップ電池内蔵で給電切れても記録続行できる。
- 旅先でGoogleマイマップにアップして公開できる。
- ひとまずパッと作れる
- 長期間容量気にせず記録しつづけられる。
というわけで、コンパクトに作れて手っ取り早くコードが作れるM5stack+GNSSモジュール使いArduinoで開発。

M5stack+GNSSモジュール
使ったもの
ハード
- M5stack Core2
- M5stack GNSS module
- アリエクで買った詳細あまりわからないアンテナ
ソフト
- Platform IO
- Arduino Framework
- SparkFun_u-blox_GNSS_v3ライブラリ
クラウド
- Cloudfrare R2
- Cloudfrare Functions
- Cloudfrare Workers
運用と感触(ローカル運用)
M5StackではGNSSモジュールが帰してくる緯度経度+高度などをCSVで1秒1回記録。SDカードに書き込む。
出来たCSVをPythonスクリプトで読みこみgoogleマイマップが読み取れるGPX形式に変換。
手動でマイマップへアップロード。
結構高い精度でロギングできてて感動。(参考:台湾バイク旅行した時のログ結果↓)
台湾旅行GNSSログ
出来たCSVをPythonスクリプトで読みこみgoogleマイマップが読み取れるGPX形式に変換。
手動でマイマップへアップロード。
結構高い精度でロギングできてて感動。(参考:台湾バイク旅行した時のログ結果↓)
台湾旅行GNSSログ
良い点
持ち運びが楽
目論見通り小さくて軽くて、給電ケーブル挿して荷物入れにポンと入れておくだけでいい感じにデータが取れる。
大容量
16GBのTFカードを入れていますが、何年分記録できるんだろうというレベルで記録可能。
低?消費電力
一日使ってもモバイルバッテリーが誤差レベルでしか減らない。
旅先でもアップロード可
SNSが捗る。

実際に使用している時 高度誤差は20m程度
問題点
価格
M5StackとGNSSモジュールとアンテナで2万円強。高度な処理しているわけでもないのでもっと安いものを選定しても良かった。
電圧問題
内蔵バッテリー電圧がさがるとSDカードの認識エラーが起きて記録が止まる現象が起こっている模様。M5Stack側の問題だとは思うが何か対策したい。
静止・低速時ドリフト
街中など電波が若干不安定な場所で静止した状態だと座標がドリフトしていく。
32bitの罠
M5Stack Core2はdoubleを指定しても32bitで扱われるようで、公式のライブラリを使うとせっかくGNSS使ってるのに緯度経度の1桁捨ててしまっているので、なんとかしたい感。自分でNMEAをパースするのも面倒なためどうしたものかというところ。
蓋閉まらない問題
M5Stack Core2に公式のGNSSモジュールをはめているのにフタが閉まらない罠。公式モジュールなんだから閉まってほしい…。ケースを削って千切って無理矢理蓋を閉めた。

蓋が閉まらない。
クラウド対応 (2026/02/21)
旅先でSDカードからのデータ吸い出しと変換が想像以上に面倒だったため、クラウドで保存とGPX変換処理を行わせることにした。
以下が処理の流れ
以下が処理の流れ
- GNSSデータ取得完了時に予め登録したWifiホットスポットを検索(バイクのナビスマホ用に使ってるホットスポットの使用を想定)
- ホットスポットに接続しNTPで時刻同期
- 同期した時刻を使ってPUTでCSVデータをR2へ格納。同時にタイムゾーンをメタデータとして付加。
- Cloudflare WorkersでCronトリガ
- Workers内でR2に保存されたCSVを、メタデータからUTC時間に直してGPXに変換

クラウド周りのアーキテクチャ図
細かい話
送信キュー
R2へのアップロード失敗・Wifiが見つからない場合は送信キューに登録し次回接続時に再送信する。重要な情報でもない+バグったときに簡単に消せるため、SDカード上に適当なtxtファイルを作りそれで管理している。
R2へのPUT
バッファには乗り切らないため、SDカードにあるデータをストリームで送信する。
時間合わせ
NTPに接続して取得した時刻でシグネチャを作成する
タイムゾーン
デバイス内にタイムゾーンを指定(現在手動)し、LocalTimeでCSVデータは記録する
GPX1.1ではUTCでのデータ記録が標準のため、CSVデータにUTCからのオフセットを追記し、GPX変換時にUTCに変換する。
なおGoogleのマイマップやReliveにGPXデータアップロードする際は、アプリを開いているタイムゾーンが適用されるため、他国でデータを取得し日本でプロットする場合には日本時間になってしまう。ここは要改善
GPXへの変換
Cloudflareの無料枠ではR2のイベントを用いたトリガ(Queue)が使えないため、不便ではあるが一定時間ごとに実行する形で実装
- WorkersはCPUの時間制約がキツい⇒制約の緩いCloudflare FunctionsでGPX変換処理を行う。
- Functionsでは時間実行ができない⇒WorkersではCronが利用可能なので、Workersで時間トリガを設定し、Functionsを叩く
- トリガからさかのぼって一定期間以内に作られたCSV && GPXが作成されていないファイルに対してGPX変換を実行する
運用と感触(クラウド運用)
めっちゃ楽
ただし、R2バケットに直接取りに行かないといけないのは結構ナンセンスなので、そのうち自分用WebUI作る。