GPSモジュール
秋月でアンテナ付キットを購入。(2022/8/20現在、在庫切れ)
Arduino
ログをPCで取得するならシリアルが2系統必要。
SoftwareSerialでもよいが、今回はSerial1のあるGR-CITRUSを使用。
Serial(USB)をPCとの通信、Serial1(TX:0, RX:1)をGPSモジュールとの通信に使用。
結線
GPSモジュール | GR-CITRUS | 備考 |
---|---|---|
5V | 5V | GR-CITRUSから給電する。ボタン電池は不使用。 |
GND | GND | |
RX | 0 | Serial1のTX。3.3Vレベルであることに注意(※) 今回は不使用。 |
TX | 1 | Serial1のRX。3.3Vレベルであることに注意(※) |
1PPS | 接続しない | 1秒周期のパルス出力。今回は不使用。 |
※ 5V系Arduinoの場合はレベル変換が必要。
LED・電池
モジュールに給電するとまず橙色LEDが弱く点灯する。しばらく待ってモジュールが衛星を捕捉すると橙色LEDが1秒周期で点滅するようになる。
バックアップ電池(CR2032)を付けておくと衛星情報などが保持されて、再起動時の測位開始にかかる時間を短縮できる。
スケッチ
#include <TinyGPS++.h> TinyGPSPlus gps; void setup() { Serial.begin(115200); Serial1.begin(9600); // 秋月のGPSモジュールはデフォルト9600ボー while (!Serial) { ; } } void loop() { while (Serial1.available() > 0){ char c = Serial1.read(); // Serial.print(c); // シリアル受信データを1文字づつ食わせる gps.encode(c); // 位置情報が更新されたか? if (gps.location.isUpdated()){ // 緯度・経度・標高を取得 Serial.print("LAT="); Serial.println(gps.location.lat(), 6); Serial.print("LONG="); Serial.println(gps.location.lng(), 6); Serial.print("ALT="); Serial.println(gps.altitude.meters()); } } }
isValid(), isUpdated(), age()
- isValid() : データが有効か?
- isUpdated():データが更新されたか? (変化したとは限らない)
- age():最後の更新からの経過時間 [msec]
取得できるデータ
// 位置 Serial.println(gps.location.lat(), 6); // 緯度[度] (double) Serial.println(gps.location.lng(), 6); // 経度[度] (double) Serial.print (gps.location.rawLat().negative ? "S" : "N"); // 南北 (bool) Serial.println(gps.location.rawLat().deg); // 整数部 (uint16_t) Serial.println(gps.location.rawLat().billionths);// 小数部(1/10億) (uint32_t) Serial.print (gps.location.rawLng().negative ? "W" : "E"); // 東西 (bool) Serial.println(gps.location.rawLng().deg); // 整数部 (uint16_t) Serial.println(gps.location.rawLng().billionths);// 小数部(1/10億) (uint32_t) // 日付 Serial.println(gps.date.value()); // 日付(DDMMYY) (uint32_t) Serial.println(gps.date.year()); // 年(西暦下2桁) (uint16_t) Serial.println(gps.date.month()); // 月(1-12) (uint8_t) Serial.println(gps.date.day()); // 日(1-31) (uint8_t) // 時刻 Serial.println(gps.time.value()); // 時刻(HHMMSSCC) (uint32_t) Serial.println(gps.time.hour()); // 時(0-23) (uint8_t) Serial.println(gps.time.minute()); // 分(0-59) (uint8_t) Serial.println(gps.time.second()); // 秒(0-59) (uint8_t) Serial.println(gps.time.centisecond()); // 1/100秒 (0-99) (uint8_t) // 速度 Serial.println(gps.speed.value()); // 速度[1/100ノット] (int32_t) Serial.println(gps.speed.knots()); // 速度[ノット] (double) Serial.println(gps.speed.mph()); // 速度[マイル/時] (double) Serial.println(gps.speed.mps()); // 速度[m/s] (double) Serial.println(gps.speed.kmph()); // 速度[km/h] (double) // 進路(方位) Serial.println(gps.course.value()); // 方位[1/100度] (int32_t) Serial.println(gps.course.deg()); // 方位[度] (double) // 標高 Serial.println(gps.altitude.value()); // 標高[cm] (int32_t) Serial.println(gps.altitude.meters()); // 標高[m] (double) Serial.println(gps.altitude.miles()); // 標高[マイル] (double) Serial.println(gps.altitude.kilometers()); // 標高[km] (double) Serial.println(gps.altitude.feet()); // 標高[フィート] (double) // 利用できる衛星の数 Serial.println(gps.satellites.value()); // (uint32_t) // HDOP(水平精度低下率) Serial.println(gps.hdop.value()); // (LSB=0.01 int32_t)
応用
NMEAの特定のフィールドのデータを抽出して取得することもできる。
だだし、数値であっても解釈されず文字列 (char*) として返す。
#include <TinyGPSPlus.h> TinyGPSPlus gps; // $GNGSA の 15~17個目フィールドを抽出するオブジェクト // ($GPGSA:GPSのみ, $GNGSA: GPS+GLONASS等) TinyGPSCustom pdop(gps, "GNGSA", 15); TinyGPSCustom hdop(gps, "GNGSA", 16); TinyGPSCustom vdop(gps, "GNGSA", 17); void setup() { Serial.begin(115200); Serial1.begin(9600); while (!Serial) { ; } } void loop() { while (Serial1.available() > 0) gps.encode(Serial1.read()); if (pdop.isUpdated() || hdop.isUpdated() || vdop.isUpdated()) { Serial.print(F(" PDOP=")); Serial.print(pdop.value()); Serial.print(F(" HDOP=")); Serial.print(hdop.value()); Serial.print(F(" VDOP=")); Serial.println(vdop.value()); } }
参考記事