Arduinoで遊ぶページ

Arduinoで遊んだ結果を残すページです。
garretlab
GPSセンサ

概要

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からデータがシリアルモニタに送信されます。シリアル入力から読み込んだデータをシリアルコンソールに出力しているだけです。

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に対応します。

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

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

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

$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マップに入力すると、現在の位置が表示されます。実際に、検索してみたところ、今度は、自宅が表示されました。

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;
}

バージョン

Arduino 0022/Arduino 1.0.1



メニューを表示するためにJavaScriptを有効にしてください。

Arduinoで遊ぶページ
Copyright © 2011 garretlab all rights reserved.
inserted by FC2 system