$10 GPSモジュール

Aliexpressで売っていた送料込み約$10.5のGPSモジュールのテスト

販売店は多数あるがAliexpressは最良評価店=ほぼ最安店であることが多い
「gps module」で検索すれば直ぐにこれが見つかるはず
中国製品は淘汰が激しいためだと思うが意外と品数が少ない

・電源電圧は5V
 GPSモジュールは3.3V(データシート上は3.0V)だが基板上の電源ICで3.3Vを作り出している
 最近の電源ICはドロップアウト電圧が非常に低い(LDOと略される)のでたぶん3.3Vでも正常動作するはず
・通信はRS-232
 初期状態の通信速度は9600bps
 TXピンの出力3.3Vはarduinoの5V入力で問題なく動作する
・データーシートは NEO-6M-0-001 で検索して探す
・配線は
  arduino TX --(要電圧変換)--> 通信モジュール RX  GPSモジュールにコマンドを送らないのであれば配線不要
  arduino RX <-(電圧変換不要)-- 通信モジュール TX
  arduinoはプログラムの書き換えにRS-232を使っているのでGPSとの通信にはソフトウエアSerialを使う
・データはテキストで送られてくる
・データの書式は NMEAフォーマット
・1秒おきに5~10行程度のデータが送られてくる。行数は一定では無い
・インターフェースはRS-232以外にUSBやSPIも有るようだ。データシートをよく見ていないので詳細は不明
 パソコンで使うのであればUSBメモリー型の物が同価格帯(むしろ安い)で有るのでこれを使うべきでは無い
・基板上のLEDは電源を入れたときに一瞬だけ点灯。衛星を捕捉したときに点滅


2015-09-17

アンテナと基板は別体になっているが基板の裏にアンテナを半田付け出来るようになっている
基板左の穴はたぶんケーブルを通すための物
GPSの捕捉時間を短縮するための電池も乗っている。青い基板の右上にある

R0026860.jpg

配線は全部で4本。GPSモジュールにコマンドを送る必要性は低いので3本で殆どのことは出来る
ZIFソケット付きの変則arduinoを使用しているが普通のarduinoとほぼ同じ機能

