Wio LTEでGrove GPS出力を解析


Wio LTEでGPSを使う

日本版のWio LTEにはGPS機能は付いていませんが、GroveのモジュールにGrove - GPSがあります。これを使えばGPSを使って、位置や時刻を取得できるようになります。Grove - GPSは国内ではスイッチサイエンスで購入することができます。
また、SORACOMのGrove IoT スターターキットにもGrove - GPSが付属しています。(実はWio LTEとGrove - GPSだけでGrove IoT スターターキットの販売価格ぐらいになるのでWio LTEでGPSを使いたい方はめちゃお得です。)

Wio LTEのライブラリにはそれを扱うライブラリもありますが単純に受信したデータを表示するだけのものなので、中身まで解析する方法を紹介します。

NMEA

GPSから受信するデータは一般的にNMEAというフォーマットになっています。
一般的なフォーマットなので、それを扱うライブラリもたくさんあります。
その中で使ってみたものがあるので紹介します。

MicroNMEA

Arduino用のライブラリなので、APIはほぼそのまま使えます。その上、マイコン用に小さいサイズで作られているのでWio LTEでも使いやすいと思います。

ZIP形式でダウンロードして、ArduinoIDEにインポートします。

スケッチ

ライブラリの中にはスケッチ例も含んでいますが、Wio LTEではそのまま使えないのでWio LTE向けにカスタムしました。

#include <WioLTEforArduino.h>
#include <MicroNMEA.h>

HardwareSerial& gps = Serial;
char nmeaBuffer[100];
MicroNMEA nmea(nmeaBuffer, sizeof(nmeaBuffer));
bool ledState = LOW;

WioLTE Wio;

void led(bool state)
{
  if(state)  Wio.LedSetRGB(0, 255, 0);
  else       Wio.LedSetRGB(255, 0, 0);
}

void gpsHardwareReset()
{
  while (gps.available())
    gps.read();

  Wio.PowerSupplyGrove(false);
  delay(500);
  Wio.PowerSupplyGrove(true);

  while (1) {
    while (gps.available()) {
      char c = gps.read();
      if (nmea.process(c))  return;

    }
  }
}

void setup()
{
  gps.begin(9600);

  Wio.Init();
  Wio.PowerSupplyGrove(true);

  led(ledState);

  SerialUSB.println("Resetting GPS module ...");
  gpsHardwareReset();
  SerialUSB.println("... done");

  MicroNMEA::sendSentence(gps, "$PORZB");
  MicroNMEA::sendSentence(gps, "$PORZB,RMC,1,GGA,1");
  MicroNMEA::sendSentence(gps, "$PNVGNME,2,9,1");

}

void loop()
{  
  if(nmea.isValid()) {
    ledState = true;
    SerialUSB.println();
    SerialUSB.println("-----------------------");  

    SerialUSB.print("Valid fix: ");
    SerialUSB.println(nmea.isValid() ? "yes" : "no");

    SerialUSB.print("Nav. system: ");
    if (nmea.getNavSystem())
      SerialUSB.println(nmea.getNavSystem());
    else
      SerialUSB.println("none");

    SerialUSB.print("Num. satellites: ");
    SerialUSB.println(nmea.getNumSatellites());

    SerialUSB.print("HDOP: ");
    SerialUSB.println(nmea.getHDOP()/10., 1);

    SerialUSB.print("Date/time: ");
    SerialUSB.print(nmea.getYear());
    SerialUSB.print('-');
    SerialUSB.print(int(nmea.getMonth()));
    SerialUSB.print('-');
    SerialUSB.print(int(nmea.getDay()));
    SerialUSB.print('T');
    SerialUSB.print(int(nmea.getHour()));
    SerialUSB.print(':');
    SerialUSB.print(int(nmea.getMinute()));
    SerialUSB.print(':');
    SerialUSB.println(int(nmea.getSecond()));

    long latitude_mdeg = nmea.getLatitude();
    long longitude_mdeg = nmea.getLongitude();
    SerialUSB.print("Latitude (deg): ");
    SerialUSB.println(latitude_mdeg / 1000000., 6);

    SerialUSB.print("Longitude (deg): ");
    SerialUSB.println(longitude_mdeg / 1000000., 6);

    long alt;
    SerialUSB.print("Altitude (m): ");
    if (nmea.getAltitude(alt))
      SerialUSB.println(alt / 1000., 3);
    else
      SerialUSB.println("not available");

    SerialUSB.print("Speed: ");
    SerialUSB.println(nmea.getSpeed() / 1000., 3);
    SerialUSB.print("Course: ");
    SerialUSB.println(nmea.getCourse() / 1000., 3);

    SerialUSB.println("-----------------------");    
    nmea.clear();
  }
  else
  {
    ledState = false;
  }

  led(ledState);

  while (gps.available()) {
    char c = gps.read();
    if(!ledState) SerialUSB.print(c);
    nmea.process(c);
  }
  delay(1000);
}

