Skip to content

GPS_RMC

朝日薫 edited this page Dec 30, 2022 · 3 revisions

GPS_RMC クラスリファレンス

簡易的GPS位置/時刻情報取得支援クラス。

UART接続 GPSの NMEAフォーマットの内$**RMC行だけを解析し、 位置情報と時刻情報を取得する。 他の情報は解析しないため実装コード量は必要最低限である。 ただしlong型乗除算を含む。 浮動小数点演算は使われない。

取得される緯度/経度は、1/6,000,000度を最小単位とするlong符号付整数値である。 この最小単位で割るとWeb地図で使用できる浮動小数点値を直接得られる。 ただし AVR-GCC/AVR-LIBC では普通float単精度浮動小数点数しかサポートされないため、 精度落ちがあることに注意されたい。 本来の正確な GPS取得精度を維持してセンサー送信する場合には元のlong型のままとするのが良い。

取得される年月日/時分秒は、BCD表現のUTC世界協定時である。 最小精度は秒。 UNIX epochへの変換や、地域時への時差加減算には <bcddatetime.h>を使用すると良い。

用例

#include <GPS_RMC.h>
GPS_RMC_Class GPS_RMC; /* クラスインスタンス作成 */

void setup (void) {
  Serial.begin(CONSOLE_BAUD); /* to PC console */
  Serial1.begin(9600);        /* from GPS NMEA */
}
void loop (void) {
  /* 注:RMC以外の出力を抑制していないのなら 1024 は必要だろう */
  /* 抑制されているなら 1行読めれば良い */
  char buff[ 80 ];

  /* GPSシリアルから NMEAを読取 */
  size_t length = Serial1.readBytes(&buff, sizeof(buff));

  if (0 < length && '$' == buff[0]) {
    /* 行頭が`$`文字ならば */
    if (GPS_RMC.update(&buff, length)) {
      /* 解析に成功したならば */
      /* 情報を構造体に取得 */
      gpsdata_t gpsdata = GPS_RMC.getData();

      /* 時刻情報が更新されたなら */
      if (gpsdata.update.stamp) {
        /* BCD表現値をそのまま 16進プリント */
        Serial
          .print(gpsdata.stamp.date, HEX)
          .print('-')
          .print(gpsdata.stamp.time, ZHEX, 6)
          .print(' ')
        ;
        /* 位置情報が取得されたなら */
        if (gpsdata.update.coordinate) {
          /* Web地図表現に変換してプリント */
          Serial
            .print(gpsdata.coordinate.latitude / 6000000.0, 7)
            .print(',')
            .print(gpsdata.coordinate.longitude / 6000000.0, 7)
            .ln()
          ;
        }
        /* 位置情報なし */
        else {
          Serial.println(F("(no latlon)"));
        }
        return;
      }
    }
    /* 時刻/位置情報なし */
    Serial.println(F("(no time) (no latlon)"));
  }
}

具体的な用例は [M5_GPS_LatLonサンプル] が詳しい。

<GPS_RMC.h>

GPS_RMC_Classを定義する。

依存性:<bcddatetime.h>

struct gpsdata_t

NEMA解析結果を返す構造体定義。

gpsdata_t 説明 備考
.coordinate .latitude long 緯度 LSB:1/6000000.0度
.longitude long 経度 LSB:1/6000000.0度
.stamp .time bcdtime_t BCD時分秒 0x123456 等
.date bcddate_t BCD年月日 0x20221231 等
.update .coordinate bool 位置情報更新 更新で真
.stamp bool 時刻情報更新 更新で真

bool update (void* _buffer, size_t _limit)

NMEAテキストを含む_bufferを先頭から最大_limit量まで解析し、 チェックサムを計算/照合し、 $**RMC行の取得に成功したなら真を返す。

bool result = GPS_RMC.update(&buff, length);

gpsdata_t getData (void)

updateで取得された$**RMC行の解析結果をgpsdata_t構造体で返す。

gpsdata_t gpsdata = GPS_RMC.getData();

long latitude   = gpsdata.coordinate.latitude;
long longitude  = gpsdata.coordinate.longitude;
bcdtime_t time  = gpsdata.stamp.time;
bcddate_t date  = gpsdata.stamp.date;
bool coordinate = gpsdata.update.coordinate;
bool stamp      = gpsdata.update.stamp;

uint8_t calcCheckSum (void* _buffer, size_t _limit)

NMEA行を_bufferとその長さ_limitで与え、計算されたチェックサムを返す。 与える行は$で始まり*で終わる範囲である。

char nmea[] = "$PCAS03,0,0,0,0,1,0,0,0*";
uint8_t chksum = GPS_RMC.calcCheckSum(&nmea, sizeof(nmea-1)); // Return the 0x03

bool testCheckSum (void* _buffer, size_t _limit)

NMEA行を_bufferとその長さ_limitで与え、末尾のチェックサムを照合した結果を真理値で返す。

char nmea[] = "$PCAS03,0,0,0,0,1,0,0,0*03";
bool result = GPS_RMC.calcCheckSum(&nmea, sizeof(nmea-1)); // Return the true