SPRESENSEで高精度GPSロガーをつくる


はじめに

みちびきのサブメータ級測位補強サービス(L1S)に対応した製品を眺めていたら
ソニーのSPRESENSEがあるではないですか。

これでGPSロガーを作れば高精度測位の 実力とやらを見せてもらおうか 実験ができる!
というわけで買ってしまいました

さて、GPSロガーに仕立てていきます

結果だけ知りたい、という人は結果へどうぞ

開発環境の構築 ~ Lチカ

公式のスタートガイドに従えば、ハマリどころはないのですが
手順を簡単に書いておきます。

環境

  • PC w/ Windows7 Pro SP1 (公式には8.1 or 10とありますが、7でもいけました)
  • SPRESENSE本体 (拡張ボードなし)
  • USB-microケーブル

ダウンロードしたもの

手順

  1. Arduino IDEをインストール → インストーラーを起動しインストールするだけ
  2. CP210xをインストール → これも...
  3. Spresense Arduino board package のインストール → Arduino IDEでの操作だけ
  4. SPRESENSEをPCに接続 → USBケーブルでつなげるだけ
  5. ブートローダのインストール → Arduino IDEでの操作だけ
  6. サンプルスケッチでLチカ → コードをコピペしてボタン押すだけ

あれっ、ボードコンピューターってこんなに簡単に動かせるんだ!
と思うくらい簡単です。いい世の中になりました。

GPSロガーに仕立てる

開発環境には豊富にサンプルがついています。
Arduino IDEで ファイル > スケッチ例 と開くとサンプルが見られます。
GNSSがGPSを使ったサンプル群です。
で、gnss_tracker が非常によくできておりまして、
これをベースに以下の点を変更してロガーとして仕立てました。

  1. 利用する衛星に GPS + L1C/A(みちびき) + L1S(みちびき 測位補強) を指定
  2. ログデータの書き込み先を SDカード から 内蔵Flash に変更 (拡張ボード未購入のため...)
  3. カスタマイズ性はいらないので、config file周りのコードをがっさり削除
  4. LEDの利用方法の変更 (L1S信号受信状況を表示)

コードはGitHubに置きました
こちらからどうぞ。

(追記) Qiita記事らしくコードを引用してポイント解説

インスタンス生成

SpGnss Gnss;                            /**< SpGnss object */

GPS受信の準備

  if (Gnss.begin(Serial) != 0)
  {
    /* Error case. */
    APP_PRINT_E("Gnss begin error!!\n");
    error_flag = 1;
  }
  else
  {
    APP_PRINT_I("Gnss begin OK.\n");

    // GPS + QZSS(L1C/A) + QZAA(L1S)
    Gnss.select(GPS);
    Gnss.select(QZ_L1CA);
    Gnss.select(QZ_L1S);
    Gnss.setInterval(POSITIONING_INTERVAL);

    if (Gnss.start(HOT_START) != OK)
    {
      /* Error case. */
      APP_PRINT_E("Gnss start error!!\n");
      error_flag = 1;
    }
  }

Gnss.begin()で初期化、Gnss.select()で衛星を指定、Gnss.setInterval()で受信間隔を指定、Gnss.start()で受信開始

位置データの受信

void loop() {
  // static
  static bool PosFixflag = false;
  static char *pNmeaBuff = NULL;
  static int WriteCounter = NUMBER_OF_CACHE;

  /* Check update. */
  if (Gnss.waitUpdate(POSITIONING_INTERVAL * 1000))
  {
    /* Get NavData. */
    SpNavData NavData;
    Gnss.getNavData(&NavData);

    /* Position Fixed?? */
    bool LedSet = ((NavData.posDataExist) && (NavData.posFixMode != 0));
    if (PosFixflag != LedSet)
    {
      Led_isPosfix(LedSet);
      PosFixflag = LedSet;
    }
    if (PosFixflag) {
        //unsigned short sat = NavData.posSatelliteType;
        unsigned short sat = NavData.satelliteType;
        // GPS, QZ_L1CA --> LED1
        if (0 != (sat & (GPS | QZ_L1CA))) {
          ledOn(PIN_LED1);
        } else {
          ledOff(PIN_LED1);  
        }
        // QZ_L1S --> LED2
        if (0 != (sat & QZ_L1S)) {
          ledOn(PIN_LED2);
        } else {
          ledOff(PIN_LED2);  
        }
    }

Gnss.waitUpdate()で位置情報の取得をまち、1が戻れば位置情報が取れています。
Gnss.getNavData()で様々な情報が詰まったSpNavDataが取り出せます。
例えばSpNavData::satelliteTypeには捕捉している衛星の種類が入っています。

NMEAデータに変換

    /* Convert Nav-Data to Nmea-String. */
    String NmeaString = getNmeaGga(&NavData);

もとのサンプル(gnss_tracker)のコードをそのまま使わせてもらっています。
あとはこれをファイルに書けばOKです。
Flashなのであまり高頻度に書き込みしないように気を付けましょう。
このコードでは受信データ12回分をバッファして、書き込み頻度を1回/分にしています。

Flash上のファイルの取り出し方

GPSログをFlashから読みだす必要があります。
そのために、YModem転送機能をそなえた簡易ファイラーを作りました。
コードは以下から取得できます。

ターミナルソフトはArduino IDEのものではなくTera Termを利用してください。
Y + 番号でダウンロードしたいファイルを指定した後、
Tera Termのメニューから ファイル > 転送 > Y-Modem > 受信
を選択します。
あらかじめ「ディレクトリを変更」でダウンロード先を指定するとよいと思います。

ログはNMEAフォーマットです。
あとは煮るなり焼くなりお好きに...

結果

自転車で120kmほど走ってログを取得しました。

Google Map
https://drive.google.com/open?id=15Q-2rhg1ZXhqd4IbaEpAJG99x_awx3eZ&usp=sharing

ログを取った日は、スタート直後からL1S信号を安定して受信できていました。
往路の環7、江戸川、手賀沼、復路の江戸川、荒川では
ほぼ100%の時間L1S信号を捕捉していたようです。

ログの精度は素晴らしく、
特に三郷駅付近、みさとの風ひろばでの休憩中のログの
ブレの少なさには驚きました。

ビルの多い街中ではL1S信号をなかなかつかめないこともありますが、
ひらけた場所を走ることが多い自転車用のロガーとしては
かなり優秀なんじゃないでしょうか。
ケースとバッテリーを工夫してロングライドのお供にしようと思います。

おまけ

ステム部分にモバイルバッテリーとSPRESENSEをつけています