ATOMIC GPS
GT-502MGG-N
AE-GYSFDMAXB
/*
Moo_M5GPS.ino
RMC センテンス自前パーステストプログラム
2024/04 : Ver.1.0 初版
検証 : Atom Lite + ATOMIC GPS
https://www.switch-science.com/products/6474
Atom Lite + GT-502MGG-N
https://akizukidenshi.com/catalog/g/g117980/
Atom Lite + AE-GYSFDMAXB
https://akizukidenshi.com/catalog/g/g109991/
2024/05 : Ver.1.1 Google Map 緯度、経度情報出力追加
Copyright 2024 Moo Soft(Yokoyama Akiyosi)
M5StackシリーズはモデルによってM5.begin()の引数が異なる
https://qiita.com/penguinprogrammer/items/5abf3e4f9583e41e9cfa
// M5Stack.h(M5Stack用)
void begin(bool LCDEnable = true, bool SDEnable = true, bool SerialEnable = true, bool I2CEnable = false);
// M5StickC.h(M5Stick-C用)
void begin(bool LCDEnable=true, bool PowerEnable=true, bool SerialEnable=true);
// M5Stack.h(ATOM用)
void begin(bool SerialEnable = true, bool I2CEnable = true, bool DisplayEnable = false);
モデル 使用ライブラリ 第1引数 第2引数 第3引数 第4引数
M5Stack Gray M5Stack LCD (省略時:初期化する) SD (省略時:初期化する) UART(省略時:初期化する) I2C (省略時:初期化しない)
M5Stick-C M5StickC LCD (省略時:初期化する) AXP (省略時:初期化する) UART(省略時:初期化する) なし
Atom Lite M5Atom UART (省略時:初期化する) I2C (省略時:初期化する) LED (省略時:初期化しない) なし
GPS 国土地理院 GNSS受信機の技術仕様調査
https://www.gsi.go.jp/common/000106157.pdf
NMEAセンテンス
https://ales-corp.co.jp/technical-information-nmea/
RMC センテンス:測位情報が最小限にまとめられたセンテンス
RMC センテンス例
$GNRMC,025345.00,A,3528.89979,N,13393.14644,E,0.730,,180424,,,A*61
0 = $GNRMC
1 = 025345.00
2 = A
3 = 3528.89979
4 = N
5 = 13393.14644
6 = E
7 = 0.730
8 =
9 = 180424
10 =
11 =
12 = ,A*61
十進法度単位
https://info.qchizu.xyz/knowledge/lat_lon/
「度分秒単位」で表現する場合時間の単位と同じで、分と秒は六十進法
33度35分29秒 130度23分56秒 = 33°35′29″ 130°23′56″
「十進法度単位」で表現する場合
33.5914度 130.3989度
33時間35分29秒を「時間」単位に変換する場合
33 + 35/60 + 29/3600 = 33.59138…時間
*/
#include "M5Atom.h"
#include <TimeLib.h> // https://github.com/PaulStoffregen/Time
// === グローバル変数、定数 定義開始 ======================= //
bool IS_DEBUG = true; // デバッグ出力フラグ
bool IS_MAP = true; // Google MAP 用データ出力フラグ
// === グローバル変数、定数 定義終了 ======================= //
// === 関数プロトタイプ宣言開始 =========================== //
String recvStr(); // GPS から RMC センテンスのデータ取得
void split(String, String *); // 文字列を分解して配列に格納
void makeGPS(String *); // GPS データ作成
String lat_calc(String); // Google Map 用緯度情報作成
String lon_calc(String); // Google Map 用経度情報作成
// === 関数プロトタイプ宣言終了 =========================== //
// ===================================================== //
// 初期設定
// ===================================================== //
void setup() {
M5.begin(false, false, true); // (UART, I2C, LED)
Serial.begin(9600);
while (!Serial);;
Serial1.begin(9600, SERIAL_8N1, 22, -1); // ATOMIC GPS デフォルト RX=GPIO9, TX=GPIO10
//Serial1.begin(9600, SERIAL_8N1, 32, -1); // Grove コネクタ
Serial.println(F("Moo_M5GPS.ino"));
} // void setup()
// ===================================================== //
// メインループ
// ===================================================== //
void loop() {
if (Serial1.available()) { // 受信していればデータ取得
String strbuf = recvStr(); // GPS から RMC センテンスのデータ取得
if (strbuf.indexOf("RMC", 0) > -1) { // RMC センテンスなら
Serial.println(strbuf);
String buf[13]; // RMC センテンスの項目数の配列確保
split(strbuf, buf); // 文字列を分解して配列に格納
makeGPS(buf); // GPS データ作成
if (IS_DEBUG) {
for (int ii = 0; ii < 13; ii++) { // 配列内容表示
Serial.print(ii, DEC);
Serial.print(" = ");
Serial.println(buf[ii]);
} // for
} // if
} // if
} // if
} // loop()
// ===================================================== //
// GPS から RMC センテンスのデータ取得
// 戻り値 : RMC センテンスの受信文字列
// ===================================================== //
String recvStr() {
String result = "";
while (true) {
result = Serial1.readStringUntil('\n'); // LF(改行、\n or 0x0A)迄読込
if (result.indexOf("RMC", 0) > -1) break;
if (IS_DEBUG) Serial.println(result);
} // while
return result;
} // void recvStr()
// ===================================================== //
// 文字列を分解して配列に格納
// target : 分解対象文字列
// *buf : 戻り値用の String 配列
// ===================================================== //
void split(String target, String *buf) {
unsigned int count = 0;
unsigned int aindex = 0;
unsigned int bindex = 0;
String tmp = "";
while (true) {
aindex = target.indexOf(',', bindex); // 要素の開始位置から,カンマの位置を検索
if (aindex != -1) { // カンマが見つかった場合
tmp = target.substring(bindex, aindex); // 文字列を切り出して
tmp.trim(); // 前後の空白削除
buf[count] = tmp; // 配列に格納
count++; // 配列インデックス更新
bindex = aindex + 1; // 要素の開始位置を更新
} else {
break;
} // if else
} // while
buf[count] = target.substring(target.lastIndexOf(",")); // 最後の項目
} // void split(String target, String *buf)
// ===================================================== //
// GPS データ作成
// *buf : GPS 情報の入った String 配列
//
// $GNRMC,002236.00,A,3530.89247,N,13403.14624,E,0.609,,180424,,,A*6A
// ===================================================== //
void makeGPS(String *buf) {
int y_ = buf[9].substring(4).toInt(); // 180424 から2桁の年取得(24)
bool isOK = buf[2].equalsIgnoreCase("A"); // データの有効性 V=無効、A=有効
isOK = isOK && (24 <= y_) && (y_ <= 50); // 年の範囲チェック
if (!isOK) {
Serial.print(F("データの有効性 V=無効、A=有効 : "));
Serial.println(buf[2]);
Serial.print(F("年(24~50) : "));
Serial.println(y_, DEC);
for (int ii = 0; ii < 13; ii++) { // 配列 "V" に初期化
buf[ii] = "V";
} // for
return;
} // if
tm t; // 日時構造体
t.tm_year = buf[9].substring(4).toInt() + 100; // 180424 年 1900年からの年数なので +100
t.tm_mon = buf[9].substring(2, 4).toInt() - 1; // 180424; 1月からの月数(0から11)
t.tm_mday = buf[9].substring(0, 2).toInt(); // 180424; 日(1から31)
t.tm_hour = buf[1].substring(0, 2).toInt() + 9; // 132236.00 時(0から23 JST = UTC + 9
t.tm_min = buf[1].substring(2, 4).toInt(); // 132236.00 分(0から59)
t.tm_sec = buf[1].substring(4, 6).toInt(); // 132236.00 秒(0から60、うるう秒を考慮)
time_t tim; // 日時
tim = mktime(&t); // 引数で渡した構造体が変更される
tm* ltim = localtime(&tim); // ローカル時間
Serial.println(F("-------------------------"));
char s[20];
sprintf(s, "%04d/%02d/%02d %02d:%02d:%02d",
ltim->tm_year + 1900, ltim->tm_mon + 1, ltim->tm_mday,
ltim->tm_hour, ltim->tm_min, ltim->tm_sec);
Serial.print("JST : ");
Serial.println(s);
Serial.println(F("-------------------------"));
Serial.print("緯度 : ");
Serial.print(buf[4]); // 10進数、dd度mm.mmmmmmm分で表わされた緯度
Serial.println(buf[3]); // N or S (例) 3530.8927
Serial.print("経度 : ");
Serial.print(buf[6]); // 10進数、ddd度mm.mmmmmmm分で表わされた経度
Serial.println(buf[5]); // E or W (例) 13403.1513
if (IS_MAP) {
String latstr = lat_calc(buf[3]);
String lonstr = lon_calc(buf[5]);
Serial.print(latstr);
Serial.print(", ");
Serial.println(lonstr);
} // if
Serial.println(F("-------------------------"));
} // void makeGPS(String *buf)
// ===================================================== //
// Google Map 用緯度情報作成
//
// 10進数、dd度mm.mmmmmmm分で表わされた緯度
// (例) 3530.8927
// 緯度の値は
// 度(dd) : 2桁の固定桁
// 分(mm) : 2桁の固定桁
// および '.' 以下の小数部(mmmmm 桁数可変)
// ===================================================== //
String lat_calc(String latstr) {
String result = "";
String _do = latstr.substring(0, 2); // 35
String fun = latstr.substring(2); // 30.8927
float _fun = fun.toFloat() / 60;
fun = String(_fun, DEC);
fun = fun.substring(fun.indexOf(".") + 1);
result = _do + "." + fun;
return result;
} // String lat_calc()
// ===================================================== //
// Google Map 用経度情報作成
//
// 10進数、ddd度mm.mmmmmmm分で表わされた経度
// (例) 13403.1513
// 経度の値は
// 度(ddd) : 3桁の固定桁
// 分(mm) : 2桁の固定桁
// および '.' 以下の小数部(mmmmm 桁数可変)
// ===================================================== //
String lon_calc(String lonstr) {
String result = "";
String _do = lonstr.substring(0, 3); // 134
String fun = lonstr.substring(3); // 03.1513
float _fun = fun.toFloat() / 60;
fun = String(_fun, DEC);
fun = fun.substring(fun.indexOf(".") + 1);
result = _do + "." + fun;
return result;
} // String lon_calc()
コメントを残す