본문 바로가기

잡다한 기술

[아두이노] 아두이노 TinyGPS 라이브러리가 위치 파싱을 못할 경우




# 해결 법


간간히 아두이노를 사용할때 GPS가 필요한 경우가 많습니다.

그래서 자료를 찾아보면 대부분 TinyGPS 라이브러리를 사용하는데

이게 또 파싱이 잘 안되는 경우가 있습니다.

그래서 모듈이나 보드 문제인줄 알고 

보드와 모듈도 계속 바꿔 보았지만 잘 되지 않았습니다.



위 사진이 바로 그 예시 인데,
TinyGPS 예제인 FullExample 예제를 사용했을 경우,
위와 같이 값이 비정상 적으로 들어오는 경우가 있습니다.

그래서 모듈과 보드 또는 통신상태의 문제는 아니라는 판단 하에 API를 바꿔보았습니다.
라이브러리 이름은 아다후루츠 또는 에이다후르츠,
영문으로 Adafruit_GPS 라이브러리 입니다.
라이브러리는 


위 링크를 타고 받으시면 됩니다.
만약 다운이 정상적으로 되지 않을 경우를 대비해서 
제가 아래에 따로 링크를 걸을테니
그걸 이용하셔도 됩니다.



자 그럼 라이브러리를 다운 받고 추가를 합시다.
추가하는 방법은 아래 링크를 클릭하면 쉽게 배우실 수 있습니다.

그리고 Adafruit_GPS 예제 파일인 Parsing 예제 파일을 켜봅시다.


소스는 위와 같습니다.

그럼 예제에 맞게 RX를 2번 핀 TX를 3번핀 Vcc를 5V GND를 GND로 셋팅 해주고
컴파일을 해주세요


자 결과가 어떻게 나오셨나요?
저는 위 사진과 같이 결과가 나왔습니다.
정상적으로 무엇인가가 나오는 것을 확인 하실수 있습니다.

자 자세히 알아 봅시다.
두번째 Location을 보면 좌표값이 뜨는걸 확인 하실수 있습니다. 
하지만 그 밑에건 뭔지 잘 알기가 어렵다.
(가린 부분은 저의 위치 이므로 가리도록 하겠습니다.)
일단 두번째 로케이션을 구글 맵에다가 치면 자신의 위치가 뜹니다.
(만약 뜨지 않는다면 그건 GPS모듈이 위치를 잘 못 잡았을 경우가 큽니다.)
(GPS는 내부에서는 위치를 잘 못 잡기때문에 외부에서 잡아야 합니다.)
그럼 일단 반은 성공한 것입니다. 
이제 이걸 간단히 보기 쉽게 축소화 시켜 봅시다.

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
/*
 * Example of getting your location, using the MTK3339.
 * It is based heavily on the examples provided by Adafruit
 *
 * Do whatever you like with this code.
 * A link on your website/blog to my blog is very much appreciated!
 */
  
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
 
SoftwareSerial gpsSerial(32);
 
Adafruit_GPS GPS(&gpsSerial);
 
uint32_t timer = millis();
 
const int gpsEnablePin = 7;
 
void setup()  
{
  pinMode(gpsEnablePin, OUTPUT);
  
  Serial.begin(115200);
  GPS.begin(9600);
  
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  
  // 1 Hz update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
     
  // http://forums.adafruit.com/viewtopic.php?f=22&t=41452
  digitalWrite(gpsEnablePin, LOW); // turn GPS off
  
  delay(5000);
  
  digitalWrite(gpsEnablePin, HIGH); // turn GPS on
  
  delay(1000);
}
 
