Autor Tema: Capturar Trama $GPRMC  (Leído 2387 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Capturar Trama $GPRMC
« en: 24 de Mayo de 2016, 01:54:45 »
Estoy intentando capturar la trama $GPRMC para  reenviarla a un servidor por gprs.
Uart1 esta con GPRS y uart2 para GPS

La cosa es que no logro sincronizar con la RDA2... cuando recorro el arreglo,este se va llenando con datos nuevos por eso solamente logro capturar 1 o 2 veces bien, he intentado deshabilitar mientras recorro el arreglo, pero el RTOS deja de correr... por solo hecho de escribir la  linea "disable_int...RDA2"

Código: C
  1. //******* Encontrar tramas **********
  2. void find_gps(void){  
  3.      
  4.       int n;
  5.       int j;
  6.      
  7.  for(n=0;Receive_String_uart2[n]!=0;n++){
  8.  //Buscar trama $GPRMC
  9. if(Receive_String_uart2[n]=='$' && Receive_String_uart2[n+1]=='G' && Receive_String_uart2[n+2]=='P'&& Receive_String_uart2[n+3]=='R' && Receive_String_uart2[n+4]=='M' && Receive_String_uart2[n+5]=='C')
  10.          {
  11.              n=5;
  12.              j=0;
  13.      
  14.             do{                                                  
  15.                 GPRMC_buff[j]=Receive_String_uart2[n];        
  16.                 j++;                                            
  17.               } while(Receive_String_uart2[++n]!=0x0D);
  18.          }
  19.   }
  20.  fprintf(debug,"$GPRMC%s\r\n",GPRMC_buff);
  21.  CLEAR_BUFFER(GPRMC_buff);    
  22.  CLEAR_BUFFER(Receive_String_uart2);
  23.       }
  24.  
  25. //---------------------------------------------------------------------------------------------------
  26. #INT_RDA2
  27. void RDA_isr2()
  28. {            
  29.    if(counter_read2==SIZE_BUFFER_UART2)  counter_read2=0x00; // Circle Buffer
  30.    Receive_String_uart2[counter_read2]=getchar(uart2);                  // Gets chars from uart
  31.    counter_read2++;                                                                           // Increment counter
  32. }


También intente poner banderas para saber cuando llega el "$" y cuando el "0D", pero igual el RTOS se enloquece...

Código: C
  1. Esto son los datos que envía el gps.
  2. //!$GPRMC,021823.000,A,0610.6072,N,07534.8988,W,0.25,244.04,220516,,,A*75{0D}{0A}
  3. //!$GPVTG,244.04,T,,M,0.25,N,0.46,K,A*3E{0D}{0A}
  4. //!$GPGGA,021824.000,0610.6072,N,07534.8988,W,1,9,0.86,1587.5,M,1.4,M,,*4F{0D}{0A}
  5. //!$GPGSA,A,3,05,02,17,19,13,28,20,12,24,,,,1.22,0.86,0.88*0B{0D}{0A}
  6. //!$GPGSV,4,1,13,05,63,265,32,19,50,067,20,17,37,100,18,12,34,305,34*7F{0D}{0A}
  7. //!$GPGSV,4,2,13,02,30,341,21,13,26,180,32,06,21,031,16,20,20,234,37*76{0D}{0A}
  8. //!$GPGSV,4,3,13,28,13,157,23,09,08,054,16,24,05,242,27,15,04,208,*79{0D}{0A}
  9. //!$GPGSV,4,4,13,25,02,319,*45{0D}{0A}

¿alguien tiene una idea de como puedo capturar esa trama?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Capturar Trama $GPRMC
« Respuesta #1 en: 24 de Mayo de 2016, 07:47:56 »
Pienso que deberias tener 2 buffers, 1 de llenado y otro en el cual tenes la trama completa.

Para simplificarlo ademas deberias tomar si o si el primer caracter como el $ supongamos asi:

Código: C
  1. if(counter_read2 != 0)
  2. {
  3.         Receive_String_uart2[counter_read2] = getchar(uart2);
  4.         counter_read2++;
  5.         if(counter_read2==SIZE_BUFFER_UART2)
  6.         {
  7.                 memcpy(Array_destino,Receive_String_uart2,SIZE_BUFFER_UART2);
  8.                 counter_read2=0x00;
  9.         }
  10. }
  11. else
  12. {
  13.         dato = getchar(uart2);
  14.         if(dato == '$')
  15.         {
  16.                 Receive_String_uart2[0] = '$';
  17.                 counter_read2++;
  18.         }
  19. }

El otro caso en el que quieras directamente capturar unicamente los GPRMC y lo demas no.

Código: C
  1. enum letras
  2. {
  3.         PRIMER_LETRA,
  4.         LETRA_G,
  5.         LETRA_P,
  6.         LETRA_R,
  7.         LETRA_M,
  8.         LETRA_C,
  9.         RESTANTE
  10. }
  11.  
  12. enum letras Estado;
  13.  
  14. switch(Estado)
  15. {
  16. case PRIMER_LETRA:
  17.         if(getchar(uart2)=='$') Estado = LETRA_G;
  18.         break;
  19. case LETRA_G:
  20.         if(getchar(uart2)=='G') Estado = LETRA_P;
  21.         break;
  22. case LETRA_P:
  23.         if(getchar(uart2)=='G') Estado = LETRA_R;
  24.         break;
  25. case LETRA_R:
  26.         if(getchar(uart2)=='G') Estado = LETRA_M;
  27.         break;
  28. case LETRA_M:
  29.         if(getchar(uart2)=='G') Estado = LETRA_C;
  30.         break;
  31. case LETRA_C:
  32.         if(getchar(uart2)=='G') Estado = RESTANTE;
  33.         counter_read2 = 0x00;
  34.         break;
  35. case RESTANTE:
  36.         dato = getchar(uart2);
  37.         if(dato == '$')
  38.         {
  39.                 Estado = LETRA_G;
  40.                 break;
  41.         }
  42.         Receive_String_uart2[counter_read2] = dato;
  43.         counter_read2++;
  44.         if(counter_read2==SIZE_BUFFER_UART2)
  45.         {
  46.                 memcpy(Array_destino,Receive_String_uart2,SIZE_BUFFER_UART2);
  47.                 Trama_presente = 1;
  48.                 Estado = PRIMER_LETRA;
  49.         }
  50.         break;
  51. default:
  52.         Estado = PRIMER_LETRA;
  53.         break;
  54. }

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Re:Capturar Trama $GPRMC
« Respuesta #2 en: 26 de Mayo de 2016, 01:32:22 »
Pienso que deberias tener 2 buffers, 1 de llenado y otro en el cual tenes la trama completa.
....
Gracias por responder,
voy a usar la primera opción... la idea es que cuando se llene el buffer se copie a Array_destino y con una la misma función  find_gps recorro para buscar toda la trama que necesito.?

Código: C
  1. void find_gps(void)
  2. {  
  3.       int n;
  4.       int j;
  5.  
  6.  for(n=0;Array_destino[n]!=0;n++){
  7.       //Buscar trama $GPRMC
  8.       if(Array_destino[n]=='G' && Array_destino[n+1]=='P' && Array_destino[n+2]=='R'&& Array_destino[n+3]=='M' && Array_destino[n+4]=='C')
  9.          {
  10.              n=6;
  11.              j=0;
  12.      
  13.             do{                                                  
  14.                 GPRMC_buff[j]=Array_destino[n];        
  15.                 j++;                                          
  16.               } while(Array_destino[++n]!=0x0D);
  17.          }
  18.        
  19.    }
  20.  
  21. }

y en el RTOS

Código: C
  1. #task(rate=900ms,max=20ms)                // Ejecutar cada 0.9 segundo y consumir como máximo 20ms
  2. void gps_in(){                                        
  3.  
  4.  find_gps();
  5.  fprintf(debug,"$GPRMC%s\r\n",GPRMC_buff);
  6.  CLEAR_BUFFER(GPRMC_buff);
  7.  fprintf(debug,"Tarea #:Captura Trama $GPRMC\r\n");
  8. }

Pero no corre bien el programa... no sé si será por el RTOS

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Capturar Trama $GPRMC
« Respuesta #3 en: 26 de Mayo de 2016, 07:28:09 »
Me acabo de dar cuenta que mi codigo que te pase tiene un error, pero bueno imagino que lo tomaste solo de referencia. Y ya le encontraste el error

Y si.. la idea es copiarlo a otro array cuando este completo, asi poder trabajar con el array ese mientras el otro se sigue llenando.
En un RTOS, la interrupciones no se bloquean, por lo que las interrupciones deberian seguir teniendo una maxima prioridad. Aunque tenes que recordar que se esta usando la interrupcion del Timer tambien para el RTOS.

La copia del array no se puede realizar EN la tarea, por que ahi no sabes cuando es que termino, y puede que todavia no se completo el array, o se completo y volvio a empezar, por lo cual no queda otra que hacerlo en la interrupcion.

En la interrupciones seria posible hacerlo de 2 formas, como el copiado puede tardar demasiado, afectando al RTOS, podrias usar un puntero, Y una ves lleno o detectado el '$' proceder a pasar a apuntar al otro array. de esa forma nunca estarias mucho tiempo.

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Capturar Trama $GPRMC
« Respuesta #4 en: 26 de Mayo de 2016, 08:25:29 »
Si te sirve, acá tengo un parseo en linea:

Código: C
  1. else if ( IIRValue == IIR_RDA ){                /* Receive Data Available */
  2.                 char_rcv = LPC_UART3->RBR;
  3.                 UART3Buffer[UART3Count] = char_rcv;
  4.                 UART3Count++;
  5.                 if ( UART3Count == BUFSIZE ){
  6.                         UART3Count = 0;         /* buffer overflow */
  7.                 }
  8.                 // now try to see where this character fits in the NMEA GGA message we're trying to decipher
  9.                 switch ( nmea_state )               // evaluate expression
  10.                 {
  11.                         case ( 1 ):                    // wait for 'G'
  12.                                 if ( char_rcv == 'G')
  13.                                         nmea_state++;
  14.                                 break;
  15.                         case ( 2 ):         // wait for 'G'
  16.                                 if ( char_rcv == 'G')
  17.                                         nmea_state++;
  18.                                 else
  19.                                         nmea_state=1;           //Si no es una G volvemos al principio
  20.                                 break;
  21.                         case ( 3 ):                     // wait for 'A'
  22.                                 if ( char_rcv == 'A')
  23.                                         nmea_state++;
  24.                                 else
  25.                                         nmea_state=1;           //Si no es una G volvemos al principio
  26.                                 break;
  27.                         case ( 4 ):                     // wait for ','
  28.                                 if ( char_rcv == ',')
  29.                                         nmea_state++;
  30.                                 break;
  31.                         case ( 5 ):                     // Estoy en el Campo UTS
  32.                                 if ( char_rcv == ','){                          //Si ya finalizó el campo
  33.                                         nmea_state++;                                   //Paso al siguiente estado
  34.                                         idx=0;
  35.                                 }else{
  36.                                         gps_UTC[idx] = char_rcv;                // Voy almacenando los caracteres recividos
  37.                                         idx++;                                                  // Incremento el índice dentro del campo actual
  38.                                 }
  39.                                 calculateoutputgps=0;
  40.                                 break;
  41.                         case ( 6 ):                     // Estamos en el Campo LATITUD
  42.                                 if ( char_rcv == ','){                          //Si ya finalizó el campo
  43.                                         nmea_state++;                                   //Paso al siguiente estado
  44.                                         idx=0;
  45.                                 }else{
  46.                                         idx++;                                                  // Incremento el índice dentro del campo actual
  47.                                         gps_latitud[idx] = char_rcv;    // Voy almacenando los caracteres recividos
  48.                                 }
  49.                                 break;
  50.                         case ( 7 ):
  51.                                 if ( char_rcv == 'N')                           // Si es Norte
  52.                                         gps_latitud[0] = '+';                   // Latitud positiva
  53.                                 else                                                            // Si es Sur
  54.                                         gps_latitud[0] = '-';                   // Latitud negativa
  55.                                 nmea_state++;
  56.                                 break;
  57.                         case ( 8 ):                             // this is a comma
  58.                                 nmea_state++;
  59.                                 break;
  60.                         case ( 9 ):                             // Estamos en el Campo LONGITUD
  61.                                 if ( char_rcv == ','){                          //Si ya finalizó el campo
  62.                                         nmea_state++;                                   //Paso al siguiente estado
  63.                                         idx=0;
  64.                                 }else{
  65.                                         idx++;                                                  // Incremento el índice dentro del campo actual
  66.                                         gps_longitud[idx] = char_rcv;   // Voy almacenando los caracteres recividos
  67.                                 }
  68.                                 break;
  69.                         case ( 10 ):
  70.                                 if ( char_rcv == 'E')                           // Si es Este
  71.                                         gps_longitud[0] = '+';                  // Latitud positiva
  72.                                 else                                                            // Si es Sur
  73.                                         gps_longitud[0] = '-';                  // Latitud negativa
  74.                                 nmea_state++;
  75.                                 break;
  76.                         case ( 11 ):                            // this is a comma
  77.                                 nmea_state++;
  78.                                 break;
  79.                         case ( 12 ):                            // Este campo es Fix quality
  80.                                 nmea_state++;
  81.                                 break;
  82.                         case (13):                                      // Este es una ','
  83.                                 nmea_state++;
  84.                                 break;
  85.                         case (14):                                      // Este es el campo de número de satelites linkeados.
  86.                                 if ( char_rcv == ','){                          //Si ya finalizó el campo
  87.                                         nmea_state++;                                   //Paso al siguiente estado
  88.                                         idx=0;
  89.                                 }else{
  90.                                         gps_Sats[idx] = char_rcv;               // Voy almacenando los caracteres recividos
  91.                                         idx++;                                                  // Incremento el índice dentro del campo actual
  92.                                 }
  93.                                 break;
  94.                         case (15):                              // this is the 4th comma
  95.                                 if ( char_rcv == 0x2C) {
  96.                                         // move to the next state
  97.                                         nmea_state++;
  98.                                         // but first prepare the meters input variable
  99.                                         gps_height[0]= 0x30;
  100.                                         gps_height[1]= 0x30;
  101.                                         gps_height[2]= 0x30;
  102.                                         gps_height[3]= 0x30;
  103.                                         gps_height[4]= 0x30;
  104.                                 }
  105.                                 break;
  106.                         case (16):                              // this is the heigth in meters
  107.                                 if ( char_rcv == 0x2e) {          // waiting for a decimal point
  108.                                         // no more numbers? OK, done with the shifting, move to the next step
  109.                                         nmea_state++;
  110.                                 }
  111.                                 else {
  112.                                         // oh no, 1 more number! Just shift the digits around and we'll be fine
  113.                                         gps_height[0]=gps_height[1];
  114.                                         gps_height[1]=gps_height[2];
  115.                                         gps_height[2]=gps_height[3];
  116.                                         gps_height[3]=gps_height[4];
  117.                                         gps_height[4]=char_rcv;
  118.                                 }
  119.                                 break;
  120.                         case (17):                              // this is the decimal part of the heigth
  121.                                 gps_height_decimeters = char_rcv;
  122.                                 // notify the main loop we have gps data available
  123.                                 calculateoutputgps = 1;
  124.                                 // and wait for the next NMEA message
  125.                                 nmea_state = 1;
  126.                                 break;
  127.                         default:
  128.                                 nmea_state = 1;     // we'll never and up here, but in case of a brownout make sure we start at the beginning
  129.                                 break;
  130.                 }
  131.         }

el enlace original es este: http://www.todopic.com.ar/foros/index.php?topic=42317.msg351072#msg351072

generalmente son más utilizados los parseadores on-line con una máquina de estado para la trama que los parseadores con buffer y análisis de linea completa...

Saludos!
-
Leonardo Garberoglio

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Re:Capturar Trama $GPRMC
« Respuesta #5 en: 30 de Mayo de 2016, 14:59:41 »

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Re:Capturar Trama $GPRMC
« Respuesta #6 en: 30 de Mayo de 2016, 23:31:37 »
.....
Por acá de nuevo, tu código funciona como quiero,
pero debí poner la linea de copiado  al otro buffer cuando  vuelve a llegar el "$"...  bueno eso es lo que entiendo.
es decir nunca va pasar por el área comentada.... según veo en la simulación.... entonces nunca va haber un desbordamiento.

Código: C
  1. #INT_RDA2
  2. void RDA_isr2() {
  3.  
  4. switch(Estado)
  5.    {
  6.         case PRIMER_LETRA:
  7.                            if(getchar(uart2)=='$') Estado = LETRA_G;  break;
  8.         case LETRA_G:
  9.                            if(getchar(uart2)=='G') Estado = LETRA_P; break;
  10.         case LETRA_P:
  11.                            if(getchar(uart2)=='P') Estado = LETRA_R; break;
  12.         case LETRA_R:
  13.                            if(getchar(uart2)=='R') Estado = LETRA_M; break;
  14.         case LETRA_M:
  15.                            if(getchar(uart2)=='M') Estado = LETRA_C; break;
  16.         case LETRA_C:
  17.                            if(getchar(uart2)=='C') Estado = RESTANTE; counter_read2 = 0x00; break;
  18.         case RESTANTE:
  19.                            c = getchar(uart2);
  20.                            if(c == '$')
  21.                              {
  22.                                Estado = LETRA_G;
  23.                                 memcpy(GPRMC_buff,Receive_String_uart2,SIZE_BUFFER_UART2);
  24.                                break;
  25.                              }
  26.        
  27.                            Receive_String_uart2[counter_read2] = c;
  28.                            counter_read2++;
  29.                        //     if(counter_read2==SIZE_BUFFER_UART2)
  30.                        //       {
  31.                        //        memcpy(GPRMC_buff,Receive_String_uart2,SIZE_BUFFER_UART2);
  32.                        //       Trama_presente = 1;
  33.                        //       Estado = PRIMER_LETRA;
  34.                       //     }
  35.                               break;
  36.          default:
  37.                            Estado = PRIMER_LETRA;
  38.                            break;
  39.    }
  40. }

Tengo otra duda:
Esta parte es muy nueva para mi... apenas logro entender.
Código: C
  1. enum letras
  2. {
  3.         PRIMER_LETRA,
  4.         LETRA_G,
  5.         LETRA_P,
  6.         LETRA_R,
  7.         LETRA_M,
  8.         LETRA_C,
  9.         RESTANTE
  10. };
  11.  enum letras Estado;

Aquí mismo es posible agregar la parte de captura de esta linea:
Código: C
  1. $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
¿o se debe hacer otro puntero?

Para poder elegir entre  enviar la trama $GPGGA y/o $GPRMC

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Capturar Trama $GPRMC
« Respuesta #7 en: 31 de Mayo de 2016, 08:32:40 »
enum letras
{
        PRIMER_LETRA,      // 0
        LETRA_G,                //1
        LETRA_P,                 // 2
        LETRA_R,                  // 3
        LETRA_M,                 // 4
        LETRA_C,                 // 5
        RESTANTE               // 6
};
 enum letras Estado;

El enum es una forma de ponerle nombres a los numeros. Ya que el switch toma unicamente enteros como parametros en los case. Si observas el codigo de elgarbe el uso numeros, bueno yo use un enum para darle mas sentido nada mas.

Lo bueno del codigo de elgarbe es que ya te divide todo el string en los campos que posee ( parseo ), Y asi podes enviar solo lo que te interesa y no TODO.

Citar
Aquí mismo es posible agregar la parte de captura de esta linea:

Código: [Seleccionar]
$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
¿o se debe hacer otro puntero?

Para poder elegir entre  enviar la trama $GPGGA y/o $GPRMC

Lo deseas poner en el mismo buffer? si es asi, simplemente agrega unas OR:

Código: C
  1. case LETRA_R:
  2.                            if(getchar(uart2)=='R' || getchar(uart2)=='G') Estado = LETRA_M; break;
  3.         case LETRA_M:
  4.                            if(getchar(uart2)=='M' || getchar(uart2)=='G') Estado = LETRA_C; break;
  5.         case LETRA_C:
  6.                            if(getchar(uart2)=='C' || getchar(uart2)=='A') Estado = RESTANTE; counter_read2 = 0x00; break;

Siempre y cuando no exista otra convinacion exacta de eso. Sino vas a tener que hacerlo un poco distinto. me refiero a combinaciones como:

GPRGA
GPRMA
GPGMC
GPGGC
etc