아두이노 우노와 NEO-6M 모듈로 GPS 목적지 알림기 만들기
부품 및 소모품
| 부품 |
수량 |
비고 |
| 아두이노 우노 (Arduino UNO) |
1 |
|
| GPS 모듈 (NEO-6M) |
1 |
외장 안테나, 내장 EEPROM, 3-5V 동작, 9600 bps 기본 보드레이트 |
| LED (범용) |
1 |
목적지 도착 시각 알림용 |
| L293D 듀얼 H-브리지 모터 드라이버 (TI) |
1 |
진동 모터 구동용 |
| 바이브레이팅 디스크 모터 (Brown Dog Gadgets) |
1 |
햅틱 피드백용 |
| 스냅형 프로토보드 (SparkFun) |
1 |
회로 구성용 |
| 9V 배터리 |
1 |
전원 공급용 |
| 9V 배럴 잭 커넥터 |
1 |
아두이노 전원 연결용 |
| 케이스 (박스) |
1 |
프로젝트 수납용 |
| 점퍼 와이어 |
1세트 |
배선용 |
필요한 도구
소프트웨어 및 온라인 서비스
프로젝트 소개
문제 정의와 해결 방안
교통 체증은 누구에게나 큰 시간 낭비입니다. 출발지에서 목적지까지 얼마나 걸릴지 예측하기란 불가능에 가깝습니다. 두 달 전 이 도시로 이사 온 후, 저는 매일 2시간 이상을 교통 체증에 갇혀 보내야 했습니다. 대중교통을 이용하는 입장에서 이 시간을 생산적으로 활용할 방법은 없을까 고민하다가, 아두이노와 GPS 모듈을 이용해 목적지 알림 장치를 만들기로 했습니다.
이 장치는 사용자가 목적지 근처에 도달하면 LED 점등이나 진동 모터 작동으로 알려줍니다. 핵심 원리는 간단합니다: 목적지의 위도·경도 좌표를 미리 저장해 두고, 현재 GPS 위치와의 거리를 실시간으로 계산해 설정된 범위(예: 50m) 이내로 들어오면 알림을 트리거하는 것입니다.
부품 상세 및 배선
NEO-6M GPS 모듈
- 통신 인터페이스: RS232 TTL (시리얼)
- 전원: 3V ~ 5V
- 기본 보드레이트: 9600 bps
- 표준 NMEA 문장 지원
- 핀 구성: VCC, RX, TX, GND
배선표 (아두이노 우노 기준)
| GPS 핀 |
아두이노 핀 |
| VCC |
VIN (5V) |
| RX |
TX 핀 (소프트웨어 시리얼에서 정의, 예: D3) |
| TX |
RX 핀 (소프트웨어 시리얼에서 정의, 예: D4) |
| GND |
GND |
L293D 모터 드라이버 IC
L293D는 16핀 듀얼 H-브리지 드라이버로, 저전류 신호를 고전류로 증폭해 DC 모터 2개를 양방향 제어할 수 있습니다. 진동 모터 구동 시 아두이노 핀에서 나오는 미약한 신호로는 모터를 직접 돌릴 수 없으므로 필수적입니다.
TinyGPS++ 라이브러리
GPS 데이터 파싱을 단순화하는 표준 라이브러리입니다. 위도·경도뿐만 아니라 날짜, 시간, 속도, 방위, 고도, 위성 수, HDOP 등 풍부한 정보를 쉽게 추출할 수 있습니다.
위도·경도 좌표 획득하기
먼저 목적지의 정확한 좌표를 알아야 합니다. 아래 스케치를 업로드하고 시리얼 모니터(9600 bps)를 열면 현재 위치의 위도·경도가 출력됩니다. GPS 모듈의 LED가 깜빡이기 시작하면 위성 신호를 수신 중이라는 뜻입니다.
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
void setup() {
Serial.begin(9600);
ss.begin(GPSBaud);
}
void loop() {
while (ss.available() > 0) {
gps.encode(ss.read());
if (gps.location.isUpdated()) {
Serial.print("Latitude= ");
Serial.print(gps.location.lat(), 6);
Serial.print(" Longitude= ");
Serial.println(gps.location.lng(), 6);
}
}
}
LED 방식 목적지 알림기
프로토타입으로 먼저 LED 알림 버전을 제작했습니다. 획득한 목적지 좌표(Dest_LAT, Dest_LON)를 코드에 입력하고, 현재 위치와의 거리를 계산해 임계값(예: 0.05km = 50m) 미만이면 내장 LED(D13)를 켜도록 했습니다.
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
unsigned long last = 0UL;
int ledPin = 13;
void setup() {
Serial.begin(115200);
ss.begin(GPSBaud);
pinMode(ledPin, OUTPUT);
}
void loop() {
while (ss.available() > 0)
gps.encode(ss.read());
if (gps.location.isUpdated()) {
Serial.print(F(" Lat="));
Serial.print(gps.location.lat(), 6);
Serial.print(F(" Long="));
Serial.println(gps.location.lng(), 6);
}
else if (millis() - last > 5000) {
Serial.println();
if (gps.location.isValid()) {
static const double Dest_LAT = 18.786254, Dest_LON = 73.880798; // 목적지 좌표로 변경
double distanceToDest = TinyGPSPlus::distanceBetween(
gps.location.lat(), gps.location.lng(), Dest_LAT, Dest_LON);
Serial.print(F("Distance to Destination ="));
Serial.print(distanceToDest / 1000, 6); // km 단위
if (distanceToDest / 1000 < 0.050000) { // 50m 이내
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
}
if (gps.charsProcessed() < 10)
Serial.println(F("WARNING: No GPS data. Check wiring."));
last = millis();
Serial.println();
}
}
최종 완성: 진동 모터 탑재 버전
LED 프로토타입 검증 후, 실제 휴대용으로 쓸 수 있도록 진동 모터와 L293D 드라이버를 추가하고 9V 배터리로 구동되는 독립형 장치로 제작했습니다. 모든 부품을 케이스에 수납하고 배선을 정리했습니다.
L293D 배선 가이드
- 5V → Enable 1, Vs, Vss
- 아두이노 D6, D7 → Input 1, Input 2
- 아두이노 GND → L293D 양쪽 GND 핀
- Output 1, Output 2 → 진동 모터 양단
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
unsigned long last = 0UL;
int motorpin1 = 6;
int motorpin2 = 7;
void setup() {
Serial.begin(115200);
ss.begin(GPSBaud);
pinMode(motorpin1, OUTPUT);
pinMode(motorpin2, OUTPUT);
}
void loop() {
while (ss.available() > 0)
gps.encode(ss.read());
if (gps.location.isUpdated()) {
Serial.print(F(" Lat="));
Serial.print(gps.location.lat(), 6);
Serial.print(F(" Long="));
Serial.println(gps.location.lng(), 6);
}
else if (millis() - last > 5000) {
Serial.println();
if (gps.location.isValid()) {
static const double Dest_LAT = 18.786254, Dest_LON = 73.880798;
double distanceToDest = TinyGPSPlus::distanceBetween(
gps.location.lat(), gps.location.lng(), Dest_LAT, Dest_LON);
Serial.print(F("Distance to Destination ="));
Serial.print(distanceToDest / 1000, 6);
if (distanceToDest / 1000 < 0.050000) {
digitalWrite(motorpin1, LOW);
digitalWrite(motorpin2, HIGH); // 진동 모터 작동
} else {
digitalWrite(motorpin1, HIGH);
digitalWrite(motorpin2, HIGH); // 정지
}
}
if (gps.charsProcessed() < 10)
Serial.println(F("WARNING: No GPS data. Check wiring."));
last = millis();
Serial.println();
}
}
제작 팁 및 주의사항
- GPS 수신 시간: 처음 켤 때 위성 잡는 데 수 분이 걸릴 수 있습니다. 야외에서 테스트하세요.
- 좌표 정밀도: 소수점 6자리(약 11cm 정밀도)까지 입력하세요.
- 알림 거리 조절: 코드 내
0.050000 값을 수정해 알림 범위를 변경할 수 있습니다.
- 전원 관리: 9V 배터리 하나로 아두이노+GPS+모터 구동 시 배터리 수명을 고려하세요.
- 프리츠 파일: 본문 하단 첨부된 .fzz 파일을 참고하면 배선이 더 명확합니다.
소스 코드 파일
Read_Lat_Lng.ino - 위도/경도 읽기
Destination_notifier_LED.ino - LED 알림 버전
Destination_notifier_motor.ino - 진동 모터 알림 버전
즐거운 메이킹 되세요!