void loop()
{
  char c = GPS.read();
  
  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
      // we can fail to parse a sentence in which case we should just wait for another
return;
  }
  
  // if millis() or timer wraps around, we'll just reset it
  if (timer > millis())  timer = millis();
  
  // approximately every 5 seconds or so, print out the current stats
  if (millis() - timer > 5000) {
    timer = millis(); // reset the timer
     
    Serial.print("\nTime: ");
    Serial.print(GPS.hour, DEC); Serial.print(':');
    Serial.print(GPS.minute, DEC); Serial.print(':');
    Serial.print(GPS.seconds, DEC); Serial.print('.');
    Serial.print(GPS.milliseconds);
    Serial.println(" UTC");
    Serial.print("Date: ");
    Serial.print(GPS.day, DEC); Serial.print('-');
    Serial.print(GPS.month, DEC); Serial.print("-20");
    Serial.println(GPS.year, DEC);
    Serial.print("Fix: "); Serial.print((int)GPS.fix);
    Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
     
    if (GPS.fix) {
      Serial.print("Location: ");
      Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
      Serial.print(", ");
      Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
       
      //Serial.print("Speed (knots): "); Serial.println(GPS.speed);
      Serial.print("Speed (km/h): "); Serial.println(GPS.speed * 1.852);
      Serial.print("Angle: "); Serial.println(GPS.angle);
      //Serial.print("Altitude: "); Serial.println(GPS.altitude);
      Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
    }
    else {
      Serial.println("No sat fix :-(");
    }
  }
}

cs

위와 같이 저와 비슷하게 바꾸면 됩니다.
이제 컴파일을 하시면 아래 사진과 같이 나오시는것을 볼수 있습니다.



위 사진은 Adafruit_GPS라이브러리를 이용하여

제가 정리한 GPS 파싱 예제 결과입니다.

여기서 자신이 필요한 데이터를 뽑아서 쓰면 됩니다.

저같은 경우는 오로지 Location 좌표만 필요하므로

소스를 다음과 같이 수정하여 아래와 같은 결과를 냈습니다.


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
/*
 * Example of getting your location, using the MTK3339.
 * It is based heavily on the examples provided by Adafruit
 *
 * Do whatever you like with this code.
 * A link on your website/blog to my blog is very much appreciated!
 */
  
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
 
SoftwareSerial gpsSerial(32);
 
Adafruit_GPS GPS(&gpsSerial);
 
uint32_t timer = millis();
 
const int gpsEnablePin = 7;
 
void setup()  
{
  pinMode(gpsEnablePin, OUTPUT);
  
  Serial.begin(115200);
  GPS.begin(9600);
  
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  
  // 1 Hz update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
     
  // http://forums.adafruit.com/viewtopic.php?f=22&t=41452
  digitalWrite(gpsEnablePin, LOW); // turn GPS off
  
  delay(5000);
  
  digitalWrite(gpsEnablePin, HIGH); // turn GPS on
  
  delay(1000);
}
 
void loop()
{
  char c = GPS.read();
  
  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    if (!GPS.parse(GPS.lastNMEA()))   
// this also sets the newNMEAreceived() flag to false
      // we can fail to parse a sentence in which case we should just wait for another
  
}
  
  // if millis() or timer wraps around, we'll just reset it
  if (timer > millis())  timer = millis();
  
  // approximately every 5 seconds or so, print out the current stats
  if (millis() - timer > 5000) {
    timer = millis(); // reset the timer
   /*  
    Serial.print("\nTime: ");
    Serial.print(GPS.hour, DEC); Serial.print(':');
    Serial.print(GPS.minute, DEC); Serial.print(':');
    Serial.print(GPS.seconds, DEC); Serial.print('.');
    Serial.print(GPS.milliseconds);
    Serial.println(" UTC");
    Serial.print("Date: ");
    Serial.print(GPS.day, DEC); Serial.print('-');
    Serial.print(GPS.month, DEC); Serial.print("-20");
    Serial.println(GPS.year, DEC);
    Serial.print("Fix: "); Serial.print((int)GPS.fix);
    Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
     */
    if (GPS.fix) {
      Serial.print(GPS.latitudeDegrees, 4);
      Serial.print(", "); 
      Serial.println(GPS.longitudeDegrees, 4);
 
      Serial.println(" ");
      Serial.println(" ");
    }
    else {
      Serial.println("No sat fix :-(");
    }
  }
}

cs



자 위와 같이 수정을 하면 나오는 결과 사진입니다.
자신이 원하는 입맛 대로 바꿔서 작업하면 됩니다.
정확한 위치는 신상 정보이므로 가렸습니다. 죄송합니다.
이것으로 GPS 파싱을 마치도록 하겠습니다.
감사합니다.