아두이노2016. 5. 12. 08:00

아두이노에 GPS 모듈을 연결하면 자신의 현재위치 등의 정보를 알 수 있습니다. GPS 는 Global Positioning System 의 약자로서 미국 국방부에서 띄운 24개 이상의 위성에서 제공 해주는 신호를 이용하여 벡터방식으로 현재의 위도와 경도를 알 수 있도록 하는 시스템 입니다. 보통 GPS 신호는 실내에서는 잡기 힘들며 하늘이 보이는 야외로 나가야 잡을 수 있습니다.  그리고 3개 이상의 위성의 신호가 잡혀야 벡터방식으로 현재의 위치를 구할 수 있습니다.  많은 위성이 일정한 간격으로 지구전체를 돌고 있으므로 지구상 어느곳 에서든지 항상 3개 이상의 GPS 신호를 잡을 수 있습니다. 고로 자동차의 네비게이션, 조난 구조장치, 선박의 항법장치, 항공기 자동 조종장치 등 수 많은 산업에 쓰이고 있습니다. 이런 GPS 를 이용할 수 있는 모듈을 아두이노에 활용하여 보도록 하겠습니다.


전세계를 동시에 Cover 하고 있는 GPS 위성들 (어떠한 지역에서도 6 개 이상의 위성이 항상 신호를 보내주고 있습니다.)



GPS 모듈의 모습입니다. 왼쪽이 GPS 모듈이고 오른쪽은 안테나 입니다.


GPS 모듈의 이름은 GY-NEO6MV2 입니다. 메인칩은 UBlox 사의 NEO-6M-0-001 입니다. 기본적인 스펙은 다음과 같습니다.


■ 데이터시트 :

NEO-6.pdf


 

GPS 모듈에는 PIN 이 없습니다. 그래서 아두이노 와의 연결을 위해서는 납땜을 해야 합니다. 4개의 암/수 케이블의 암 부분을 잘라내고 GPS 모듈에 납땜을 하려고 합니다.


모듈에는 4개의 단자가 있습니다. 전원공급을 위한 VCC (3.3V 이나 5V 모두 연결 가능) , GND , RX , TX 가 있습니다. RX 와 TX 로 시리얼통신을 통해서 신호를 주고 받게 됩니다. 4개의 선을 납땜해 주었습니다.


모듈에 안테나를 연결하고 반대쪽 숫놈 단자를 아두이노에 연결해 주었습니다. 안테나는 꼽을 수 있도록 커넥터가 마련되어 있어서 그냥 꼽으면 됩니다.  아두이노와의 연결은 다음과 같이 해 주었습니다.


GPS 모듈

아두이노

VCC

 5V

GND

GND

RX

D5

TX

D6



밖으로 나가야 GPS 신호를 잡을 수 있으므로 노트북과 모듈, 아두이노를 챙겨서 의왕시에 있는 최근에 개장한 왕송호수공원에 나가 보았습니다. 늦봄의 정취가 참 아름답습니다. ^^


적당한 벤치에 앉아 노트북을 펼치고 GPS 모듈이 연결된 아두이노를 연결하고 준비한 소스를 업로드 합니다. 


소스 1

이 소스는 GPS 가 잘 잡히는지 테스트용 입니다. GPS 모듈에서 보내주는 내용을 그냥 찍어보는 용도 입니다. 그래도 들어 있을 정보는 모두 들어 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <SoftwareSerial.h>
 
SoftwareSerial gpsSerial(6,5);
 
void setup() {
  Serial.begin(9600);
  Serial.println("Start GPS... ");
  gpsSerial.begin(9600);
}
 
void loop() {
  if(gpsSerial.available())
  {
    Serial.write(gpsSerial.read());
  }
}
cs


시리얼 모니터에 다음과 같이 데이터가 뜹니다. 계속 뜹니다.