R0026861.jpg
おくられてくるNMEAフォーマットのデータ
時刻と位置の取得ならこの中のごく一部のデータを切り出すだけで良い
0001  $GPRMC,101105.00,A,3552.52403,N,13917.10887,E,0.057,,170915,,,D*72
0002 $GPVTG,,T,,M,0.057,N,0.106,K,D*23
0003 $GPGGA,101105.00,3552.52403,N,13917.10887,E,2,10,08,105,,3.,,,00*1
0004 $PSAA3,2,5130,3,7,029201,,17,08,15*0
0005 $GGS,,11,0,1,6,3,0,7,0,2,6,418,3072401,775
0006 GPS,32,1136,28311,2,413,2,8,9,1,9,4,8,2*0
0007 $PGV3,,1,0,008,3424,1033504,10324
0008 GGL,55.543,,397188,,111500AD*2
0009 $GPRMC,101106.00,A,3552.52406,N,13917.10886,E,0.110,,170915,,,D*77
0010 $GPVTG,,T,,M,0.110,N,0.203,K,D*27
0011 $GPGGA,101106.00,3552.52406,N,13917.10886,E,2,10,08,103,,3.,M,00*0
0012 $PGAA,,0,5130,3,7,029201,,1790881560
0013 GPS,311,0,1,6,3,0,7,0,2,6,414,3,7,405,7*5
0014 $PS,32,1136,28311,2,21392,2,971,2,2,882*1
0015 $PGV3,,1,0,008,2,24810,3,04810,24
0016 GGL,55.546,,397108,E1016.0A,*5
0017 $GPRMC,101107.00,A,3552.52409,N,13917.10886,E,0.114,,170915,,,D*7D
0018 $GPVTG,,T,,M,0.114,N,0.210,K,D*21
0019 $GPGGA,101107.00,3552.52409,N,13917.10886,E,2,10,.8,8.9M387,,0005C
0020 GPS,A3,20,1,6,0075,2,0,5,,.7,.8,.5*0
0021 $GGV,,,1,26116,2056702,3062,1833072,01277
0022 GGV,,,1,1,5,3,3,5,824,3,0,829,0,92428,17A
0023 GPS,3311304,04324,4,703,5,4,703*1
0024 $PGL3525209N131.186,,11070,AD6B
0025 $GPRMC,101108.00,A,3552.52414,N,13917.10883,E,0.127,,170915,,,D*7B
0026 $GPVTG,,T,,M,0.127,N,0.235,K,D*26
0027 $GPGGA,101108.00,3552.52414,N,13917.10883,E,2,10,08,19.,,3.,M,00*B
0028 $PGAA,,2,5130,3,7,0,9201,,1790881.60
0029 GGS,,11,0,1,663,0,7,0,2,6,4,4,3,72401,774
0030 $PSV32,1136,28,0152,21392,2,9,2,2,4,8,2*8
0031 $PGV,,,1,0,008,2,24817,3504,10324
0032 GPL,35.544,,397.083E101800AD*D
0033 $GPRMC,101109.00,A,3552.52416,N,13917.10881,E,0.049,,170915,,,D*73
0034 $GPVTG,,T,,M,0.049,N,0.091,K,D*23
0035 $GPGGA,101109.00,3552.52416,N,13917.10881,E,2,10,0.818.,M3.7M,0005
0036 $GGA,,,0,5,306300,5,9,015,1.9,.8,.600
0037 GPS,3111026,16320,6,02230,2,483,0,405,7*3
0038 $PGV3,,1,36523,9,52821,9202,27212,2,882*7
0039 $GGS,,31,3,0,8,3,4,8,7,3,04810,241
0040 $PLL352541,,191.081E,019.0A,*C
0041 $GPRMC,101110.00,A,3552.52419,N,13917.10880,E,0.082,,170915,,,D*72
0042 $GPVTG,,T,,M,0.082,N,0.152,K,D*2A
0043 $GPGGA,101110.00,3552.52419,N,13917.10880,E,2,10,08,192,,8.,,00056
0044 $PSAA3,2051,0,3,7,0292,1,,17908,15*0
0045 $GGV,,,1,0,1,6,3,5,700,2,6,418,3072,012774
0046 GPS,32111,6,28281,2,413,0,8,9,2,9,428,3*3
0047 $PGV3,,1,04004,2424,10335,4,70324
0048 GGL,55.249N,397108,,11100,AD*A
0049 $GPRMC,101111.00,A,3552.52423,N,13917.10876,E,0.067,,170915,,,D*78
0050
行番号
解説
改行コードは0D+0Aと0Dだけの時がある。何か意味があるのかもしれない
#GPRMC、$GPGGAのように似通ったデータを含む物も有る
上のデータを受信するarduinoスケッチ
0001  #include "SoftwareSerial.h"
0002
0003 SoftwareSerial GPSSerial(10, 11);
0004
0005 void setup()
0006 {
0007 Serial.begin(57600);
0008 Serial.println("GPS TEST");
0009
0010 GPSSerial.begin(9600);
0011 }
0012
0013 void loop()
0014 {
0015 char chr;
0016
0017 if( GPSSerial.available() ) {
0018 chr = GPSSerial.read();
0019 Serial.write(chr);
0020 }
0021 }
行番号
解説
3行目
GPSモジュールとの通信は10,11番ピンを使っている

時刻の受信

