manipulação de Caracteres para GPS

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

manipulação de Caracteres para GPS

Mensagempor rodrigoadachi » 08 Jun 2009 22:06

Ola,

Estou tentando tratar os dados que o GPS envia pela serial, mas estou com algumas duvidas:

Código: Selecionar todos
  strcpy(gpsread,"$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47");
 
  if (strcmp(gpsread[0],'$')==0){// Ler dados que iniciem com '$'
   output_bit(LED_GPS,1);
   strncpy(gptip,strchr (strchr (gpsread,'P'),'G'),3);// verifica o tipo de mensagem, ex.: GGA
   
   strcpy(gga_data,strtok (strchr (gpsread,','),'*'));
     
   lcd_pos_xy(1,1);printf(escreve_lcd,"LAT: %s",gga_lat);
   lcd_pos_xy(1,2);printf(escreve_lcd,"LON: %s",gga_lon);


onde 'gpsread' é o dado do GPS, coloquei um valor fixo para poder testar, por exemplo como irei ler somente a latude e a longtude sendo que o padrão para o tipo GGA é:

    GGA - essential fix data which provide 3D location and accuracy data.
    $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
    Where:
    GGA Global Positioning System Fix Data
    123519 Fix taken at 12:35:19 UTC
    4807.038,N Latitude 48 deg 07.038' N
    01131.000,E Longitude 11 deg 31.000' E
    1 Fix quality: 0 = invalid
    1 = GPS fix (SPS)
    2 = DGPS fix
    3 = PPS fix
    4 = Real Time Kinematic
    5 = Float RTK
    6 = estimated (dead reckoning) (2.3 feature)
    7 = Manual input mode
    8 = Simulation mode
    08 Number of satellites being tracked
    0.9 Horizontal dilution of position
    545.4,M Altitude, Meters, above mean sea level
    46.9,M Height of geoid (mean sea level) above WGS84
    ellipsoid
    (empty field) time in seconds since last DGPS update
    (empty field) DGPS station ID number
    *47 the checksum data, always begins with *


Obrigado pela atenção...
rodrigoadachi
Nibble
 
Mensagens: 70
Registrado em: 15 Out 2007 12:19
Localização: Bahia - Brazil

Mensagempor Francesco » 09 Jun 2009 00:21

Até onde sei, a melhor maneira é separar em várias strings utilizando a vírgula como separador. Isso funciona bem se o número de vírgulas forem sempre os mesmos, mesmo que o tamanho dos dados mudem.

Por exemplo, na sua string:
"$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47"

Você tem:
(0) $GPGGA ,
(1) 123519 ,
(2) 4807.038 ,
(3) N ,
(4) 01131.000 ,
(5) E ,
(6) 1.08 ,
(7) 0.9 ,
(8 ) 545.4 ,
(9) M ,
(10) 46.9 ,
(11) M ,
(12) ,
(13) *47

Ao todo, são 14 argumentos. Se forem sempre esses 14, mesmo que com tamanhos diferentes, você pode fazer o seguinte:

char * arg0;
char * arg1;
char * arg2;
... até...
char * arg13;

arg0 = gpsread ; //Primeiro argumento.

arg1 = strchr( arg0 , ',' ) ; //Acha a vírgula.
*(arg1)='\0' ; // Separa as strings.
arg1++; // Aponta para o primeiro caractere.

arg2 = strchr( arg1 , ',' ) ;
*(arg2)='\0' ;
arg2++;

arg3 = strchr( arg2 , ',' ) ;
*(arg3)='\0' ;
arg3++;

... até ...

arg13 = strchr( arg12 , ',' ) ;
*(arg13)='\0';
arg13++ ;

Lembrando que isso só funciona se o número de vírgulas forem sempre os mesmos. E mesmo assim é bom colocar linhas de verificação.
Assim você tem os argumentos separados para ter somente a longitude e a latitude.
Avatar do usuário
Francesco
Word
 
Mensagens: 699
Registrado em: 04 Mar 2008 00:22
Localização: São Paulo - SP

Mensagempor rodrigoadachi » 09 Jun 2009 12:20

Obrigado Francesco

Fiz assim:

Código: Selecionar todos
//strcpy(gpsread,BufferRX);
  strcpy(gpsread,"$GPGGA,123519,4807.038,N,01131.000,E,2,08,0.9,545.4,M,46.9,M,,*47");
  if (strcmp(arg0,gpsread)!=0){
   arg0 = gpsread;
   output_bit(LED_GPS,1);
 
  if (strcmp(gpsread[0],'$')==0){// Ler dados que iniciem com '$'
   strncpy(gptip,strchr (strchr (gpsread,'P'),'G'),3);// verifica o tipo de mensagem, ex.: GGA
   
   strcpy(gga_data,strtok (strchr (gpsread,','),'*'));
  }
 
   // Fix taken at 12:35:19 UTC
   arg1 = strchr( arg0 , ',' ) ; //Acha a vírgula.
   *(arg1)='\0' ; // Separa as strings.
   arg1++; // Aponta para o primeiro caractere.
 
   //Latitude 48 deg 07.038'
   arg2 = strchr( arg1 , ',' ) ;
   *(arg2)='\0' ;
   arg2++;
   //Cardial N
   arg3 = strchr( arg2 , ',' ) ;
   *(arg3)='\0' ;
   arg3++;
 
   //Longitude 11 deg 31.000'
   arg4 = strchr( arg3 , ',' ) ;
   *(arg4)='\0' ;
   arg4++;
   //Cardial E
   arg5 = strchr( arg4 , ',' ) ;
   *(arg5)='\0' ;
   arg5++;

   //Fix quality
   arg6 = strchr( arg5 , ',' ) ;
   *(arg6)='\0' ;
   arg6++;

   // Number of satellites being tracked
   arg7 = strchr( arg6 , ',' ) ;
   *(arg7)='\0' ;
   arg7++;
 
   // Horizontal dilution of position
   arg8 = strchr( arg7 , ',' ) ;
   *(arg8)='\0' ;
   arg8++;
 
   //Altitude, contadores, média acima do nível do mar
   arg9 = strchr( arg8 , ',' ) ;
   *(arg9)='\0' ;
   arg9++;
   //Unidade de medida para arg9
   arg10 = strchr( arg9 , ',' ) ;
   *(arg10)='\0' ;
   arg10++;
 
   // Altura da Geoidal (média do nível do mar) acima WGS84 elipsóide
   arg11 = strchr( arg10 , ',' ) ;
   *(arg11)='\0' ;
   arg11++;
   ////Unidade de medida para arg11
   arg12 = strchr( arg11 , ',' ) ;
   *(arg12)='\0' ;
   arg12++;
 
   //tempo em segundos desde a última atualização DGPS
   arg13 = strchr( arg12 , ',' ) ;
   *(arg13)='\0';
   arg13++ ;
 
   //ID de estação DGPS
   arg14 = strchr( arg13 , ',' ) ;
   *(arg14)='\0';
   arg14++ ;
 
   //o checksum dados, começa sempre com *
   arg15 = strchr( arg14 , ',' ) ;
   *(arg15)='\0';
   arg15++ ;
 
   gga_lat = strcat(arg2,arg3);
   gga_lon = strcat(arg4,arg5);
   gga_alt = strcat(arg9,arg10);
   gga_altg = strcat(arg11,arg12);
 
  lcd_pos_xy(1,1);printf(escreve_lcd,"Lat: %s",gga_lat);
  lcd_pos_xy(1,2);printf(escreve_lcd,"Lon: %s",gga_lon);
  lcd_pos_xy(1,3);printf(escreve_lcd,"Alt: %s",gga_alt);
  if (strcmp(arg6,'0')==0){strcpy(gga_qualit,"Inválido");}
  if (strcmp(arg6,'1')==0){strcpy(gga_qualit,"GPS Fixado");}
  if (strcmp(arg6,'2')==0){strcpy(gga_qualit,"DGPS Fixado");}
  if (strcmp(arg6,'3')==0){strcpy(gga_qualit,"PPS Fixado");}
  if (strcmp(arg6,'4')==0){strcpy(gga_qualit,"Tempo Real Cinemático");}
  if (strcmp(arg6,'5')==0){strcpy(gga_qualit,"Flutuação RTK");}
  if (strcmp(arg6,'6')==0){strcpy(gga_qualit,"Aproximado");}
  if (strcmp(arg6,'7')==0){strcpy(gga_qualit,"Manual modo de entrada");}
  if (strcmp(arg6,'8')==0){strcpy(gga_qualit,"Modo de Simulação");}
  lcd_pos_xy(1,4);printf(escreve_lcd,"Qual: %c",qualit);
  }
   else{
   output_bit(LED_GPS,0);
  } 


Mas o qualit não ta funcionando:

Código: Selecionar todos
if (strcmp(arg6,'8')==0){strcpy(gga_qualit,"Modo de Simulação");}
  lcd_pos_xy(1,4);printf(escreve_lcd,"Qual: %c",qualit);


se o arg6 = 8 ele nã ta escrevendo, naum sei se é pq o arg6 ´um ponteiro...
rodrigoadachi
Nibble
 
Mensagens: 70
Registrado em: 15 Out 2007 12:19
Localização: Bahia - Brazil

Mensagempor Francesco » 09 Jun 2009 13:48

Na comparação, é preciso colocar dois ponteiros. O primeiro é arg6, mas o segundo não será considerado ponteiro se for colocado em aspas simples, precisa ser dupla. Assim:

Código: Selecionar todos
strcmp(arg6,"8")


Agora, se o arg6 tiver apenas 1 caractere, você pode fazer assim:

Código: Selecionar todos
switch( arg6[ 0 ] )
{
  case '0' :
    strcpy(gga_qualit,"Inválido");
    break ;

  case '1' :
    strcpy(gga_qualit,"GPS Fixado");
    break ;

... até ...
  case '8' :
    strcpy(gga_qualit,"Modo de Simulação");
    break ;
}
Avatar do usuário
Francesco
Word
 
Mensagens: 699
Registrado em: 04 Mar 2008 00:22
Localização: São Paulo - SP

Mensagempor rodrigoadachi » 09 Jun 2009 16:17

Muito obrigado mais uma vez Francesco, com sua ajuda pude termina a parte basica de meu projeto.

Código: Selecionar todos
/*
   GPS

   Rodrigo Adachi - rodrigoadachi@yahoo.com.br

*/

#include <16F877A.h>

#fuses HS, PUT, NOWDT, NOBROWNOUT, NOPROTECT, NOLVP
#ROM 0x07ff = {0} //Calibragem do oscilador interno
#use delay(clock=4000000) // Cristal 8Mhz (8000000hz)
#use rs232(baud=9600,PARITY=N,BITS=8,STOP=1,xmit=PIN_C6,rcv=PIN_C7)

#define LED_STATUS            pin_a0
#define LED_GPS               pin_a1

// LCD
#define lcd_db4               pin_b2 // pino de dados d4 do LCD
#define lcd_db5               pin_b3 // pino de dados d5 do LCD
#define lcd_db6               pin_b5 // pino de dados d6 do LCD
#define lcd_db7               pin_b4 // pino de dados d7 do LCD
#define lcd_rs                pin_b0 // pino rs do LCD
#define lcd_enable            pin_b1 // pino enable do LCD

#use fast_io(b)               // Inicialização rápida dos Pinos de I/O
#byte portb = 0x06            //#byte porta = 0x05

#include <_lcd.c>
#include <string.h>
#include <input.c>
#include <stdio.h>

// SERIAL
#define MAX_BUFFER 15
char BufferRX[MAX_BUFFER+1];
boolean CHEGOU_COMANDO = false;
//---------------------------------------------------------------------------
//Interrupção de recebimento de caracter pela UART.
//---------------------------------------------------------------------------
#int_rda
void Serial_Recebe_Car()
{
static unsigned char ch;
static int IndexBuf=0;
ch = getc(); //Pega o caracter no registrador da UART.
BufferRX[IndexBuf] = ch; //Guarda o caracter no buffer.
if( BufferRX[IndexBuf] == '*' ) //Se é o fim da string de comando.
{
BufferRX[IndexBuf+1] = '\0'; //Finaliza sting.
IndexBuf = 0;
CHEGOU_COMANDO = true; //Avisa que chegou uma string de comando.
}else{
IndexBuf++;
}
if( (BufferRX[0] != '$' ) || (IndexBuf >= MAX_BUFFER) )
{
IndexBuf = 0;
}
}
#int_timer0
void MeuTimer(){// TIME INTERNO
 static int time;
 static boolean led;
 set_timer0(125-get_timer0());
 time++;
 if (time == 1000){
  time=0;
  led=!led;
  output_bit(LED_STATUS,led);
 }
}
void main(){
 char gpsread[70],gptip[4],gga_qualit[25];
 char gga_data[50],* gga_lat,* gga_lon,* gga_alt,* gga_altg;
 char * arg0,* arg1,* arg2,* arg3,* arg4,* arg5,* arg6,* arg7;
 char * arg8,* arg9,* arg10,* arg11,* arg12,* arg13,* arg14,* arg15;
 //char gga_qualit[]={"Inválido,GPS Fixado,DGPS Fixado,PPS Fixado,Tempo Real Cinemático,Flutuação RTK,Flutuação RTK,Aproximado,Manual modo de entrada,Modo de Simulação"};
 // INICIALIZA INTERRUPÇÃO
 set_timer0(125);
 setup_timer_0(RTCC_INTERNAL | RTCC_DIV_8);
 enable_interrupts(int_timer0);
 enable_interrupts(GLOBAL); // Habilita registrador de interrupção.
 // INICIALIZA LCD
 portb = 0;
 set_tris_b(0b11000000);
 inicializa_lcd();
 limpa_lcd();
 
 lcd_pos_xy(1,1);printf(escreve_lcd,"                ");
 lcd_pos_xy(1,2);printf(escreve_lcd," GPS - SAKURA   ");
 lcd_pos_xy(1,3);printf(escreve_lcd," F/W V1.002     ");
 lcd_pos_xy(1,4);printf(escreve_lcd,"                ");
 delay_ms(3000);
 limpa_lcd();
 lcd_pos_xy(1,3);printf(escreve_lcd," Esperando GPS  ");
 while(true){
  strcpy(gpsread,BufferRX);
  //Teste
  //strcpy(gpsread,"$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47");
  if (strcmp(arg0,gpsread)!=0){
   arg0 = gpsread;
   output_bit(LED_GPS,1);
   limpa_lcd();
 
  if (strcmp(gpsread[0],'$')==0){// Ler dados que iniciem com '$'
   strncpy(gptip,strchr (strchr (gpsread,'P'),'G'),3);// verifica o tipo de mensagem, ex.: GGA
   
   strcpy(gga_data,strtok (strchr (gpsread,','),'*'));
  }
 
   // Fix taken at 12:35:19 UTC
   arg1 = strchr( arg0 , ',' ) ; //Acha a vírgula.
   *(arg1)='\0' ; // Separa as strings.
   arg1++; // Aponta para o primeiro caractere.
 
   //Latitude 48 deg 07.038'
   arg2 = strchr( arg1 , ',' ) ;
   *(arg2)='\0' ;
   arg2++;
   //Cardial N
   arg3 = strchr( arg2 , ',' ) ;
   *(arg3)='\0' ;
   arg3++;
 
   //Longitude 11 deg 31.000'
   arg4 = strchr( arg3 , ',' ) ;
   *(arg4)='\0' ;
   arg4++;
   //Cardial E
   arg5 = strchr( arg4 , ',' ) ;
   *(arg5)='\0' ;
   arg5++;

   //Fix quality
   arg6 = strchr( arg5 , ',' ) ;
   *(arg6)='\0' ;
   arg6++;

   // Number of satellites being tracked
   arg7 = strchr( arg6 , ',' ) ;
   *(arg7)='\0' ;
   arg7++;
 
   // Horizontal dilution of position
   arg8 = strchr( arg7 , ',' ) ;
   *(arg8)='\0' ;
   arg8++;
 
   //Altitude, contadores, média acima do nível do mar
   arg9 = strchr( arg8 , ',' ) ;
   *(arg9)='\0' ;
   arg9++;
   //Unidade de medida para arg9
   arg10 = strchr( arg9 , ',' ) ;
   *(arg10)='\0' ;
   arg10++;
 
   // Altura da Geoidal (média do nível do mar) acima WGS84 elipsóide
   arg11 = strchr( arg10 , ',' ) ;
   *(arg11)='\0' ;
   arg11++;
   ////Unidade de medida para arg11
   arg12 = strchr( arg11 , ',' ) ;
   *(arg12)='\0' ;
   arg12++;
 
   //tempo em segundos desde a última atualização DGPS
   arg13 = strchr( arg12 , ',' ) ;
   *(arg13)='\0';
   arg13++ ;
 
   //ID de estação DGPS
   arg14 = strchr( arg13 , ',' ) ;
   *(arg14)='\0';
   arg14++ ;
 
   //o checksum dados, começa sempre com *
   arg15 = strchr( arg14 , ',' ) ;
   *(arg15)='\0';
   arg15++ ;
 
   gga_lat = strcat(arg2,arg3);
   gga_lon = strcat(arg4,arg5);
   gga_alt = strcat(arg9,arg10);
   gga_altg = strcat(arg11,arg12);
 
  lcd_pos_xy(1,1);printf(escreve_lcd,"Lat: %s",gga_lat);
  lcd_pos_xy(1,2);printf(escreve_lcd,"Lon: %s",gga_lon);
 
  switch( arg6[ 0 ] )
{
  case '0' :
    strcpy(gga_qualit,"Inválido");
    break ;

  case '1' :
    strcpy(gga_qualit,"GPS Fixado");
    break ;
  case '2' :
    strcpy(gga_qualit,"DGPS Fixado");
    break ;

  case '3' :
    strcpy(gga_qualit,"PPS Fixado");
    break ;
  case '4' :
    strcpy(gga_qualit,"Tempo Real Cinemático");
    break ;

  case '5' :
    strcpy(gga_qualit,"Flutuação RTK");
    break ;
  case '6' :
    strcpy(gga_qualit,"Aproximado");
    break ;

  case '7' :
    strcpy(gga_qualit,"Manual modo de entrada");
    break ;
   
  case '8' :
    strcpy(gga_qualit,"Modo de Simulação");
    break ;
}
 
  lcd_pos_xy(1,3);printf(escreve_lcd,"Alt: %s",gga_alt);
  lcd_pos_xy(1,4);printf(escreve_lcd,"Qual: %s",gga_qualit);
  }
   else{
   output_bit(LED_GPS,0);
  } 
 }
}
rodrigoadachi
Nibble
 
Mensagens: 70
Registrado em: 15 Out 2007 12:19
Localização: Bahia - Brazil

Mensagempor rodrigoadachi » 01 Ago 2009 15:24

...
rodrigoadachi
Nibble
 
Mensagens: 70
Registrado em: 15 Out 2007 12:19
Localização: Bahia - Brazil


Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x