1
2
3
4
5
6
7
8
9
$GPRMC,082608.00,A,3730.67773,N,12694.42632,E,0.048,,110516,,,D*78
$GPVTG,,T,,M,0.048,N,0.089,K,D*2B
$GPGGA,082608.00,3730.67773,N,12694.42632,E,2,08,1.54,49.8,M,18.5,M,,0000*6D
$GPGSA,A,3,08,42,01,07,11,16,50,10,,,,,2.95,1.54,2.51*01
$GPGSV,3,1,09,01,44,188,40,07,57,267,41,08,64,024,45,10,12,063,36*7A
$GPGSV,3,2,09,11,66,211,45,16,23,108,34,27,,,28,42,43,152,37*46
$GPGSV,3,3,09,50,43,152,38*4F
$GPGLL,3730.67773,N,12694.42632,E,082608.00,A,D*6F
 
cs


무언가 알 수 없는 데이터가 계속 0.5초 간격으로 시리얼 모니터에 표시가 되는데...  이건 NMEA 이라고 부르는 GPS 규약에 의한 프로토콜 이라고 합니다. 미국의 The National Marine Electronics Association 이라는 기관에서 정한 프로토콜 이라고 하는데 자세한 내용은 아래의 링크에서 볼 수 있습니다. 


■ NMEA 자세히 알아보기 : http://www.gpsinformation.org/dale/nmea.htm


NMEA에 대해서는 간략히 정리된 표를 하나 참고삼아 가져와 보겠습니다.


NameGarminMagellanLowranceSiRFNotes:
GPAPBNYYNAuto Pilot B
GPBODYNNNbearing, origin to destination - earlier G-12's do not transmit this
GPGGAYYYYfix data
GPGLLYYYYLat/Lon data - earlier G-12's do not transmit this
GPGSAYYYYoverall satellite reception data, missing on some Garmin models
GPGSVYYYYdetailed satellite data, missing on some Garmin models
GPRMBYYYNminimum recommended data when following a route
GPRMCYYYYminimum recommended data
GPRTEYUUNroute data, only when there is an active route. (this is sometimes bidirectional)
GPWPLYYUNwaypoint data, only when there is an active route (this is sometimes bidirectional)

▲ NMEA 2.0 프로토콜


위의 표를 보니 제가 알고싶어하는 데이터는 현재의 위도와 경도 데이터 입니다. 즉 GPGLL 에 있는 값인것 같습니다. 위도와 경도로 보이는 데이터가 여러군데에 보이는데 확실한 차이는 잘 모르겠습니다. 혹시 이 글을 보시는 분들 중에 차이점 아시는 분은 댓글로 알려주시면 감사하겠습니다. GPGGA 가 Fix Data 인것 보면 더 정확한 값인것 같기도 하구요. 아무튼 GPGLL 에 들어있는 위도와 경도값으로 보이는 3730.67773,N,12694.42632,E 라는 값을 그대로 구글맵에서 검색해 보았습니다. 찾을 수 없다고 나옵니다. 위도와 경도값은 맞는데 소숫점을 우리가 알고 있는 위도와 경도 단위로 바꿔 보았습니다. 37.3067773, 126.9442632 로 수정해서 검색해 보았습니다.


이제야 제대로 나옵니다. 제가 앉아있던 벤치가 있던 자리가 정확히 맞습니다. 뭐 스마트폰 GPS로도 얼마든지 알 수 있는 기능이지만 GPS 의 RAW 데이터를 분석해서 현재 위치를 알아보니 뭔가 신기하기도 하고 그렇습니다.


하지만 위의 NMEA 데이터를 보시면 알겠지만 일반인이 알아보기에 굉장히 어렵습니다. 이를 Parsing 해야 데이터로서 가치가 더욱 높아질 것 같습니다.




소스 2

인터넷을 뒤져보니 TinyGPS 라는 라이브러리가 나옵니다. GPS RAW 데이터를 손쉽게 Parsing 해서 활용할 수 있도록 하는 라이브러리 입니다. 이를 사용해 보겠습니다.