gettime.png
時刻表示arduinoスケッチ
0001  #include "SoftwareSerial.h"
0002
0003 SoftwareSerial GPSSerial(10, 11);
0004
0005 byte index;
0006 char buf[200];
0007
0008 void clear_buf()
0009 {
0010 for( byte index = 0 ; index < 200 ; index++ ) {
0011 buf[index] = 0;
0012 }
0013 }
0014
0015 void setup()
0016 {
0017 Serial.begin(57600);
0018 Serial.println("GPS GET TIME");
0019
0020 clear_buf();
0021 index = 0;
0022 GPSSerial.begin(9600);
0023 }
0024
0025 void loop()
0026 {
0027 char chr;
0028 byte hour;
0029
0030 if( GPSSerial.available() ) {
0031 chr = GPSSerial.read();
0032 if( (chr == 0x0d) || (chr == 0x0a) ) {
0033 if( strncmp( buf, "$GPGGA", 6 ) == 0 ) {
0034 hour = (buf[7] - '0') * 10 + (buf[8] - '0') + 9;
0035 if( hour >= 24 ) {
0036 hour -= 24;
0037 }
0038 Serial.print( hour );
0039 Serial.write( ':' );
0040 Serial.write( buf[9] );
0041 Serial.write( buf[10] );
0042 Serial.write( ':' );
0043 Serial.write( buf[11] );
0044 Serial.write( buf[12] );
0045 Serial.println("");
0046 }
0047 clear_buf();
0048 index = 0;
0049 } else {
0050 buf[index] = chr;
0051 index++;
0052 }
0053 }
0054 }
0055
行番号
解説
3行目
GPSモジュールとの通信は10,11番ピンを使っている
34行目
日本時刻はJSTより9時間ずれる
スケッチ
ファイル ファイルタイプ 添付ファイルの解説
GPS.zip arduino 上の2つのスケッチ現物

2015-09-18

位置をシリアルモニターに出力するスケッチ。この書式の座標をGoogleマップの検索欄に入力すると現在地が表示される
0001  #include "SoftwareSerial.h"
0002
0003 #define rxPin 10
0004 #define txPin 11
0005
0006 SoftwareSerial GPSSerial(rxPin, txPin);
0007
0008 byte index;
0009 char buf[200];
0010 char *ptr_format_id;
0011 char *ptr_utc_time;
0012 char *ptr_latitude; // S <--> N
0013 char *ptr_latitude_sn;
0014 char *ptr_longitude; // E <--> W
0015 char *ptr_longitude_ew;
0016
0017 void clear_buf()
0018 {
0019 for( byte index = 0 ; index < 200 ; index++ ) {
0020 buf[index] = 0;
0021 }
0022 }
0023
0024 void setup()
0025 {
0026 Serial.begin(57600);
0027 Serial.println("GPS GET location");
0028
0029 clear_buf();
0030 index = 0;
0031 GPSSerial.begin(9600);
0032 }
0033
0034 void loop()
0035 {
0036 char chr;
0037
0038 double latitude;
0039 double longitude;
0040
0041 if( GPSSerial.available() ) {
0042 chr = GPSSerial.read();
0043 if( (chr == 0x0d) || (chr == 0x0a) ) {
0044 ptr_format_id = strtok( buf, "," );
0045 if( strncmp( ptr_format_id, "$GPGGA", 6 ) == 0 ) {
0046 ptr_utc_time = strtok( NULL, "," );
0047 ptr_latitude = strtok( NULL, "," );
0048 ptr_latitude_sn = strtok( NULL, "," );
0049 ptr_longitude = strtok( NULL, "," );
0050 ptr_longitude_ew = strtok( NULL, "," );
0051 latitude = atoi( ptr_latitude ) / 100;
0052 latitude += (atof(ptr_latitude) - latitude * 100) / 60;
0053 longitude = atoi( ptr_longitude ) / 100;
0054 longitude += (atof(ptr_longitude) - longitude * 100) / 60;
0055 Serial.print(ptr_latitude_sn);
0056 Serial.print(latitude,8);
0057 Serial.print(",");
0058 Serial.print(ptr_longitude_ew);
0059 Serial.print(longitude,8);
0060 Serial.println("");
0061 }
0062 clear_buf();
0063 index = 0;
0064 } else {
0065 buf[index] = chr;
0066 index++;
0067 }
0068 }
0069 }
0070
行番号
解説
51-54
NMEAフォーマットは度分秒方式なので、Googleマップと同じ10進小数点方式に変換

大体合っている

R0026864.jpg
スケッチ
ファイル ファイルタイプ 添付ファイルの解説
GPSne.zip arduino スケッチ現物

衛星を補足できているときだけ日時を出力するプログラム。GPSモジュールは電池でバックアップされているので衛星を補足できていなくても日時を送信してくる。長期放置した場合この日時が狂っている可能性があるので衛星を補足したときだけ日時を表示するようにする

