· GNSS (Global Navigation Satellite System)
GNSS는 우주 궤도를 돌고 있는 인공위성에 발신하는 전파를 이용해 지구 전역에서 움직이는 물체의 위치·고도치·속도를 계산하는 위성항법 시스템으로, 현재 미사일 유도 같은 군사적 용도뿐 아니라 측량이나 항공기, 선박, 자동차 등의 항법장치에 많이 이용되고 있다.
미국의 GPS, 러시아의 GLONASS, 유럽의 Galileo, 중국의 Beidou, 일본의 QZSS가 대표적인 GNSS 시스템이며, 현재 정상 가동되어 활발하게 서비스를 제공하는 위성측위시스템은 GPS와 GLONASS가 있다.
GNSS u-blox 7 위치 모듈은 GNSS 수신기이며 GPS, GLONASS 또는 Galileo 신호를 단독으로 수신하고 추적할 수 있다. QZSS 신호는 GPS 신호와 동시에 수신될 수 있다.
· 위치 추적방법
인공위성을 이용해 정확한 위치를 파악하는 방법은 다음과 같다.
우선, GPS 모듈과 1개의 GPS 인공위성이 연결되었다고 가정했을 때, 인공위성과 GPS 모듈 사이에 같은 거리에 있는 지점은 수없이 많다. 그러므로 정확한 위치를 알 수 없다.
2개의 인공위성과 연결되어있을 때도 마찬가지이다. 두 원을 그렸을 때 교차하는 점이 2개가 그려진다. 결국, 2개의 인공위성과 연결되어있을 때도 정확한 위치를 알 수 없다.
그렇다면 한 가지 점에서 만나기 위해서는 3개 이상의 위성이 필요하다. 바로 ‘삼각측량’이라는 개념이다. 세 개의 위성까지 정확한 위치를 알아내면 내 위치를 유추해 낼 수 있다.
· GNSS performance
- Receiver type
56개의 채널을 사용한다. GPS 위성은 두 개의 주파수 대역인 L1 (1575.42MHz)과 L2 (1227.60MHz)에 대한 신호를 전송한다. GPS는 L1 대역을 사용한다. L1 대역에는 모든 사용자에게 사용 가능한 SP (standard positioning) 코드가 있으며, C/A 코드 (사인 코드로 사용됨)와 Precision (P) 코드가 통합되어 있다. L2 대역에는 변조된 P 코드가 있으며, 전리층 (ionospheric) 지연을 측정하는 데 사용되며 이때 정밀 위치 서비스가 사용할 수 있으면 정확도가 증대된다.
- Time-to-First-Fix
GPS 수신기의 전원을 켰을 때 GPS 수신기가 현재 위치를 파악하는 데까지 걸리는 시간을 뜻하며, Cold Start, Warm Start, Hot Start로 구분된다.
* Almanac 데이터
GPS 위성배치의 개략적인 궤도 파라미터 정보이며, 몇 달에 한 번씩 갱신된다. GPS 수신기는 Almanac 데이터를 통해 특정 시각의 특정 지점에서 어떤 위성들의 신호를 수신할 수 있는지 미리 파악할 수 있으므로 보다 신속하게 자기 위치를 계산할 수 있다. GPS 수신기가 Almanac 데이터를 가지고 있지 않으면 데이터 전체를 수신하며, Almanac 데이터를 가지고 있되 최신 데이터가 아니면 해당 부분만 수신한다.
* Ephemeris 데이터
GPS 위성의 아주 정교한 궤도 및 시각보정 정보이며, 매 5시간마다 새로이 갱신된다. GPS 수신기는 Ephemeris 데이터를 통해 정밀하게 자기 위치를 파악할 수 있다.
위성별로 해당 위성의 Ephemeris 데이터를 30초 동안에 전송을 완료하며, 지속해서 이를 재전송한다.
GPS 수신기는 최신의 Almanac 데이터를 통해 어떤 위성들의 신호를 수신할 수 있는지 미리 파악하고, 최신의 Ephemeris 데이터를 수신한 위성 중 한 위성으로부터 신호를 받아 위성들과 시각 동기를 이루고, 다른 2개 이상의 위성들로부터 신호를 받아 각 위성까지의 거리를 측정하여 자기 위치를 파악하는 것이다.
Time-to-First-Fix는 Almanac 데이터와 Ephemeris 데이터의 수신 여부에 따라 Cold Start, Warm Start, Hot Start로 구분한다.
(1) Cold Start
Cold Start는 전원을 켠 후, 위성으로부터 Almanac 데이터 일부와 신호가 수신되는 위성 중 최소 3개 이상의 위성으로부터 각각 Ephemeris 데이터 전체를 수신하여 위치를 파악하는데 걸리는 시간이다. 사용했던 GPS 수신기의 전원을 끈 후, 수십 일 동안 사용하지 않다가 다시 사용하는 상황에 해당한다.
(2) Warm Start
Warm Start는 전원을 켠 후, 신호가 수신되는 위성 중 1~2개의 위성으로부터 각각의 Ephemeris 데이터 전체를 수신하여 위치를 파악하는 데 걸리는 시간이다. 사용했던 GPS 수신기의 전원을 끈 후, 수 시간 이내 다시 사용하는 경우가 이에 해당한다.
(3) Hot Start
Hot Start는 새로운 데이터의 수신 없이 위치를 파악하는 데 걸리는 시간으로 사용했던 GPS 수신기의 전원을 끈 후, 수 분 이내 다시 사용하는 경우 혹은 일시적으로 위성 신호를 수신하지 못하여 위치파악을 하지 못하다가 다시 위성 신호를 수신하게 된 상황에 해당한다.
- Sensitivity
각 상황에 따른 감도를 나타낸다. 앞서 말한 Cold Start, Warm Start, Hot Start 등에서 특정 감도 값을 갖는다.
-Max navigation update rate
최대 업데이트 속도는 1초에 10번 즉, 10Hz이다.
· NMEA-0183 형식
NMEA는 ‘National Marine Electronics Association’의 앞글자를 딴 약자이다. 정의로는 다음과 같다.
“해양 전자 장비 기자재 간의 통신을 위해 정의된 전기적 인터페이스 및 데이터 프로토콜”
현재 GPS 통신에서는 ‘NMEA-0183’을 표준 프로토콜로 사용하고 있다. 다음은 그 예이다.
‘$’로 시작되는 각각의 한 줄을 ‘NMEA Sentence’ 혹은 ‘NMEA 문장’이라고 한다. GPS 수신기가 GPS 위성 시스템으로부터 반송파를 받아서 해석한 후, NMEA 문장으로 내보내는 것이다. NMEA는 데이터의 패킷인 셈이다. NMEA는 여러 타입으로 분류되고 각 타입에 따라 고유한 프로토콜을 가지고 있다. 따라서, 타입을 먼저 파악한 후, 그에 맞는 프로토콜로 해석을 해야 한다.
-$ : 문장의 시작을 의미한다.
-Linefeed : 문장의 끝을 의미한다. <CR>/<LF>를 의미한다.
-Device ID : 장치를 구분하는 용도다. 현재 이 데이터를 말하는 장치의 ID라는 의미로 'Talker ID'라고도 부른다. '$' 바로 다음에 오는 문자 2개 ‘GP’를 말한다.
-Sentence ID : 문장을 구분하는 용도다. Sentence Name이라고도 한다. Device ID 다음에 오는 문자 3개. 예를 들면 'RMC'를 말한다.
-콤마 : 각 필드를 구분하는 용도이다.
· GPGGA
GPGGA는 'Global Positioning System Fix Data'를 의미한다. GPGGA는 총 17개의 field를 가진다. 참고로 예제에서는 12~15 필드는 비어 있다. 그리고, 17번 필드는 그림에서는 보이지 않는데, 그 이유는 Terminator 문자인 CR/LF이기 때문이다.
Idx |
Field |
Value |
Comments |
1 |
Sentence ID |
$GPGGA |
Global Positioning system fixed data |
2 |
UTC Time |
141113.999 |
시각. hhmmss.sss 형태이다. 예제는 14시 11분 13.999초라는 의미이다. 세계 표준시이므로 한국에서 사용하려면 +9를 해야 한다. 참고로 날짜는 GPGGA로는 확인할 수 없고, GPRMC에서 처리해야 한다 |
3 |
Latitude |
3730.08 |
위도. ddmm. mmmm 형식이다. 앞의 2자가 '도' 이고 이후는 '분' 이다. *'도분초' 형식이 아닌 '도분' 인것을 유의할 것. 필요하다면 소수점 아래는 60을 곱하여 '초' 형식으로 변환해야 한다. => 0.0308분 x60 = 1.848 초 |
4 |
N/S Indicator |
N |
N = North, S = South 북위 인지 남위 인지를 나타낸다. |
5 |
Longitude |
12655.2369 |
경도. dddmm.mmmm 형식이다. 앞의 3자가 '도' 이고 이후는 '분' 이다. *'도 분초' 형식이 아닌 '도분' 인 것을 유의할 것. 필요하다면 소수점 아래는 60을 곱하여 '초' 형식으로 변환해야 한다. |
6 |
E/W Indicator |
E |
E = East, W = West, 동경인지 서경인지를 나타낸다. |
7 |
Position Fix |
1 |
0 = Invalid, 1 = Valid SPS, 2 = Valid DGPS, 3 = Valid PPS 위치가 결정됐는지를 나타낸다. 이 값이 0이면 위도, 경도 등을 믿을 수 없으므로 사용하면 안 된다. |
8 |
Satellites Used |
06 |
Satellites being used (0-12) 현재 수신되는 위성의 개수이다. |
9 |
HDOP |
1.7 |
Horizontal Dilution of Precision |
10 |
Altitude |
98.9 |
WGS-84 타원체에서 평균해수면(MSL : Mean Sea Level)을 기준으로 한 고도. 고도값의 단위는 다음에 오는 Altitude Units 필드가 결정한다. |
11 |
Altitude Units |
M |
M = Meters |
12 |
Geoid Seperation |
(empty) |
Geoid seperation in meters according to WGS-84 ellipsoid MSL과 Geoid의 고도차. 마이너스 값이 나올 수 있다. |
13 |
Seperation Units |
(empty) |
M = Meters |
14 |
DGPS Age |
(empty) |
Age of DGPS data in seconds |
15 |
DPGS Station ID |
0 |
|
16 |
Checksum |
*3E |
|
17 |
Terminator |
CR/LF |
|
· GPRMC
GPRMC는 'Recommended Minimum Specific GNSS Data'로 정의되어있다. NMEA에는 GPS에서 필수적인 PVT(Position, Velocity, Time) 데이터의 고유한 버전이 있다. 그것을 RMC라고 부른다. 'RMC'에서 RM이 Recommended Minimum의 약자이고, C는 GNSS를 의미한다. RMA, RMB도 있으며 각각 LORAN-C와 Navigation을 의미한다.
Idx |
Field |
Value |
Comments |
1 |
Sentence ID |
$GPRMC |
Recommended Minimum Specific GNSS Data |
2 |
UTC Time |
141113.999 |
UTC시각. hhmmss.sss 형태. 예제는 14시 11분 13.999초 이다. |
3 |
Status |
A |
A = Active, V = Void GPGGA의 7번항목, Position Fix와 유사하다. 차이점은 GPRMC가 더 간단하게 2-상태 라는 점. V이면 신뢰할 수 없는 상태이다. |
4 |
Latitude |
3730.0308 |
위도. ddmm.mmmm 37도 30.0308' |
5 |
N/S Indicator |
N |
N = North, S = South 북위 인지 남위 인지를 나타낸다. |
6 |
Longitude |
12655.2369 |
경도. dddmm.mmmm 126도 55.2369' |
7 |
E/W Indicator |
E |
E = East, W = West, 동경인지 서경인지를 나타낸다. |
8 |
Speed over ground |
19.77 |
Knots 단위의 속도이다. km/h로 변환하려면 1.852를 곱하면 된다. eg. 19.77 (Knots) x 1.852 = 36.61404 (km/h)1 |
9 |
Course over ground |
195.23 |
Degrees. 진행 방향을 표현한다. 진북을 중심으로 시계방향으로 0 보다 같거나 크고, 360보다 작은 범위의 각도 값을 준다. 여기서 말하는 '진북'은 WGS-84 타원체를 중심으로 한 것이다. |
10 |
UTC Date |
101200 |
UTC 날짜. DDMMYY eg. 101200은 2000년 12월 10일을 의미한다. |
11 |
Magnetic variation |
(empty) |
Degrees. '자북' 과 9번에서 말한 '진북' 과의 차이를 각도로 표시한 것이다. 통상적인 GPS에서는 대개 NULL로 채워져 있다. |
12 |
Checksum |
*3E |
|
13 |
Terminator |
CR/LF |
|
GPS Navigation update rate & Uart baudrate Setting
FTDI (TTL 직렬 전송을 USB 신호로 변환하는 장치) 케이블을 연결하고 제조사(Ublox) 공식 홈페이지에서 ‘u-center’ 응용프로그램을 다운로드받아 실행한다. NEO-7M의 기본설정 값은 Navigation update rate는 1Hz이고 Usart baudrate는 9600bps이다. 데이터시트를 살펴보면 Navigation update rate는 최대로 10Hz(100ms) 값을 갖는다.
첫 번째로 어플리케이션에서 [View]-[Text Console]을 통해 데이터를 정상적으로 수신하는지 확인한다.
[View]-[Message View]을 클릭해 창을 띄운다. 좌측 메뉴에서 [UBX]-[CFG(config)]-[Rate]에 들어간다. 그리고 Measurement Period를 1000ms(1Hz)에서 100ms(10Hz)로 바꾼다.
Uart Baudrate 설정은 보다 더 간단하다. [Receiver]-[Baudrate]에서 원하는 속도를 선택한다.
기타 원하는 다른 설정들을 변경할 때 모두 ‘u-center’라는 응용프로그램을 통해서만 변경할 수 있다.
Atmega128을 이용한 NEO-7m의 Data 파싱
#define F_CPU 8000000UL
#define BAUD 9600
#define U2X_S 2 // U2X -> 1 or 2
#define MYUBRR ((F_CPU*U2X_S)/(16L*BAUD)-1)
#define null 0 // C 형 NULL 값 (0)
#define ETX 0x0A
#include <avr/io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <ctype.h>
#include "USART_ch0.h"
//비교 NMEA
char NAME[10]="$GPGGA"; //NMEA _ GPGGA
char NAME2[10]="$GPRMC"; //NMEA _ GPRMC
//UART GPS_DATA 저장
char GPS_DATA[100]; // UART로 받은 데이터 저장
char GPS_DATA1[100]; // GPGGA DATA 피신 저장
char GPS_DATA3[100]; // GPRMC DATA 피신 저장
//구간 별로 저장하기 위한 포인터
char *GPS_cut=0; // STRTOK 함수 사용을 위한 변수
char *GPS_Dcut[15]={0}; // GPGGA 값을 ( , ) STRTOK 로 나누어 저장
char *GPS_Dcut2[15]={0}; // GPRMC 값을 ( , ) STRTOK 로 나누어 저장
//Count 및 flag 변수
int GPScnt; // UART로 받은 데이터 저장 COUNT
int GPScnt1; // UART COUNT 값 피신 저장
int GPSflag;
int i;
// 버퍼저장
char test1[20];
char test2[20];
char test3[20];
int rx;
void usart0_rx_isr(uint8_t RX_data);
void GPS_Latitude();
void GPS_Longitude();
void GPS_Altitude();
ISR(USART0_RX_vect){
rx = UDR0;
//USART0_Transmit(rx);
usart0_rx_isr(rx);
}
int main(){
USART0_Init(MYUBRR);
USART0_Transmit_String("UART Init O.K\n");
//UCSR0B |= (1 << UDRIE0);
// Enable interrupt
sbi(UCSR0B, RXCIE); // RX
sei( );
USART0_Transmit_String("UART interrupt Enable O.K\n");
SREG=0x80;
_delay_ms(1000);
while(1){
GPS_Latitude();
GPS_Longitude();
GPS_Altitude();
};
}
//interrupt [USART0_RXC]
void usart0_rx_isr(uint8_t RX_data){
//USART0_Transmit_String("UART Start O.K \n");
unsigned char RX;
RX=(char)RX_data;
//////////RX= UDR0;
if(RX == '$'){ // GPS NMEA_code [STX]
GPS_DATA[0]='$'; // GPS_DATA[0] 에 '$' 저장
GPScnt=1; // GPScnt = 1 저장
GPSflag=0; // GPSflag = 0 저장
}
else{
GPS_DATA[GPScnt]=RX; // char 형 DATA RX 를 GPS_DATA 배열에 저장
if(GPS_DATA[GPScnt] == '\n') { // 위에서 ETX = 0x0A 라고 했으므로 조건을 걸어버린다.
GPScnt1=GPScnt; // 조건이 성립되면 COUNT 된 값을 GPScnt1으로 피신시킨다.
if(strncmp(NAME,GPS_DATA,6)==0) { // 이 부분은 NAME = "$GPGGA" 비교한 것이다.
memmove(GPS_DATA1,GPS_DATA,GPScnt1); // 메모리 복사
GPS_cut= strtok(GPS_DATA1,","); // STRTOK 구간 나누는 함수
for(i=0;GPS_cut!=null;i++){ // 나누는 조건이 0일때까지
GPS_Dcut[i]=GPS_cut; // 나눈값 포인터 배열에 저장
GPS_cut=strtok(null,","); // 구간 ( , ) 나누기
}
GPSflag=1; // flag =1
}
else if(strncmp(NAME2,GPS_DATA,6)==0) { // 이 부분은 NAME = "$GPRMC" 비교한 것이다.
memmove(GPS_DATA3,GPS_DATA,GPScnt1);
GPS_cut= strtok(GPS_DATA3,",");
for(i=0;GPS_cut!=null;i++){
GPS_Dcut2[i]=GPS_cut;
GPS_cut=strtok(null,",");
}
}
}
GPScnt++;
}
}
void GPS_Latitude() // 위 도
{
unsigned char DO,BOON; // 도, 분 저장 변수
double CHO; // 초 저장 변수
double Latitude; // GPS_LATITUDE 값 저장 변수
//atol() => LONG 변환 , atoi() => INT 변환, atof() => DOUBLE 변환
//순수 숫자나 부호로 이루어진 문자열을 해당 타입으로 변환
// $GPGGA,035155.00,3723.19464,N,12656.72748,E,1,06,1.69,47.0,M,18.5,M,,*6F 출력 샘플
// 위도 는 처음 도분 형태로 들어온다. 우리는 구글 맵상과 비교를 위하여 도분을 도분초로 변환 한다.
Latitude=atof(GPS_Dcut2[2]); // 문자열을 DOUBLE 형 으로 변환후 저장 => " 3723.19464 "
DO=Latitude/100; // 도 위치인 37 저장
BOON=(int)Latitude%100; // 분 위치인 23 저장
CHO=(Latitude-(int)Latitude)*60; // 초 를 구하기 위하여 (3723.19464 - 3723) * 60
// 소숫점만 빼내어 60을 곱하면 초로 변환 된다.
sprintf(test2,"LATIT: %2d'%2d`%0.02lf %s \n",DO,BOON,CHO,GPS_Dcut[3]);
USART0_Transmit_String(test2);
_delay_ms(100);
}
void GPS_Longitude() // 경 도
{
unsigned char DO,BOON; // 도, 분 저장 변수
double CHO; // 초 저장 변수
double Longitude; // GPS_LATITUDE 값 저장 변수
//atol() => LONG 변환 , atoi() => INT 변환, atof() => DOUBLE 변환
//순수 숫자나 부호로 이루어진 문자열을 해당 타입으로 변환
// $GPGGA,035155.00,3723.19464,N,12656.72748,E,1,06,1.69,47.0,M,18.5,M,,*6F 출력 샘플
// 경도 는 처음 도분 형태로 들어온다. 우리는 구글 맵상과 비교를 위하여 도분을 도분초로 변환 한다.
Longitude=atof(GPS_Dcut2[4]); // 문자열을 DOUBLE 형 으로 변환후 저장 =>" 12656.72748 "
DO=(int)Longitude/100; // 도 위치인 126 저장
BOON=((int)Longitude%100); // 분 위치인 56 저장
CHO=(Longitude-(int)Longitude)*60; // 초 를 구하기 위하여 (12656.72748 - 12656) * 60
sprintf(test3,"LONGI: %3d'%02d`%0.02lf%s \n",DO,BOON,CHO,GPS_Dcut[5]);
USART0_Transmit_String(test3);
_delay_ms(100);
}
void GPS_Altitude() // 고 도
{
float Altitude; // GPS_LATITUDE 값 저장 변수
//atol() => LONG 변환 , atoi() => INT 변환, atof() => DOUBLE 변환
//순수 숫자나 부호로 이루어진 문자열을 해당 타입으로 변환
// $GPGGA,035155.00,3723.19464,N,12656.72748,E,1,06,1.69,47.0,M,18.5,M,,*6F 출력 샘플
// 경도 는 처음 도분 형태로 들어온다. 우리는 구글 맵상과 비교를 위하여 도분을 도분초로 변환 한다.
Altitude=atof(GPS_Dcut[8]); // 문자열을 DOUBLE 형 으로 변환후 저장 =>" 12656.72748 "
//USART0_Transmit('A');
sprintf(test1,"Altitude: %.1f\n",Altitude);
USART0_Transmit_String(test1);
_delay_ms(100);
}
*Usart Header File은 HC06에서 사용했던 것과 동일하다.
'Embedded System > ATmega128' 카테고리의 다른 글
Balancing Robot (0) | 2020.04.04 |
---|---|
C-LCD 8-bit Control and 4-bit Control (4) | 2020.04.04 |
HC06 Bluetooth Module (Master / Slave 연동하기) (0) | 2020.03.28 |
HC06 (Bluetooth Module) Mobile 연동하기 (0) | 2020.03.27 |
HC-SR04 Module (초음파 센서 모듈) (3) | 2020.03.27 |
댓글