■ TinyGPS 라이브러리

https://github.com/mikalhart/TinyGPS

TinyGPS-master.zip


위에서 다운로드 받은 라이브러리를 설치하고 아래의 예제 소스를 실행해 보았습니다. 실행 후 15분 정도를 걸으면서 GPS 로그를 10초 마다 기록해 보았습니다.


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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
 
 
#include <SoftwareSerial.h>
#include <TinyGPS.h>
 
// Define which pins you will use on the Arduino to communicate with your 
// GPS. In this case, the GPS module's TX pin will connect to the 
// Arduino's RXPIN which is pin 3.
#define RXPIN 6
#define TXPIN 5
//Set this value equal to the baud rate of your GPS
#define GPSBAUD 9600
 
// Create an instance of the TinyGPS object
TinyGPS gps;
// Initialize the NewSoftSerial library to the pins you defined above
SoftwareSerial uart_gps(RXPIN, TXPIN);
 
// This is where you declare prototypes for the functions that will be 
// using the TinyGPS library.
void getgps(TinyGPS &gps);
 
// In the setup function, you need to initialize two serial ports; the 
// standard hardware serial port (Serial()) to communicate with your 
// terminal program an another serial port (NewSoftSerial()) for your 
// GPS.
void setup()
{
  // This is the serial rate for your terminal program. It must be this 
  // fast because we need to print everything before a new sentence 
  // comes in. If you slow it down, the messages might not be valid and 
  // you will likely get checksum errors.
  Serial.begin(9600);
  //Sets baud rate of your GPS
  uart_gps.begin(GPSBAUD);
  
  Serial.println("");
  Serial.println("GPS Shield QuickStart Example Sketch v12");
  Serial.println("       ...waiting for lock...           ");
  Serial.println("");
}
 
// This is the main loop of the code. All it does is check for data on 
// the RX pin of the ardiuno, makes sure the data is valid NMEA sentences, 
// then jumps to the getgps() function.
void loop()
{
  while(uart_gps.available())     // While there is data on the RX pin...
  {
      int c = uart_gps.read();    // load the data into a variable...
      if(gps.encode(c))      // if there is a new valid sentence...
      {
        getgps(gps);         // then grab the data.
      }   
  }
}
 
// The getgps function will get and print the values we want.
void getgps(TinyGPS &gps)
{
  // To get all of the data into varialbes that you can use in your code, 
  // all you need to do is define variables and query the object for the 
  // data. To see the complete list of functions see keywords.txt file in 
  // the TinyGPS and NewSoftSerial libs.
  
  // Define the variables that will be used
  float latitude, longitude;
  // Then call this function
  gps.f_get_position(&latitude, &longitude);
  // You can now print variables latitude and longitude
  Serial.print("Lat/Long: "); 
  Serial.print(latitude,5); 
  Serial.print(", "); 
  Serial.println(longitude,5);
  
  // Same goes for date and time
  int year;
  byte month, day, hour, minute, second, hundredths;
  gps.crack_datetime(&year,&month,&day,&hour,&minute,&second,&hundredths);
  // Print data and time
  Serial.print("Date: "); Serial.print(month, DEC); Serial.print("/"); 
  Serial.print(day, DEC); Serial.print("/"); Serial.print(year);
  Serial.print("  Time: "); Serial.print(hour, DEC); Serial.print(":"); 
  Serial.print(minute, DEC); Serial.print(":"); Serial.print(second, DEC); 
  Serial.print("."); Serial.println(hundredths, DEC);
  //Since month, day, hour, minute, second, and hundr
  
  // Here you can print the altitude and course values directly since 
  // there is only one value for the function
  Serial.print("Altitude (meters): "); Serial.println(gps.f_altitude());  
  // Same goes for course
  Serial.print("Course (degrees): "); Serial.println(gps.f_course()); 
  // And same goes for speed
  Serial.print("Speed(kmph): "); Serial.println(gps.f_speed_kmph());
  Serial.println();
  
  // Here you can print statistics on the sentences.
  unsigned long chars;
  unsigned short sentences, failed_checksum;
  gps.stats(&chars, &sentences, &failed_checksum);
  //Serial.print("Failed Checksums: ");Serial.print(failed_checksum);
  //Serial.println(); Serial.println();
  delay(10000);
}
cs