gpsdatetime.png
衛星を補足できているときだけ日時を出力するプログラム
0001  #include "SoftwareSerial.h"
0002
0003 #define rxPin 10
0004 #define txPin 11
0005
0006 SoftwareSerial GPSSerial(rxPin, txPin);
0007
0008 byte index;
0009 char buf[200];
0010 char *ptr_format_id;
0011 char *ptr_utc_time;
0012 char *ptr_utc_date;
0013 char *ptr_dummy;
0014 char *ptr_mode;
0015
0016 void clear_buf()
0017 {
0018 for( byte index = 0 ; index < 200 ; index++ ) {
0019 buf[index] = 0;
0020 }
0021 }
0022
0023 char *strtok2( char *buf, const char delim )
0024 {
0025 static char *next;
0026 char *prev;
0027
0028 if( buf != NULL ) {
0029 next = buf;
0030 }
0031 prev = next;
0032 while( *next != '\0' ) {
0033 if( *next == delim ) {
0034 *next = '\0';
0035 next++;
0036 return prev;
0037 } else {
0038 next++;
0039 }
0040 }
0041
0042 return NULL;
0043 }
0044
0045 void setup()
0046 {
0047 Serial.begin(57600);
0048 Serial.println("GPS GET date time");
0049
0050 clear_buf();
0051 index = 0;
0052 GPSSerial.begin(9600);
0053 }
0054
0055 void loop()
0056 {
0057 char chr;
0058 int year;
0059 byte month;
0060 byte day;
0061 byte hour;
0062 byte min;
0063 byte sec;
0064
0065 if( GPSSerial.available() ) {
0066 chr = GPSSerial.read();
0067 if( (chr == 0x0d) || (chr == 0x0a) ) {
0068 buf[index] = 0x0;
0069 ptr_format_id = strtok2( buf, ',' );
0070 if( strncmp( ptr_format_id, "$GPRMC", 6 ) == 0 ) {
0071 ptr_utc_time = strtok2( NULL, ',' );
0072 ptr_dummy = strtok2( NULL, ',' );
0073 ptr_dummy = strtok2( NULL, ',' );
0074 ptr_dummy = strtok2( NULL, ',' );
0075 ptr_dummy = strtok2( NULL, ',' );
0076 ptr_dummy = strtok2( NULL, ',' );
0077 ptr_dummy = strtok2( NULL, ',' );
0078 ptr_dummy = strtok2( NULL, ',' );
0079 ptr_utc_date = strtok2( NULL, ',' );
0080 ptr_dummy = strtok2( NULL, ',' );
0081 ptr_dummy = strtok2( NULL, ',' );
0082 ptr_mode = strtok2( NULL, ',' );
0083
0084 if( *ptr_mode != 'N' ) {
0085 hour = (*(ptr_utc_time + 0) - '0') * 10 + (*(ptr_utc_time + 1) - '0') + 9;
0086 if( hour >= 24 ) {
0087 hour -= 24;
0088 }
0089 min = (*(ptr_utc_time + 2) - '0') * 10 + (*(ptr_utc_time + 3) - '0');
0090 sec = (*(ptr_utc_time + 4) - '0') * 10 + (*(ptr_utc_time + 5) - '0');
0091 day = (*(ptr_utc_date + 0) - '0') * 10 + (*(ptr_utc_date + 1) - '0');
0092 month = (*(ptr_utc_date + 2) - '0') * 10 + (*(ptr_utc_date + 3) - '0');
0093 year = 2000 + (*(ptr_utc_date + 4) - '0') * 10 + (*(ptr_utc_date + 4) - '0');
0094 Serial.print(year);
0095 Serial.print("/");
0096 Serial.print(month);
0097 Serial.print("/");
0098 Serial.print(day);
0099 Serial.print(" ");
0100 Serial.print(hour);
0101 Serial.print("/");
0102 Serial.print(min);
0103 Serial.print("/");
0104 Serial.print(sec);
0105 Serial.println("");
0106 }
0107 }
0108 clear_buf();
0109 index = 0;
0110 } else {
0111 buf[index] = chr;
0112 index++;
0113 }
0114 }
0115 }
0116
行番号
解説
23
strtok関数はデリミタが連続しているとスキップしてしまうので類似の関数を作った
84
衛星が補足できているとここがN以外になる
スケッチ
ファイル ファイルタイプ 添付ファイルの解説
GPSdatetime.zip arduino 上のスケッチ現物