top of page

Usando módulo de GPS NEO 6M


O GPS (Global Positioning System) é o nome do sistema utilizado para navegação e aquisição de medidas precisas de localização geográfica e geodésica. O GPS modelo NEO-6M foi lançado no mercado pela Ublox (https://www.u-blox.com/en), e posteriormente descontinuado para o lançamento de módulos receptores de GPS com mais recursos como os NEO-7M e NEO-8M. Devido ao seu grande sucesso muitos sites da China oferecem placas prontas integradas com o módulo NEO 6-M.


Neste artigo iremos aprender como ligar e comunicar com a placa que é oferecida em sites como Aliexpress ou Ebay:




Em geral as placas oferecidas no mercado chinês possuem reguladores, uma E2PROM, que salva os dados de parâmetro de configuração quando o módulo é desligado, uma bateria de backup, uma Antena para o módulo GPS e o conector de alimentação e saída de dados, com interface padrão serial USART (Universal Synchronous Asynchronous Receiver Transmitter), (em nível TTL, 3,3V), e taxa de transmissão é pré configurada em 9600 bps. O esquemático da placa pode ser conferido na Figura 1. Dentre os modelos oferecidos existe algumas placas com opção de se conectar uma antena externa, com ganho maior, essas placas possuem um conector SMA para conexão do cabo da antena.


A placa analisada no LIEPO pode ser alimentada em 5V. No circuito existe um regulador do tipo LDO que ajusta a tensão em 3.3V. A interface serial é de 3,3V e não tolerante a 5V, dessa forma, é preciso que o seu controlador tenha um USART de 3,3V. Caso contrario, você irá precisar de um level shift para fazer a interface do módulo com seu controlador.



Figura 1: Esquemático do Modulo com o receptor de GPS NEO-6M.


Para se comunicar com o módulo, precisamos de um controlador com uma porta serial USART, dessa maneira, basta ligar o módulo com tensão de 5V (verifique se a placa do módulo possui o regulador, o módulo por si só deve ser alimentado até 3.3V), e em seguida conectar o pino de TX da placa do módulo GPS no RX do conector da porta serial do controlador, e unir as 2 referencias, GND do módulo no GND do controlador.


No caso de usar um computador PC para se comunicar com o módulo, precisamos de um conversor de sinais que permita a conversão dos sinais da porta serial, padrão RS232, para o padrão serial TTL (3.3V).


Comunicando como Módulo GPS


Para obter essas mensagens do módulo, a principio não é necessário enviarmos nenhum comando, as mensagens são encaminhadas do módulo para o controlador ininterruptamente em forma de loop. Dessa forma basta entendermos as mensagens para retirar a informação de interesse, nesse caso, os dados referentes a latitude e longitude onde nosso GPS esta localizado.


Os comandos enviados pelo GPS NEO 6M seguem sentenças do protocolo NMEA0183 proposto pela NMEA (NAtional Marine Electronics Association), onde as sentenças podem ser conferidas aqui,

Quando ligado em visão aberta e o GPS obtiver sinal de resposta dos satélites teremos as seguintes linhas de informação.

$GPRMC,181842.00,A,2200.51026,S,04753.84408,W,0.125,,170216,,,A*79

$GPVTG,,T,,M,0.125,N,0.231,K,A*25

$GPGGA,181842.00,2200.51026,S,04753.84408,W,1,06,1.56,865.9,M,-6.1,M,,*4C

$GPGSA,A,3,18,21,29,10,20,25,,,,,,,2.81,1.56,2.35*0A

$GPGSV,4,1,16,04,,,44,10,46,325,36,13,04,125,,14,01,352,*4D

$GPGSV,4,2,16,15,26,093,28,16,24,224,,18,82,332,33,20,31,140,21*7A

$GPGSV,4,3,16,21,51,189,38,25,18,013,19,26,46,251,46,29,47,091,40*77

$GPGSV,4,4,16,31,06,311,25,32,19,104,24,33,45,059,32,46,29,287,37*78

$GPGLL,2200.51026,S,04753.84408,W,181842.00,A,A*65

Quando o GPS não obtiver resposta dos sinal de satélites teremos as seguintes linhas de informação.

$GPRMC,122457.00,V,,,,,,,170216,,,N*79

$GPVTG,,,,,,,,,N*30

$GPGGA,122457.00,,,,,0,03,2.16,,,,,,*57

$GPGSA,A,1,02,24,15,,,,,,,,,,2.38,2.16,1.00*0D

$GPGSV,2,1,06,02,59,040,37,05,04,020,,06,,,34,15,25,316,35*41

$GPGSV,2,2,06,24,67,225,37,31,,,25*4C

$GPGLL,,,,,122457.00,V,N*4D

Sintaxe para a Sentença NMEA

Cada Sentença NMEA carrega uma sintaxe,

Vamos conferir a sentença abaixo, (enviada pelo GPS).

$GPRMC,181842.00,A,2200.51026,S,04753.84408,W,0.125,,170216,,,A*79

Verificando os parâmetros fornecido por essa sentença conseguimos identificar.

181842.00: (UTC time of fix): Hora UTC, Nesse momento 18h 18min 42s .00 centésimos de segundo.

O Formato de horas UTC é a Hora Mundial, ou Tempo Coordenado Universal (UTC - Universal Coordinated Time).

Pode ser conferido em :

A: Resposta do GPS. A (GPS recebendo sinal do satélite) ou V (sem Sinal do Satélite) :

2200.51026,S: Latitude, S:(South) (Sul) ou N:(North) (Norte).

Posicionamento para Latitude, em formato DMS (Degree, Minutes, Seconds) poderiamos considerar 22graus, 00min, .51026*60 -> 30,62s, sendo assim 22°00'30,62'', SUL.

04753.84408,W: Longitude, W:West(Oeste) ou E: East (leste)

Posicionamento para Longitude, em formato DMS (Degree, Minutes, Seconds) poderiamos considerar 47graus, 53min, .84408*60 -> 50,64, sendo assim, 47 °,53' 50,64'', Oeste.

Site para conferência de coordenadas DMS

Desse site podemos também obter as coordenadas em DD (decimal degrees)

Assim temos a localização de latitude e longitude no qual podemos inserir no "google maps" (https://www.google.com.br/maps/), Lat, Long: -22.0085056,-47.8974

0.125: (Speed in knots): Velocidade em Nós ou milhas náuticas.(sendo 1 nó ~1.852 km/h) para 0.125 nós teremos nesse instante 0.06431 m/s , (GPS estático nessa medida). Em regra de três, podemos obter a resposta em m/s dividindo o valor obtido por ~1,944.

Para outras conversões de medida podemos usar o site abaixo: https://www.convert-me.com/en/convert/speed/knot.html?u=knot&v=1

170216: (Date Stamp): UTC date of fix, Data UTC, ddmmaa, Em nosso exemplo, 17 de feveiro de 2016.

A (Mode indicator), (A=Autonomous).:

Segundo o fabricante, o modo autônomo permite que o GPS opere sem a necessidade de um host ou conexão de rede externa. Com base em dados de efemérides de satélite previamente transmitidos baixados e armazenados pelo Receptor GPS, permite a geração de dados para orbitais dos satélite automaticamente, permitindo futuras correções de posição GPS.

79 (Checksum).: Gerado pelo algoritmo do Checksum para checagem da sentença emitda. Um exemplo de checksum pode ser conferido em, https://en.wikipedia.org/wiki/NMEA_0183

Em nosso estudo estaremos utilizando o computador embarcado Colibri VF61, junto com a placa IRIS Board, da Toradex® ( https://www.toradex.com).

Na comunicação com o módulo devemos selecionar a porta serial correspondente, em nosso exemplo estaremos usando a USART COM2, rodando em cima do WINCE 6.0. Essa porta é direcionada para os pinos da porta serial USART-B, do conector X16 (Extension Connector) da IRIS Board, Nessa porta os níveis de tensão seguem padrão TTL, (nível de 3.3V - 0V).

No conector X16 os seguintes pinos poderão ser utilizados,

pino 33 - VCC.

pino 31 - RX

pino 32 - TX

pino 36 - GND

A comunicação serial deve ser configurada com Baudrate a 9600 bps(padrão), 8 bits de dados, 1 bit de parada, sem paridade e sem controle de fluxo. Isso poderá ser feito no próprio programa durante a comunicação com o módulo GPS.

Uma vez inicializado a comunicação com o dispositivo através da porta serial (solicitando-se uma leitura na porta), basta separar os dados de interesse dentro da string que o GPS transmitiu, levantando assim os dados referente a latitude e longitude, de onde conseguimos obter sua localização.

Desenvolvendo a biblioteca para a comunicação com o GPS.

A biblioteca descrita abaixo foi desenvolvida de forma bem simples como exemplo para a comunicação com o GPS, foi implementada em C++ para o compilador Embedded Visual C++ da Microsoft e poderá ser facilmente adaptada p/ qualquer outra plataforma (micro controladores) que utilize a linguagem de programação C++ e tenha como feature uma USART, implementada.

Veremos abaixo os arquivos GPSLIB.h e GPSLIB.cpp que formam o header

No programa principal, podemos fazer a chamada da classe do GPS, executando o método que retorna a resposta referente a Latitude e Longitude.

// Chamando uma classe m_GPS da estrutura CGPSLIB

CGPSLIB m_GPS;

//Variaveis de aquisição do GPS

// Recebe string do GPS.

char* Recebe_GPS_String; // variavel que recebe string da serial e outras funções.

/////////////////////////////////////////////////////////////////////////////////////////////////////////// //Iniciando GPS.

///Alocando string que recebera os dados do gps

Recebe_GPS_String = (char*) malloc (500);

//Essa método deve retornar as mensagens preparadas na lib GPSLIB.h

. // A função toma como Sintaxe o port e a velocidade de leitura.

// COM2 é passado via classe CString da MFC,

Recebe_GPS_String = m_GPS.ReadComPort("COM2:",9600); // Classe GPS definida em m_GPS.

//Escrevendo leitura do GPS.

printf ("%s\n", Recebe_GPS_String);

Observação: Algumas das rotinas implementadas utilizam classes e funções interpretada pela MFC, (Microsoft Foundation Class), durante a compilaçãono Visual C++ e podem ter quer ser alteradas caso seja utilizado outro compilador C++.

GPSLIB.h

//diretivas para o compilador. (coloque os mesmos nomes para .h e .cpp)

#ifndef _GPSLIB_DOT_H

#define _GPSLIB_DOT_H

/*

LIB PARA REALIZAR LEITURA DO GPS.

Nesse exemplo nossa função na biblioteca pode retornar até 3 mensagens,

1- "Problema de Comunicação com GPS"

A mensagem é exibida quando não conseguimos encontrar um indice, de mensagens de retorno do GPS.

A função trava, não deixa o programa continuar, porem exibe mensagens no terminal para auxiliar a busca do erro.

Normalmente essa mensagem sera exibida quando houver problema de hardware (GPS queimado) ou em algum cabo de conexão.

2- "Sem Sinal no GPS"

Com o GPS em funcionamento normal, a mensagem pode ser apresentada enquanto existe a busca por satelites, nesse caso a função não trava.

Devemos montar uma rotina para aguardar ate que a mensagem altere para a cordenada.

3-"A,H:020929 Lat:22,02,41.46,S Lon:047,53,20.02,W".

No caso do GPS estar ativo receberemos a mensagem com informações de lagitude e longitude em formato DMS.

As rotinas de recebimento devem ser escritas no programa principal.

*/

//Criando a classe

class CGPSLIB

{

public:

// Construtor para a cliação da

CGPSLIB(); // para criação da classe.

// método com acesso publico para a ler a resposta enviada pelo GPS.

//A classe CString é compilada pela MFC no Visual C++, caso o compilador não consiga identificar essa classe , / / a entrada pode ser feita de outras formas. usando usigned int dentro da função,

char *ReadComPort(CString PortSpecifier,unsigned int BaudRate);

protected:

/*

//{{AFX_MSG(CGPS_NEO6M)

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

*/

} ;

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}

// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

GPSLIB.cpp

#include "math.h"

#include "stdafx.h"

#include <stdexcept>

#include "GPSLIB.h"

#include <stdio.h>

#include <string.h>

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

//construtor.

CGPSLIB::CGPSLIB()

{

}

//Método impelmentado para leitura da porta serial

char *CGPSLIB::ReadComPort(CString PortSpecifier, unsigned int BaudRate)

{

//Variaveis

char cBuffer[500] = "\0";

char nBuffer[500] = "\0";

char GPS_INFO_Buffer[500] = "\0";

memset(&cBuffer, 0, 500); // Zera cBuffer.

memset(&nBuffer, 0, 500); // Zera nBuffer.

memset(&GPS_INFO_Buffer, 0, 500); // Zera GPS_INFO_Buffer.

DWORD dwSize = 500, dwRead = 0;

//Variaveis para mandar retorno da serial.

char *envia_array_GPS;

envia_array_GPS = (char*) malloc (100);

//Var verifica se GPS esta ativo.

char valid;

//Var longetude.

char Lon[20] = "\0";

char Lon_DMS[20] = "\0";

//Var de Latitude

char Lat_DMS[20] = "\0";

char Lat[20] = "\0";

char H_DMS[4] = "\0";

char M_DMS[3] = "\0";

float S_DMS;

char aux[5] = "\0";

// Variaveis para Tempo

char Hora_UTC[6] = "\0";

char Hora[2] = "\0";

char Min[2] = "\0";

char Seg[2] = "\0";

char *partida;

bool ciclo;

//int ciclo;

S_DMS = 0;

int i,j,k;

i=0;

j=0;

k=0;

ciclo = TRUE;

while (ciclo == TRUE)

{

// Lendo buffer de dados da Serial.

// Nesse ponto vocÊ deve criar uma rotina para leitura da porta serial segundo sua plataforma de uso.

//Nesse programa criamos um "handle" que é interpretado pelo Compilador da Microsoft Visual C++.

//1-criando um Handle para abrir o port Serial

DCB dcb; // Estrutura DCB da propria microsoft. permite a configuração da Serial.

DWORD byteswritten = 0;

HANDLE hPort = CreateFile(

PortSpecifier,

GENERIC_READ|GENERIC_WRITE, // Handle permitindo escrita ou leitura.

0,

NULL,

OPEN_EXISTING,

0,

NULL

);

if (GetCommState(hPort,&dcb))

{ // Configuração padrao da Ocean 8N1.

dcb.BaudRate = BaudRate; //padrão 9600 Baud

dcb.ByteSize = 8; //8 data bits

dcb.Parity = NOPARITY; //no parity

dcb.StopBits = ONESTOPBIT; //1 stop

}

if(hPort == INVALID_HANDLE_VALUE);

if (SetCommState(hPort,&dcb))

{

//Setando timeouts pra leitura.

COMMTIMEOUTS commTimeOut; // tipo de ponteiro COMMTIMEOUTS structure. Pre definida //pela Microsoft Ela ajuda a configurar o timeout.

memset(&commTimeOut, 0, sizeof(COMMTIMEOUTS));

// Set the timeouts so that read operations will only

// after our buffer is full (10 characters)

//

commTimeOut.ReadIntervalTimeout = 1; //Maximo tempo permitido entre a chegada de um //caracter e outro, Tempo dado em ms. 0 desabilita //essa opção.

commTimeOut.ReadTotalTimeoutConstant = 10; //2112

commTimeOut.ReadTotalTimeoutMultiplier = 10; //

SetCommTimeouts(hPort, &commTimeOut);

ReadFile(hPort, &cBuffer, dwSize, &dwRead, NULL); // tenho que receber num array e nao num ponteiro. *

}

CloseHandle(hPort); //close the handle

//Uma vez carregado o buffer de serial, podemos indexar os dados do vetor partir da string de interesse //usando função strstr() da biblioteca "string.h". Ela busca exatamente a string desejada dentro do vetor, //e guarda na posição 0, junto com o restante dos dados armazenados no buffer.

partida = strstr(cBuffer,"$GPRMC");

// Caso queira indexar uma busca em outra sentença do GPS.

//partida = strstr(cBuffer,"$GPGGA");

if (partida != NULL)

{

ciclo = FALSE; // so quebra um laco quando eu achar um indice.

sprintf (nBuffer,"%s",partida); // copia no novo buffer, o restante da string.

// Conferindo o conteudo do nosso buffer indexado

//printf ("%s\n",nBuffer); // Opção para debugger dos dados coletados do GPS.

//Uma vez com o buffer indexado o usuário pode modificar as mensagens transmitidas da forma //que desejar.

for ( i = 0 ; i < 6; i++)

{

Hora_UTC[i] = nBuffer[i+7];

}

Hora_UTC[i] = '\0';

Hora[0]= Hora_UTC[0];

Hora[1]= Hora_UTC[1];

Min[0]= Hora_UTC[2];

Min[1]= Hora_UTC[3];

Seg[0]= Hora_UTC[4];

Seg[1]= Hora_UTC[5];

// Verificando GPS ATIVO

valid = nBuffer[17];

if (nBuffer[17] == 'A')

{

// Latitude.

if (nBuffer[23] == '.')

{

H_DMS[0] = nBuffer[19];

H_DMS[1] = nBuffer[20];

M_DMS[0] = nBuffer[21];

M_DMS[1] = nBuffer[22];

for (i=0 ; i < 6; i++)

{

aux[i] = nBuffer[23+i];

}

//Aqui fazemos uso da classe CString para preparar o valor coletado em //DMS,

CString Trans_String(aux);

//transformando uma string tipo ponto flutuante em valor numérico.

S_DMS = wcstod(Trans_String,0);

S_DMS = (S_DMS)* 60;

CString string;

string.Format(_T("%.2f"), S_DMS);

//Preparo a string com 2 strings tipo arrays + string tipo CString + um caracter.

sprintf (Lat_DMS,"%s,%s,%S,%c",H_DMS,M_DMS,string,nBuffer[30]);

}

for (i=0 ; i < 12; i++)

{

Lat[i] = nBuffer[i+19];

}

// Longetude.

if (nBuffer[37] == '.')

{

H_DMS[0] = nBuffer[32];

H_DMS[1] = nBuffer[33];

H_DMS[2] = nBuffer[34];

M_DMS[0] = nBuffer[35];

M_DMS[1] = nBuffer[36];

for (i=0 ; i < 6; i++)

{

aux[i] = nBuffer[37+i];

}

CString Trans_String(aux);

S_DMS = wcstod(Trans_String,0);

S_DMS = (S_DMS)* 60;

CString string;

string.Format(_T("%.2f"), S_DMS);

sprintf (Lon_DMS,"%s,%s,%S,%c",H_DMS,M_DMS,string,nBuffer[44]);

}

for (i=0 ; i < 13; i++)

{

Lon[i] = nBuffer[i+32];

}

}else if (nBuffer[17] == 'V')

{

}

else

{

sprintf (GPS_INFO_Buffer,"Sem Sinal no GPS");

//break;

}

}else

{

printf ("Problema de Comunicação com GPS \r\n");

sprintf (GPS_INFO_Buffer,"Problema de Comunicação com GPS");

}

}

if (nBuffer[17] =='A')

{

//Escrevendo a mensagem de saída.

GPS_INFO_Buffer[0] = nBuffer[17];

GPS_INFO_Buffer[1] = ',';

GPS_INFO_Buffer[2] = 'H';

GPS_INFO_Buffer[3] = ':';

k = 4; // indice para GPS_INFO_Buffer

//Carrega Hora UTC

for (i = 0 ; i < 6 ;i++)

{

GPS_INFO_Buffer[k] = Hora_UTC[i];

k=k+1;

}

GPS_INFO_Buffer[k] = ' ';

k =k + 1;

GPS_INFO_Buffer[k] = 'L';

k =k + 1;

GPS_INFO_Buffer[k] = 'a';

k =k + 1;

GPS_INFO_Buffer[k] = 't';

k =k + 1;

GPS_INFO_Buffer[k] = ':';

k =k + 1;

for (i = 0 ; i < 13 ;i++)

{

GPS_INFO_Buffer[k] = Lat_DMS[i];

k=k+1;

}

GPS_INFO_Buffer[k] = ' ';

k =k + 1;

GPS_INFO_Buffer[k] = 'L';

k =k + 1;

GPS_INFO_Buffer[k] = 'o';

k =k + 1;

GPS_INFO_Buffer[k] = 'n';

k =k + 1;

GPS_INFO_Buffer[k] = ':';

k =k + 1;

for (i = 0 ; i < 14 ;i++)

{

GPS_INFO_Buffer[k] = Lon_DMS[i];

k=k+1;

}

}else

if (nBuffer[17] =='V')

{

sprintf (GPS_INFO_Buffer,"Sem Sinal no GPS");

printf ("Sem Sinal no GPS \r\n");

}

envia_array_GPS = GPS_INFO_Buffer; // ponteiro aponta para cBuffer.

return envia_array_GPS; //dados lidos pela serial.

}

bottom of page