GPSモジュールから時刻を取得
安価な(正確には安価になった)GPSモジュールを手に入れたので使えるか試してみた
仕様


データシートとか添付されていないので仕様はネットで調べた
名称:アンテナ付きVK2828U7G5 GPSモジュールTTL 1-10Hz FLASH飛行制御GPSモデル(Amazon)
コアチップ:u-blox(ユーブロックス)製の「UBX-G7020-KT」を搭載
対応コマンド:UBXプロトコル(u-blox社独自),および標準NMEA-0183コマンド(当然ながらMediaTek(MTK)社独自の「PMTKコマンド」は使用できない)
ケーブル(色に注意)
赤: 1 PPS Time standard pulse output
黒: 2 VCC Power supply input 3.3V-5V
黄: 3 TX UART/TTL Interface
緑: 4 RX UART/TTL Interface
青: 5 GND Ground
白: 6 EN 有効・無効(LOWでシャットダウン,HIGHまたはオープンで有効)
動作確認
GPSとは添付のケーブルで電源供給とデータはシリアル接続で良し
ESP32-C3を使い2つ目のシリアル(Serial1)でGPSと接続,arduinoIDEにてシリアル出力で確認

スケッチ
//GPSモジュール:VK2828U7G5
//
const int rxPin = 20;
const int txPin = 21;
void setup(void) {
Serial.begin(115200);
while(!Serial) delay(200);
Serial1.begin(9600, SERIAL_8N1, rxPin, txPin);
while(!Serial1) delay(200);
}
//GPSから送られてくるNMEA文字列をそのままシリアルモニタで表示
void loop(void) {
if(Serial1.available() > 0) { //If anything comes in Serial1 (pins 0 & 1)
Serial.write(Serial1.read()); //read it and send it out Serial (USB)
} else {
delay(10);
}
}
結果として座標や時間が標準形式(NMEA-0183)で表示される
出力されるテキストデータはセンテンス(データ種類)で分類されていて,デフォルトでは全て出力されるようになっているのでひっきりなしにデータが流れてくる
主なセンテンス(データ種類)の種類
- GGA: 時刻、緯度、経度、高度、受信衛星数などの詳細な測位情報
- RMC: 時刻、緯度、経度、速度、方位角などの最小限の航法情報
- GSV: 視界にいる衛星の数や、その電波強度(SNR)などの衛星情報
- GSA: 測位に使われた衛星の番号や、精度の指標(DOP値)
時刻のみ取得にセット
いまのところ実用になるのは時刻なので時刻だけ取得してみる
そのまま出力データから時刻だけを抽出する方法もあるが,必要ないデータは受ける必要もないので送られるセンテンスを選択する
このチップ(UBX-G7020-KT)はフラッシュメモリで設定情報を格納できるので,一度設定すれば良くu-blox専用の設定ツールを使うのが推奨されている
しかしツールのためだけに接続準備するのも面倒なのでUBXコマンド使用してスケッチで対応
//GPSモジュール:VK2828U7G5
// GPSを時計のみの出力にセット
//
const int rxPin = 20;
const int txPin = 21;
// u-blox UBXコマンド (各NMEA出力を無効/有効にするためのバイナリデータ)
const byte DISABLE_GGA[] PROGMEM = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x23};
const byte DISABLE_GLL[] PROGMEM = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A};
const byte DISABLE_GSA[] PROGMEM = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31};
const byte DISABLE_GSV[] PROGMEM = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38};
const byte DISABLE_VTG[] PROGMEM = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x46};
const byte ENABLE_RMC[] PROGMEM = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x4E};
void sendUBX(const byte *cmd, byte len) {
for(int i = 0; i < len; i++) {
Serial1.write(pgm_read_byte(cmd + i));
}
}
void setup(void) {
Serial.begin(115200);
while(!Serial) delay(200);
Serial1.begin(9600, SERIAL_8N1, rxPin, txPin);
while(!Serial1) delay(200);
//不要なセンテンスを無効化
sendUBX(DISABLE_GGA, sizeof(DISABLE_GGA)); delay(100);
sendUBX(DISABLE_GLL, sizeof(DISABLE_GLL)); delay(100);
sendUBX(DISABLE_GSA, sizeof(DISABLE_GSA)); delay(100);
sendUBX(DISABLE_GSV, sizeof(DISABLE_GSV)); delay(100);
sendUBX(DISABLE_VTG, sizeof(DISABLE_VTG)); delay(100);
//RMC(時刻含む)のみ有効化
sendUBX(ENABLE_RMC, sizeof(ENABLE_RMC)); delay(100);
Serial.println("GPS configuration complete. Only RMC will be output.");
}
//GPSから送られてくるNMEA文字列をそのままシリアルモニタで表示
void loop(void) {
if(Serial1.available() > 0) { //If anything comes in Serial1 (pins 0 & 1)
Serial.write(Serial1.read()); //read it and send it out Serial (USB)
} else {
delay(10);
}
}
リセット
工場出荷状態に戻す場合は以下(再起動はデータのみなので使用する場合は要編集)
//GPSモジュール:VK2828U7G5
// 工場出荷状態にリセット
const int rxPin = 20;
const int txPin = 21;
//工場出荷状態にリセット(設定の初期化)
// モジュールの内蔵フラッシュ(EEPROM/BBR)に書き込まれた
// カスタム設定(ボーレート変更、出力頻度など)を消去し、デフォルトに戻す
//
const byte FACTORY_RESET[] PROGMEM = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x17, 0x2F, 0xAE};
//再起動(コールドスタート)
// 設定の初期化ではなく、GPSの衛星補足データ(アルマナック・エフェメリス)を
// すべてクリアしてゼロから衛星を探し直す(コールドリセット)
//
const byte COLD_START[] PROGMEM = {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x5D};
void sendUBX(const byte *cmd, byte len) {
for(int i = 0; i < len; i++) {
Serial1.write(pgm_read_byte(cmd + i));
}
}
void setup(void) {
Serial.begin(115200);
while(!Serial) delay(200);
Serial1.begin(9600, SERIAL_8N1, rxPin, txPin);
while(!Serial1) delay(200);
//工場出荷状態にリセット(設定の初期化)
sendUBX(FACTORY_RESET, sizeof(FACTORY_RESET)); delay(100);
Serial.println("GPS configuration complete. Only RMC will be output.");
}
//GPSから送られてくるNMEA文字列をそのままシリアルモニタで表示
void loop(void) {
if(Serial1.available() > 0) { //If anything comes in Serial1 (pins 0 & 1)
Serial.write(Serial1.read()); //read it and send it out Serial (USB)
} else {
delay(10);
}
}
時計
時刻のみにして時計(シリアル出力まで)にする
NMEA-0183のエンコードには「TinyGPSPlus」を利用
スケッチ(SJIS,TAB4,LF)
GPSからpps信号を処理しようとして実験中止
表示部分などは今後の展開による


























