みちびき対応のGPS受信機(GYSFDMAXB)の使い方 [Arduino]
スマホなどでお馴染みのGPS(Global Positioning System)は「全地球測位システム」と呼ばれ、現在地の「緯度、経度」などの位置情報を取得する事が可能です。
次の動画は4衛星以上を追尾している「三次元測位中」(3D-Fix)の状態です。この赤いLEDが点滅している状態を15分以上維持することにより、安定した位置情報を得る事ができます。
[スケッチ1の実行例] - GPSのセンテンス(NMEAフォーマット)の表示
[スケッチ2の実行例] - 時刻、緯度、経度、海抜の表示
目次
1. 使用部品・材料
2. 配線図
3. スケッチ1(GPSセンテンスの表示)
4. スケッチ2(時刻、緯度、経度、海抜の表示)
5. 緯度経度について
6. Googleマップの座標フォーマット
7. Googleマップで2点間の距離を測定する
8. 日本の東西南北の緯度経度
9. NMEAフォーマット
1. 使用部品・材料
総額で約2,470円です。(Arduino本体の値段を除く)
部品/材料 | 値段 | 備考 |
---|---|---|
ブレッドボード | ¥270 | 秋月電子の通販コード(P-00315) |
GPS受信機キット 1PPS出力付き 「みちびき」対応 GYSFDMAXB | ¥2200 | 秋月電子の通販コード(K-09991) |
汎用小信号高速スイッチング・ダイオード 1N4148 100V200mA 1本 | 数円 | 秋月電子の通販コード(I-00941) |
カーボン抵抗器 | 数円 | 10kΩ(1個)を使用。 |
2. 配線図
今回はUART通信にSoftwareSerial(2ピン/3ピン)を使用しています。
GPS受信機の「GYSFDMAXB」(MT3339)の接続方法は秋月電子の取扱説明書の記載通りです。
GYSFDMAXBの入出力信号レベルが3.3Vですので、スイッチングダイオードを使用して、Arduinoからの5V送信(TX)を止めています。その代わりに3.3Vの電圧を10kΩを通してかけています。
3. スケッチ1 - GPSセンテンスの表示
シリアルモニターに「GPSのセンテンス」を表示します。
※シリアルモニターの通信速度は115200bpsにして下さい。
#include <SoftwareSerial.h> // rxPin = 2 txPin = 3 SoftwareSerial mySerial(2, 3); void setup() { mySerial.begin(9600); Serial.begin(115200); } void loop() { if (mySerial.available()) { Serial.write(mySerial.read()); } }
4. スケッチ2 - 時刻、緯度、経度、海抜の表示
シリアルモニターに現在の「時刻、緯度、経度、海抜」を表示します。
※シリアルモニターの通信速度は115200bpsにして下さい。
#include <SoftwareSerial.h> // rxPin = 2 txPin = 3 SoftwareSerial mySerial(2, 3); // NMEAの緯度経度を「度分秒」(DMS)の文字列に変換する String NMEA2DMS(float val) { int d = val / 100; int m = ((val / 100.0) - d) * 100.0; float s = ((((val / 100.0) - d) * 100.0) - m) * 60; return String(d) + "度" + String(m) + "分" + String(s, 1) + "秒"; } // (未使用)NMEAの緯度経度を「度分」(DM)の文字列に変換する String NMEA2DM(float val) { int d = val / 100; float m = ((val / 100.0) - d) * 100.0; return String(d) + "度" + String(m, 4) + "分"; } // NMEAの緯度経度を「度」(DD)の文字列に変換する String NMEA2DD(float val) { int d = val / 100; int m = (((val / 100.0) - d) * 100.0) / 60; float s = (((((val / 100.0) - d) * 100.0) - m) * 60) / (60 * 60); return String(d + m + s, 6); } // UTC時刻から日本の標準時刻に変換する(GMT+9:00) String UTC2GMT900(String str) { int hh = (str.substring(0,2).toInt()) + 9; if(hh > 24) hh = hh - 24; return String(hh,DEC) + ":" + str.substring(2,4) + ":" + str.substring(4,6); } void setup() { mySerial.begin(9600); Serial.begin(115200); } void loop() { // 1つのセンテンスを読み込む String line = mySerial.readStringUntil('\n'); if(line != ""){ int i, index = 0, len = line.length(); String str = ""; // StringListの生成(簡易) String list[30]; for (i = 0; i < 30; i++) { list[i] = ""; } // 「,」を区切り文字として文字列を配列にする for (i = 0; i < len; i++) { if (line[i] == ',') { list[index++] = str; str = ""; continue; } str += line[i]; } // $GPGGAセンテンスのみ読み込む if (list[0] == "$GPGGA") { // ステータス if(list[6] != "0"){ // 現在時刻 Serial.print(UTC2GMT900(list[1])); // 緯度 Serial.print(" 緯度:"); Serial.print(NMEA2DMS(list[2].toFloat())); Serial.print("("); Serial.print(NMEA2DD(list[2].toFloat())); Serial.print(")"); // 経度 Serial.print(" 経度:"); Serial.print(NMEA2DMS(list[4].toFloat())); Serial.print("("); Serial.print(NMEA2DD(list[4].toFloat())); Serial.print(")"); // 海抜 Serial.print(" 海抜:"); Serial.print(list[9]); list[10].toLowerCase(); Serial.print(list[10]); }else{ Serial.print("測位できませんでした。"); } Serial.println(""); } } }
GPSのセンテンスはCSV形式ですので「,」を区切り文字としてStringList(文字列リスト)を生成します。後は、StringListから緯度、経度などを取り出して、標準的な形式に変換しています。
5. 緯度経度について
緯度 | 赤道(0度)を基準として南(S)または北(N)へ90度を表す。 |
---|---|
経度 | イギリスのグリニッジ子午線(0度)を基準に東(E)または西(W)へ180度を表す。 |
緯度、経度は「度分秒」や「度」(10進数)などで位置を表します。
例えば、皇居(Googleマップ)の 緯度は35度41分06.6秒(35.685178)、経度は139度45分10.1秒(139.752804)となります。
※1度 = 60分 = 3600秒。1度の1/60が1分で1分の1/60が1秒となります。
6. Googleマップの座標フォーマット
Googleマップで「緯度, 経度」を入力して位置を検索するには、次の3つの書式を使用できます。※3つとも同じ座標となります。
緯度, 経度 | |
---|---|
度分秒(DMS) | 41°24'12.2"N, 2°10'26.5"E |
度分(DMM) | 41 24.2028, 2 10.4418 |
度(DD) | 41.40338, 2.17403 |
※「度 = °」「分 = '」「秒 = "」
7. Googleマップで2点間の距離を測定する
マップを右クリックで表示されるポップアップメニューで「距離を測定」で計測できます。2点間の距離を測る事ができますので、GPSにどれくらいの誤差があるかを確認できます。
8. 日本の東西南北の緯度経度
緯度 | 経度 | |
---|---|---|
最北端(北海道択捉島) | 45度33分26秒 | 148度45分08秒 |
最南端(東京都沖ノ鳥島) | 20度25分31秒 | 136度04分11秒 |
最東端(東京都南鳥島) | 24度16分59秒 | 153度59分11秒 |
最西端(沖縄県与那国島) | 24度26分58秒 | 122度56分01秒 |
※国土地理院が公表している日本の最東西南北の座標です。若干、座標がずれてる模様です。
9. NMEAフォーマット
UART通信でGPS受信機からマイコンなどへ送信されるデータはNMEA(NMEA0183)フォーマットです。このNMEAフォーマットは「$GPGGA」や「$GPRMC」などの1行のセンテンスの集合体です。
※センテンスは日本語では「文」という意味です。また、1センテンスは1行で行端は必ず改行コード(¥r¥n)となります。
センテンスの例
$GPGGA,135250.000,3541.123,N,13945.123,E,1,4,1.75,31.7,M,39.5,M,,*65 $GPGLL,3541.123,N,13945.123,E,135250.000,A,A*5D $GPGSA,A,3,07,29,193,06,,,,,,,,,1.98,1.75,0.92*3B $GPGSV,4,1,13,02,86,273,,193,83,346,26,05,56,315,16,50,48,170,*48 $GPGSV,4,2,13,06,40,135,30,13,40,216,16,30,34,112,,07,28,069,32*7A $GPGSV,4,3,13,29,21,309,28,20,14,284,,09,13,045,,19,04,175,*78 $GPGSV,4,4,13,15,04,229,*42 $GPRMC,135250.000,A,3541.123,N,13945.123,E,0.25,71.12,140617,,,A*5D $GPVTG,71.12,T,,M,0.25,N,0.47,K,A*0C $GPZDA,135250.000,14,06,2017,,*51
センテンスの一覧
次はGYSFDMAXBのデフォルトで出力されるセンテンスです。
$GPGGA | GPS位置情報 |
---|---|
$GPGLL | 地理的位置 - 緯度/経度 |
$GPGSA | DOP及びアクティブ衛星 ※DOP(Dilution Of Precision)はGPSの精度低下率です。 |
$GPGSV | 衛星情報 |
$GPRMC | 最小ナビゲーション情報(推奨?) |
$GPVTG | 針路と速度 |
$GPZDA | 時刻と日付(UTC) |
$GPGGA
GPS位置情報
番号 | 内容 |
---|---|
1 | 世界協定時(UTC)の時刻。hhmmss.sss形式 |
2 | 緯度。ddmm.mmmm形式 |
3 | 北緯(N) or 南緯(S) |
4 | 経度。dddmm.mmmm形式。 |
5 | 東経(E) or 西経(W) |
6 | GPS品質。 0:測位不可 1:GPS 2:DGPS |
7 | 使用衛星数。 |
8 | HDOP値(水平方向の精度) |
9 | アンテナの海抜高度 |
10 | アンテナの海抜高度の単位 |
11 | ジオイド高度 |
12 | ジオイド高度の単位 |
13 | DGPSデータの時間。 ※この項目は私の環境では常に空でした。 |
14 | DGPS基準局ID。 ※この項目は私の環境では存在しません。 |
15 | チェックサム |
$GPGLL
地理的位置 - 緯度/経度
番号 | 内容 |
---|---|
1 | 緯度。ddmm.mmmm形式 |
2 | 北緯(N) or 南緯(S) |
3 | 経度。dddmm.mmmm形式。 |
4 | 東経(E) or 西経(W) |
5 | 世界協定時(UTC)の時刻。hhmmss.sss形式 |
6 | ステータス。 A:データ有効 V:データ無効 |
7 | モード。 A:単独測位 D:DGPS N:データ無効 |
8 | チェックサム |
※私の環境では7と8の間に「,」がなく繋がっていました。
$GPGSA
DOP及びアクティブ衛星
番号 | 内容 |
---|---|
1 | 2D/3D切り替えモード。 M:手動 A:自動 |
2 | 測位モード。 1:測位なし 2:2D 3:3D |
3-14 | 使用している衛星番号。 ※最大12個の衛星が出力されます。ない場合は空です。 |
15 | PDOP値(位置精度) |
16 | HDOP値(水平精度) |
17 | VDOP値(垂直精度) |
18 | チェックサム |
※私の環境では17と18の間に「,」がなく繋がっていました。
GPGSV
衛星情報
番号 | 内容 |
---|---|
1 | このGPGSVセンテンスの総数。 |
2 | このGPGSVセンテンスの番号。 |
3 | 現在位置から受信可能な衛星数。 |
4 | 1個目の衛星番号。 ※みちびきは「193」。 ※ひまわり6号は「129」(42)。 ※ひまわり7号は「137」(50)。 |
5 | 1個目の衛星仰角。00から99度 |
6 | 1個目の衛星方位角。000から359度 |
7 | 1個目の衛星のSNR in dB。00から99dBHz |
8-11 | 2個目の衛星(4-7と同じ項目) |
12-15 | 3個目の衛星(4-7と同じ項目) |
16-19 | 4個目の衛星(4-7と同じ項目) |
20 | チェックサム |
※初期時などは一部項目が省略されるようです。(「,」も省略)
$GPRMC
最小ナビゲーション情報(推奨?)
番号 | 内容 |
---|---|
1 | 世界協定時(UTC)の時刻。hhmmss.sss形式 |
2 | ステータス。 A:データ有効 V:データ無効 |
3 | 緯度。ddmm.mmmm形式 |
4 | 北緯(N) or 南緯(S) |
5 | 経度。dddmm.mmmm形式。 |
6 | 東経(E) or 西経(W) |
7 | 地表の移動速度(ノット)。000.0から999.9ノット ※1ノット=1852m/h |
8 | 真方位(真北は0度)。000.0~359.9度 |
9 | 世界協定時(UTC)の日付。ddmmyy形式 |
10 | 磁気偏差 ※この項目は私の環境では常に空でした。 |
11 | 磁気偏差方向 ※この項目は私の環境では常に空でした。 |
12 | モード。 A:単独測位 D:DGPS N:データ無効 |
13 | チェックサム |
※私の環境では12と13の間に「,」がなく繋がっていました。
$GPVTG
針路と速度
番号 | 内容 |
---|---|
1 | 真方位(真北は0度)。000.0~359.9度 |
2 | 常にT |
3 | 磁気方位(磁北は0度)。000.0~359.9度 |
4 | 常にM |
5 | 地表の移動速度(ノット)。000.0から999.9ノット ※1ノット=1852m/h |
6 | 常にN |
7 | 地表の移動速度(km/h)。 |
8 | 常にK |
9 | モード。 A:単独測位 D:DGPS N:データ無効 |
10 | チェックサム |
※私の環境では9と10の間に「,」がなく繋がっていました。
$GPZDA
時刻と日付(UTC)
番号 | 内容 |
---|---|
1 | 時刻。hhmmss.sss形式 |
2 | 日。dd形式 |
3 | 月。mm形式 |
4 | 年。yyyy形式 |
5 | ??? ※この項目は私の環境では常に空でした。 |
6 | チェックサム |
※この時刻、日付は世界協定時(UTC)です。
最後に
今回は「海抜」が含まれる$GPGGAを使用しました。各フォーマットの簡易的な解説を記載しましたので色々と試してみると良いと思います。
測位の精度に関しては屋内(2F)でしか観測していませんが、誤差は3m-5m程度のようです。屋外の場合はもう少し精度が良いと思います。
掲示板
ArduinoやRaspberry Piなどの電子工作の掲示板を作成しました。質問やわからない事は電子工作 (Arduino・ラズパイ等)でユーザー同士で情報を共有して下さい。