본문 바로가기
Embedded System/ATmega128

NEO-7M (GPS module)

by xangmin 2020. 3. 28.
반응형

< Neo-7M (GPS module) >

· GNSS (Global Navigation Satellite System)

GNSS는 우주 궤도를 돌고 있는 인공위성에 발신하는 전파를 이용해 지구 전역에서 움직이는 물체의 위치·고도치·속도를 계산하는 위성항법 시스템으로, 현재 미사일 유도 같은 군사적 용도뿐 아니라 측량이나 항공기, 선박, 자동차 등의 항법장치에 많이 이용되고 있다.

 

 미국의 GPS, 러시아의 GLONASS, 유럽의 Galileo, 중국의 Beidou, 일본의 QZSS가 대표적인 GNSS 시스템이며, 현재 정상 가동되어 활발하게 서비스를 제공하는 위성측위시스템은 GPSGLONASS가 있다.

 

 GNSS u-blox 7 위치 모듈은 GNSS 수신기이며 GPS, GLONASS 또는 Galileo 신호를 단독으로 수신하고 추적할 수 있다. QZSS 신호는 GPS 신호와 동시에 수신될 수 있다.

 

· 위치 추적방법

인공위성을 이용해 정확한 위치를 파악하는 방법은 다음과 같다.

우선, GPS 모듈과 1개의 GPS 인공위성이 연결되었다고 가정했을 때, 인공위성과 GPS 모듈 사이에 같은 거리에 있는 지점은 수없이 많다. 그러므로 정확한 위치를 알 수 없다.

 

2개의 인공위성과 연결되어있을 때도 마찬가지이다. 두 원을 그렸을 때 교차하는 점이 2개가 그려진다. 결국, 2개의 인공위성과 연결되어있을 때도 정확한 위치를 알 수 없다.

 

그렇다면 한 가지 점에서 만나기 위해서는 3개 이상의 위성이 필요하다. 바로 삼각측량이라는 개념이다. 세 개의 위성까지 정확한 위치를 알아내면 내 위치를 유추해 낼 수 있다.

 

· GNSS performance

< NEO-7M datasheet >

 - Receiver type

 56개의 채널을 사용한다. GPS 위성은 두 개의 주파수 대역인 L1 (1575.42MHz)L2 (1227.60MHz)에 대한 신호를 전송한다. GPSL1 대역을 사용한다. 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-FixAlmanac 데이터와 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 형태이다.

예제는 141113.999초라는 의미이다. 세계 표준시이므로 한국에서 사용하려면 +9를 해야 한다.

참고로 날짜는 GPGGA로는 확인할 수 없고, GPRMC에서 처리해야 한다

3

Latitude

3730.08

위도. ddmm. mmmm 형식이다. 앞의 2자가 '' 이고 이후는 '' 이다.

*'도분초' 형식이 아닌 '도분' 인것을 유의할 것.

필요하다면 소수점 아래는 60을 곱하여 '' 형식으로 변환해야 한다.

=> 0.0308x60 = 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

MSLGeoid의 고도차. 마이너스 값이 나올 수 있다.

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'에서 RMRecommended Minimum의 약자이고, CGNSS를 의미한다. RMA, RMB도 있으며 각각 LORAN-CNavigation을 의미한다.

Idx

Field

Value

Comments

1

Sentence ID

$GPRMC

Recommended Minimum Specific GNSS Data

2

UTC Time

141113.999

UTC시각. hhmmss.sss 형태. 예제는 141113.999초 이다.

3

Status

A

A = Active, V = Void

GPGGA7번항목, Position Fix와 유사하다. 차이점은 GPRMC가 더 간단하게 2-상태 라는 점.

V이면 신뢰할 수 없는 상태이다.

4

Latitude

3730.0308

위도. ddmm.mmmm

3730.0308'

5

N/S Indicator

N

N = North, S = South

북위 인지 남위 인지를 나타낸다.

6

Longitude

12655.2369

경도. dddmm.mmmm

12655.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. 10120020001210일을 의미한다.

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 rate1Hz이고 Usart baudrate9600bps이다. 데이터시트를 살펴보면 Navigation update rate는 최대로 10Hz(100ms) 값을 갖는다.

 

 첫 번째로 어플리케이션에서 [View]-[Text Console]을 통해 데이터를 정상적으로 수신하는지 확인한다.

 

 [View]-[Message View]을 클릭해 창을 띄운다. 좌측 메뉴에서 [UBX]-[CFG(config)]-[Rate]에 들어간다. 그리고 Measurement Period1000ms(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에서 사용했던 것과 동일하다.

 

 

< GPS Module이 위성과 연결이 제대로 되지 않았을 때 >

 

< GPS Module이 위성과 연결이 제대로 되었을 때 >

 

< 위도와 경도 데이터 파싱 결과 >
반응형

댓글