반응형

이전 글 [GPS 모듈의 사용 - GPS 로그 찍어보기] 에서 아두이노에 GPS 모듈을 붙여서 GPS 로그를 시리얼모니터에 출력해 보았습니다. 이번에는 GPS 모듈외에 SD카드에 텍스트를 저장할 수 있는 모듈을 추가해서 GPS 로그를 저장 할 수 있는 GPS 추적기를 만들어 보겠습니다. SD카드 저장모듈은 예전에 한 번 리뷰한적이 있습니다. [아두이노로 SD카드 다루기 (SD카드 정보, SD 카드 읽기/쓰기)] 이를 이용하여 GPS 의 위도와 경도 데이터를 마이크로 SD 카드에 텍스트 형식으로 저장하는 것 입니다. 단, 저장하는 형식은 GPS 로그기록 포맷인 XML 형식의 GPX 파일 포맷으로 하여 구글어스 등의 프로그램에서 바로 불러 올 수 있도록 생성해 보려고 합니다.


마이크로 SD 카드 저장모듈 입니다. SD 카드 모듈에 대해서 모른다면 [여기] 를 참고 하시면 됩니다.


각 모듈의 연결은 위와 같습니다.  상세사항은 아래를 참고하세요.


연결


GPS 모듈과 아두이노의 연결

VCC   -------------------  5V

GND  -------------------  GND

RX    --------------------  D5

TX    --------------------  D6



SD카드모듈과 아두이노의 연결

CS      ---------------------- D4

SCK    ---------------------- D13

MOSI  ---------------------- D11

MISO  ---------------------- D12

VCC    ---------------------- 3.3V

GND    --------------------- GND




소스



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
105
106
107
108
#include <SoftwareSerial.h>
#include <TinyGPS.h>
#include <SPI.h>
#include <SD.h>
 
#define RXPIN 6
#define TXPIN 5
#define GPSBAUD 9600
 
File myFile;
TinyGPS gps;
SoftwareSerial uart_gps(RXPIN, TXPIN); 
void getgps(TinyGPS &gps);
 
void setup()
{
  Serial.begin(9600);
  uart_gps.begin(GPSBAUD);
  
  Serial.println("");
  Serial.println("GPS Shield QuickStart Example Sketch v12");
  Serial.println("       ...waiting for lock...           ");
  Serial.println("");
 
  Serial.print("Initializing SD card..."); 

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
}
 
void loop()
{
  while(uart_gps.available())
  {
      int c = uart_gps.read();
      if(gps.encode(c))
      {
        getgps(gps);
      }   
  }
}
 
void getgps(TinyGPS &gps)
{
  float latitude, longitude;
 
  gps.f_get_position(&latitude, &longitude);
  Serial.print("Lat/Long: "); 
  Serial.print(latitude,5); 
  Serial.print(", "); 
  Serial.println(longitude,5);
  
  int year;
  byte month, day, hour, minute, second, hundredths;
  gps.crack_datetime(&year,&month,&day,&hour,&minute,&second,&hundredths);
 
  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);
  
  Serial.print("Altitude (meters): "); Serial.println(gps.f_altitude());  
  Serial.print("Course (degrees): "); Serial.println(gps.f_course()); 
  Serial.print("Speed(kmph): "); Serial.println(gps.f_speed_kmph());
  Serial.println();
  
  unsigned long chars;
  unsigned short sentences, failed_checksum;
  gps.stats(&chars, &sentences, &failed_checksum);
  
  writegps(latitude, longitude);
  
  delay(3000);
  
}
 