動作

Grove - GPSWio LTEUARTのGroveコネクタに接続して、動作をさせます。
受信したGPSの情報が妥当でない場合はLEDを赤く点灯し、GPSから受信したNMEAをそのまま表示します。GPSの情報が妥当な場合はNMEAを解析した結果を表示します。

GPS情報が妥当でない場合

GPS情報が妥当な場合(自宅がバレそうなので、位置情報の細かい値は伏せてます)

GPS情報の各値はMicroNMEAクラスの各関数で取得できるようになっていますので、
ちなみに緯度経度はWGS84(世界測地系)です。こちらはGoogleMapなどのほとんどの地図ソフトがWGS84なので気にする必要はありませんが、時刻はUTC(協定世界時)なのでJST(日本時間)にしたい場合は9時間分足してください。(時刻の足し算はそのままやるとめんどくさいので、わからない場合ははコメント下さい。)

執筆しているWio LTEのkindle書籍について

だいぶ出版が遅れてしまっているのですが、執筆しているWio LTEの本がようやくゴールが見えてきました。いろいろ掲載許可の確認が遅くなってしまったのと、次々載せたいネタが増えたので遅れてしまいました。
すでに出版しているファーストステップ編では、Arduino環境とEspruino(JavaScript)環境のセットアップ方法を解析しましたが、近日出版予定のGroveリファレンス編はこの記事で書いている様にさまざまなGroveのモジュールの扱い方を解説しています。実はこの記事もGroveリファレンス編に掲載しているネタの一つです。(この記事よりもうちょっと細かく書いています)
ファーストステップ編ではArduino環境で扱う場合とEspruino(JavaScript)環境で扱う場合の両方を書きましたが、ボリュームの都合上、それぞれの書籍を分けることにしました。近日出版するのはArduino環境向けの書籍です。

以下、書籍の情報です。

出版形式:kindle(電子書籍)
価格:1,250円(予定)
その他:書籍の中で、扱っているライブラリやスケッチ例はGitHubからダウンロードできるようにします。
〇目次
Groveとは
Groveの種類
 電圧の違い
 インターフェースの違い
Groveリファレンス
 Grove IoT Starter kit
  Grove - ボタン(P) (入力装置)
  Grove - ブザー(出力装置)
  Grove - 磁気スイッチ
  Grove - 温湿度センサー
  Grove - 超音波距離センサー
  Grove - GPS
  Grove - 3軸デジタル加速度センサー(±16g)
 さまざまなGroveモジュール
  Grove - 水センサ
  Grove - 水分センサ
  Grove - シリアルカメラモジュールキット
  Grove - I2C タッチセンサ
 そのまま繋げられないGroveモジュール
  Grove - ダストセンサー
  Grove - CO2センサー
  GROVE - 火炎センサ
 自作Groveモジュール
  e-DISP4
  BME680 温湿度・気圧・ガスセンサモジュール
  VEML6070 UV紫外線センサ・モジュール

(リクエストあれば、出版後扱うモジュールを追加していく予定です。)