위의 소스에 자세하게 영어로 주석이 쓰여 있으니 참고하시면 되겠습니다. 사실 자세히 보면 주석만 많지 별거 없는 소스 입니다. 맨 아래 delay 를 빼버리면 GPS 에서 주는대로 데이터를 계속 받습니다.


1
2
3
4
5
6
Lat/Long: 37.30678, 126.94424
Date: 5/11/2016  Time: 8:41:30.0
Altitude (meters): 1000000.00
Course (degrees): 0.00
Speed(kmph): 0.09
 
cs


로그는 위와 같이 찍힙니다. 위의 RAW 데이터 보다 훨씬 보기가 쉽습니다. 일단 첫째줄에 위도 경도가 나오고 날짜, 시간, 고도(이건 오류인듯 합니다. 계속 저렇게 나오네요.), 진행방향, 움직이는 속도가 찍힙니다.


모든 데이터가 보고 싶은 분들은 아래 파일을 다운로드 받으세요.

move_gps_1.txt


이 파일을 GPS 로그 파일인 gpx 파일로 변환해서 구글어스에서 불러와 보았습니다. gpx 파일로의 변환은 Notepad++ 의 매크로 기능을 이용하니 간단하게 되네요. 어차피 gpx 파일이 xml 형식의 파일이기 때문에 형식만 맞춰서 파일은 만들어주면 됩니다. 나중에 GPS Logger 도 만들어볼 생각인데 그 때는 gpx 파일형식으로 바로 저장하도록 만들어야겠죠. 제가 만든 gpx 파일은 아래 파일을 다운로드 받아 보시면 됩니다.

move_gps.gpx


gpx 파일을 구글어스를 실행하고 열기->gpx 파일을 선택해서 열어주시면 다음과 같이 움직인 GPS 로그기록을 볼 수 있습니다.


파란색으로 제가 움직인 구간이 표시 됩니다. 15분 동안 꽤 많이 걸었네요.


이상 몸으로 체험해본 아두이노 GPS 모듈 사용기 였습니다. 


다음 계획은 GPS 로그 기록을 SD카드 저장 모듈을 통해서 마이크로SD 카드에 저장해 보는 것 입니다. 그렇게 하면 첩보영화에서 가끔 나오는 차량에 자석으로 붙이는 위치 추적기? 비슷한 것을 만들어 볼 수 있을 것입니다.


미드 브레이킹 배드에서 나왔던 GPS 추적기

반응형
Posted by 대네브 (deneb)