void writegps(float lati, float longi)
{
  Serial.print("lati/longi: "); 
  Serial.print(lati,5); 
  Serial.print(", "); 
  Serial.println(longi,5);
  Serial.println();
 
  myFile = SD.open("gpstest1.txt", FILE_WRITE);
 
  if (myFile) {
    Serial.print("Writing to gpstest1.txt...");
    myFile.print("      <trkpt lat=\"");
    myFile.print(lati,5);
    myFile.print("\" lon=\"");
    myFile.print(longi,5);
    myFile.println("\">");
    myFile.println("        <ele></ele>");
    myFile.println("        <time></time>");
    myFile.println("      </trkpt>");
    myFile.close();
    Serial.println("done.");
  } else {
    Serial.println("error opening gpstest1.txt");
  }
  
}
 


위의 소스에서 writegps() 함수가 SD카드에 GPX 포맷으로 XML 데이터를 저장하는 부분입니다. XML 의 데이터 부분만 저장이 되므로 윗부분 선언 부분과 맨 마지막 맺음 태그 부분은 수동으로 붙여 주어야 합니다. Serial.print() 부분은 테스트를 위한 부분으로 모두 삭제해도 상관 없습니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="UTF-8"?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" 
xmlns:xalan="http://xml.apache.org/xalan" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
creator="MotionX Live" version="1.1">
  <trk>
    <name>TEST TRACK</name>
    <desc>2016. 5. 13.  17:00 pm</desc>
    <trkseg>
      <trkpt lat="37.31182" lon="126.95788">
        <ele></ele>
        <time></time>
      </trkpt>
      <trkpt lat="37.31122" lon="126.95790">
        <ele></ele>
        <time></time>
      </trkpt>
      <trkpt lat="37.31062" lon="126.95794">
        <ele></ele>
        <time></time>
      </trkpt>
    </trkseg>
  </trk>
</gpx>


GPX 포맷의 XML 형식은 위와 같습니다. <trkseg> ~ </trkseg> 부분이 반복되면서 GPS 데이터가 저장 되는 것 입니다. 위의 소스에서는 바로 이 부분(데이터)을 생성해 줍니다. 그러므로 <trkseg> ~ </trkseg> 부분 이외의 맨윗부분과 아랫부분의 XML 태그를 덧붙이고 확장자를 GPX 파일로 저장하면 GPX 파일이 완성됩니다.




장치에 소스를 업로드 하고 작은 박스에 넣어 차에 싣고서는 마트 가는 길에 실행을 시켜 보았습니다. 마트에 다녀온 후 GPS 추적기의 SD카드를 뽑아서 컴퓨터에 꼽아보니 위와 같이 파일이 생성되었습니다. 파일의 생성크기는 위의 소스와 같이 매 3초마다 기록을 했을 경우 대략 30분에 30KB 정도의 용량이 소모 되었습니다.


생성된 파일을 메모장으로 열어보았습니다. 위와 같이 GPX 파일의 데이터 부분이 잘 생성된 것을 볼 수 있습니다.


위에서 설명한 바와 같이 GPX 파일을 완성 후 구글어스에서 열어 보았습니다. 파일을 열 때 위와 같이 기본옵션이 아니라 Gps 라는 파일형식을 선택해야 열립니다. 그러지 않으면 파일이 보이지 않습니다.


파일을 열면 잠시 후 위와 같이 SD카드에 기록된 GPS 로그가 지도상에 나타 납니다. 제가 운행한 경로가 정확히 나타나네요.


이상으로 간단하지만 아두이노를 이용하여 GPS 추적기를 만들어 보았습니다. 아두이노 우노 대신에 프로 미니 등을 이용하면 더욱 작게 소형화가 가능하며 적당한 케이스와 강력한 네오디움 자석 등을 결합하면 자동차에 척하고 붙이는 상용 추적기 못지 않은 성능을 발휘 할 것 같습니다. (저에게 이런 장치를 써먹을 날이 오진 않겠죠?)


남겨진 문제점

1. 장시간 움직임이 없을 경우의 처리

2. 추적로그에 날짜, 시간 추가 (GPS 시간은 한국시간보다 9시간 느리다.)

3. 파일이 너무 커질 경우의 처리


반응형

+ Recent posts