GPSセンサ
UNO R3

概要

GPSセンサを使った実験です。

GT-720FというGPSセンサモジュールを使います。古いセンサのようで、新しく入手するのは難しいかもしれません。

目的

GPSセンサがどういう情報を出力しているのかを調べます。

出力されたデータを、Googleマップに入力できるデータ形式に変換します。

データシート

GT-720Fのデータシートを参照して、どのようなものかを調べました。

概要

GT-720Fの仕様の概要は以下の通りです。

項目 内容
電源電圧(Vdd) 3.8~8V
CEP(平均誤差半径) 5m
出力データ GPGGA、GPGLL、GPGSA、GPGSV、GPRMC、GPVTG、GPZDA

GT-720Fは、6ピンのデバイスで各ピンの意味は以下の通りです。

ピン番号 内容
1 Ground
2 Power
3 Serial Data In 2(RS-232C レベル)
4 Serial Data Out 2(RS-232C レベル)
5 NC(実際はTTL In)
6 NC(実際はTTL Out)

5番ピンと6番ピンとはデータシート上はNCとなっていますが、Webページでいろいろ検索すると、TTLレベルの出力が出ているとのことです。TTLレベルが出力されていると、Arduinoに直接接続することができるので、今回は、こちらを使いました。

特殊なコネクタを使っているのが難点です。

実験

まずは、GT-720Fがどういうデータを出力しているのかを調べました。

以下のように接続します。電源を接続し、GT-720FのTTL出力をArduinoのデジタルの0番ピン(シリアル通信の受信)に接続するだけです。また、シリアルコンソールに文字を表示するため、USBケーブルでPCと接続します。

GT-720Fのピン番号 Arduinoのピン番号
1 GND
2 5V
3 接続しない
4 接続しない
5 接続しない
6 デジタル0(RX)

GT-720Fの出力を表示する

以下のスケッチを動かすと、GT-720Fからデータがシリアルモニタに送信されます。シリアル入力から読み込んだデータをシリアルコンソールに出力しているだけです。

1
2
3
4
5
6
7
8
9
void setup () {
  Serial.begin(9600);
}
 
void loop () {
  if (Serial.available()) {
    Serial.write(Serial.read());
  }
}

スケッチをアップロードするときは、Arduinoの0番ピンとGT-720Fとの接続を切っておく必要があります。デジタルピンの0番と1番とはPCとのシリアル通信にも利用しているためです(USB端子と共用しています)。接続したままだとスケッチのアップロードに失敗します(GT-720Fの電源を切断しておいてもいいかもしれませんが)。スケッチのアップロード完了後、Arduino0番ピンとGT-720Fの6番ピンとを接続します。

出力された情報を見ると、GPGGA、GPGSA、GPGSV、GPRMC、GPVTGの5種類は出力されていましたが、GPGLL、GPZDAの2種類は確認できませんでした。私の使い方の問題かもしれません。

GPRMCとGPGGAに経度と緯度の情報が含まれています。Googleマップにこの情報をそのまま入れてみたところ(Googleマップに、「緯度,経度」を入力すると、その緯度・経度の場所が表示されます。経度や緯度、コンマはすべて半角で入力してください。例えば、「51.475,0」と入れると、イギリスのグリニッジ公園が出てきます)、測定場所とは異なる場所が表示されました(海の上でした)。

誤差にしてはあまりにもひどいので、調べてみると、「分」の扱いがGT-720FとGoogleマップとで異なっていました。GT-720Fの出力は60進形式、Googleマップへの入力は、10進形式とのことでした。例えば、60進形式で30分が10進形式で0.5に対応します。

後でわかったことですが、Googleマップでも、60進形式を受け付けてくれます。なので、以下はあまり意味はありません。

60進法の数値をを10進法の数値に変換する

GT-720Fの出力を、Googleマップに入力できるよう変換するプログラムを作成しました。GT-720Fが出力するGPRMCを解析して、変換します。

GT-720FのGPRMCの出力例は、以下の通りです(緯度・経度はいい加減なものです)。

1
$GPRMC,225014.002,A,3500.0000,N,13900.0000,E,000.0,000.0,190811,,,D*6F

コンマ区切りになっていて、$GPRMCの次から、時刻(UTC)、状態(A=有効、V=警告)、緯度、北緯・南緯(北緯=N、南緯=S)、経度、東経・西経(東経=E、西経=W)、以下省略、となっています。また、改行コードは、CR+LFでした。

緯度・経度は、百の位以上が度、10の位以下が分を表します。GT-720Fが出力する数値を100で割った値が度、元の値から度を引いた値が60進形式の分です。60進形式で表されているGPSの出力をを10進形式に変換するには、度 + 分/60 を計算すればいいことになります(60分=1度なので)。

GT-720Fの出力を読み取り、緯度と経度とを出力する簡単なプログラムを作成しました。文字列の解析には、strtok()を使いましたが、フォーマットが明確なので、sscanf()でも問題ありません。南緯や西経には対応していません。対応させる場合は、それぞれ、-1をかければ大丈夫と思います。

このプログラムが出力するのは、(GT-720Fが出力した)時刻、緯度、経度 その後、10進変換した 「緯度, 経度」です。最後の、「緯度, 経度」をコピー・ペーストしてGoogleマップに入力すると、現在の位置が表示されます。実際に、検索してみたところ、今度は、自宅が表示されました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
void setup () {
  Serial.begin(9600);
}
 
void loop () {
  static char s[256];
  static int pos = 0;
   
  if (Serial.available()) {
      s[pos] = Serial.read();
      if (s[pos] == '\n') {
        s[pos - 1] = '\0'; // Escape '\r'
        analyze_data(s);
        pos = 0;
      } else {
        pos++;
      }
  }
}
 
// analyze GPS output.
void analyze_data(char *s) {
  char *type;
  char *time;
  char *latitude, *longitude;
  char *tmp;
   
  type = strtok(s, ",");
  if(strcmp(s, "$GPRMC") != 0) {
    return;
  }
 
  time = strtok(NULL, ",");
  tmp  = strtok(NULL, ",");
  latitude = strtok(NULL, ",");
  tmp = strtok(NULL, ",");
  longitude = strtok(NULL, ",");
 
  Serial.println(time);
  Serial.println(latitude);
  Serial.println(longitude);
  Serial.println();
   
  Serial.print(stod(latitude), 7);
  Serial.print(", ");
  Serial.println(stod(longitude), 7);
  Serial.println();
}
 
// Convert sexagesimal to decimal
float stod(char *s) {
  float f;
  float deg, min;
   
  f = atof(s);
 
  deg = (int)f / 100;
  min = f - deg * 100;
   
  return deg + min / 60;
  

バージョン

Hardware:Arduino UNO R3
Software:Arduino 0022/Arduino 1.0.1

最終更新日

November 1, 2022

inserted by FC2 system