댓글을 달아 주세요

  1. 이전 댓글 더보기
  2. 꾸야

    gps값이 자꾸 ,,,99 99 99 이런값이뜨는데 왜그런거죠??

    2017.03.18 11:01 [ ADDR : EDIT/ DEL : REPLY ]
    • 아마도 gps 신호를 못 잡아서 그런거 아닐까요?
      실내에서는 안잡히고
      반드시 야외로 나가서야 잡힙니다.
      나가기 좀 그렇다면
      최대한 창가쪽에 모듈을 놓고 테스트 해 보세요.
      그래도 확실한건 나가서 하는게 확실하죠

      2017.03.20 10:06 신고 [ ADDR : EDIT/ DEL ]
  3. 궁금해요 ㅜㅜ

    이 gps 모듈을 통하여 무선 통신을 하게할 수 있을까요??

    2017.04.11 15:32 [ ADDR : EDIT/ DEL : REPLY ]
  4. 프로그래밍새싹

    혹시 gps 모듈로 고도나 속도도 알 수 있을까요????

    2017.04.14 15:33 [ ADDR : EDIT/ DEL : REPLY ]
    • 좌표를 현재의 지도 데이터와 대조하면 고도를 알 수 있죠.
      속도는 일정시간의 이동거리를 gps로 구할 수 있으니 당연히 구할 수 있어요.

      2017.04.15 12:27 신고 [ ADDR : EDIT/ DEL ]
  5. 프로그래밍새싹

    제품부터 선 꼽는 곳, 코드까지 다 그대로 했는데 작동이 되질 않습니다 ㅠㅠ 뭐가 문제일까요....

    2017.04.26 16:10 [ ADDR : EDIT/ DEL : REPLY ]
  6. Gpsneom8

    혹시 gps센서중 neo m8 모델도 tinygps 라이브러리로 파싱이 되는지 알수있을까요..?

    2017.07.11 12:07 [ ADDR : EDIT/ DEL : REPLY ]
  7. Gpsneom8

    블로그 참조해서 무사히 파싱 성공했습니다! 추가 질문이 있는데요, 혹시 gps에서 계산되는 속도 값이 위도경도에 의한 속도 말고, 고도에 의한 속도도 계산되서 나오는지 혹시 아시나요?

    2017.07.14 20:32 [ ADDR : EDIT/ DEL : REPLY ]
    • gps는 위도 경도 2차원 데이터인데
      고도까지 측정이 될까요?
      아 물론 지도 데이터와 위경도 데이터가 결합되면 고도도 구할 수는 있습니다

      2017.07.16 04:41 신고 [ ADDR : EDIT/ DEL ]
  8. 초보자

    도움되는 글이었습니다.
    두번째 소스를 컴파일했을 때 exit status 1 이렇게 오류가 뜨는데 혹시 원인 아시나요?

    2017.09.20 22:15 [ ADDR : EDIT/ DEL : REPLY ]
  9. 초보자

    아하 라이브러리 때문인거 같네요.. 컴파일은 제대로 됬는데 업로드 했을때 시리얼 모니터에는 외계어만 찍히네요..ㅜ

    2017.09.21 00:05 [ ADDR : EDIT/ DEL : REPLY ]
  10. 간절

    txt 파일을 gpx 파일로 변환 하는데 어려워서 그런데 자세히 설명 부탁드릴 수 있을까요?

    2017.11.19 14:40 [ ADDR : EDIT/ DEL : REPLY ]
    • 매크로는 단순반복 작업을 도와주는 기능 입니다. notepad++ 은 http://demun.tistory.com/2135 여기를 참고해 주세요.

      2017.11.19 14:46 신고 [ ADDR : EDIT/ DEL ]
  11. ??

    코드는 rx가 6인데 표에는 5라고 되어있네요 어떻게 해야 되나요?

    2018.08.10 15:15 [ ADDR : EDIT/ DEL : REPLY ]
  12. gpx파일로 바꾸는 방법을 자세히 알고싶습니다

    2018.08.15 01:24 [ ADDR : EDIT/ DEL : REPLY ]
    • 윗댓글에 있었네요

      2018.08.15 01:25 [ ADDR : EDIT/ DEL ]
  13. 두듀

    시리얼 모니터에 뜨는 위경도 값을 블루투스를 이용해서 어플로 보낼수 잇을까요 ??

    2018.09.28 23:16 [ ADDR : EDIT/ DEL : REPLY ]
  14. 초보자

    GPS Shield QuickStart Example Sketch v12
    ...waiting for lock...


    이상태로 변화가 없는데 왜그럴까요...

    2019.10.26 18:54 [ ADDR : EDIT/ DEL : REPLY ]
  15. 아두이노초보자

    안녕하세요! 학교 과제로 저 코딩을 이용하다가 의문점이 생겨서 댓글 남겨보아요...
    void loop안에 getgps(gps); 가 있는데 이것은 void getgps(TinyGPS &gps) 에 맞춘건가요? 똑같이 왼쪽에는 getgps가 존재하고 괄호() 안에는 gps 가있어서요 이렇게 맞춰야하나 궁금점이 생겼습니다.

    2019.11.11 17:54 [ ADDR : EDIT/ DEL : REPLY ]
    • 아두이노초급

      저도 모르겠습니다 구글링 해 보시길

      2020.01.11 10:55 [ ADDR : EDIT/ DEL ]
  16. 촙자

    (gps.encode(c) 코드가 안먹히는데 c를 인식을 못하는건지 encode가 안먹히는데 수정할게있나요?

    2020.03.02 11:07 [ ADDR : EDIT/ DEL : REPLY ]
  17. 다두이노사이트에서 산 아두이노와 위에님이사신 똑같은 gps모듈사서 노트북연결한후 밖에서 소스1을 실행해봤는데 아무것도 안나오는데 어떻해야할까요ㅜㅡㅜ 조언좀부탁드립니다

    2020.04.29 15:36 [ ADDR : EDIT/ DEL : REPLY ]
    • 아두이노

      Start gps라는 문구도안나와요ㅜㅡㅜ

      2020.04.29 19:32 [ ADDR : EDIT/ DEL ]
    • 그 문구도 안나온다는건 아예 아두이노 개발환경 자체가 잘못된겁니다 처음부터 차근차근 살펴보시길

      2020.04.29 19:40 신고 [ ADDR : EDIT/ DEL ]
    • 아두이노

      arduino micro pro에 arduino leonardo보드연결해서 GY-neo06mv2연결했는데 깜박이는거나 다른 코드들은 되는데 gps 연결하는것만안되요 ㅠㅠ pin도 인터넷으로 찾아보니까 1(tx), 0(rx)로 되있어서 연결도 잘한것 같은대 더이상 어떤게 문제인지 모르겠어요 ㅠㅠ

      2020.05.07 20:09 [ ADDR : EDIT/ DEL ]
  18. teaung0217

    이야... 며칠 묵은 때가 여기서 해결됬습니다 복받으세요!
    혹시 일반 스마트폰처럼 쉽게 GPS 잡하는 방법을 아시나요? 휴대폰 GPS 안테나는 새끼손가락보다 작던데요

    2020.05.18 21:16 [ ADDR : EDIT/ DEL : REPLY ]
  19. 아두이노

    저 gps값이 나오는데 gpgll 해보니까 부산인데 창원이 나오더라구요 혹시 이값을 정확히 할수 있는 방법이나 어떤게 잘못 된건지 알 수 있을까요?

    2020.05.30 19:46 [ ADDR : EDIT/ DEL : REPLY ]
  20. 아두아두

    밖에 나가서 5분정도 기다리니 값이 나오네요ㅋㅋㅋ
    좋은 글 감사합니다~~^^

    2020.12.07 12:43 [ ADDR : EDIT/ DEL : REPLY ]
    • 잘 되신다니 기쁘네요
      한 번 신호를 잡은 이후로는 백업배터리에 의해 마지막 좌표가 저장되어 더 빨리 잡힐겁니다

      2020.12.07 13:01 신고 [ ADDR : EDIT/ DEL ]
    • 오호 그렇군요 그래서 배터리가 있던 것이였고 그래서 한번 전원을 끊었다 다시 넣었을때 더 빨리 잡히더라고요

      2021.05.02 14:37 [ ADDR : EDIT/ DEL ]
  21. taeung0217

    NEO-7M 모듈은 지자기 센서가 있다 하던데 진짜인가요?

    2021.05.19 14:57 [ ADDR : EDIT/ DEL : REPLY ]