Autor Tema: grados a decimales  (Leído 2212 veces)

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

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
grados a decimales
« en: 23 de Enero de 2017, 17:18:35 »
Hola, tengo esta trama GPS:  0610.9689,N,07535.1974,W
y debo convertirla a decimales,el formato es de esta forma:
ddmm.mmmm   para latitud
dddmm.mmmm para longitud

Entonces:
dd + mm.mmmm/60   para latitud
ddd + mm.mmmm/60 para longitud

06+(10.9689/60)=6.182815N                 Latitud
075+(35.1974/60)=75.5866233333W    Longitud

Para finalmente obtener esto:6.182815,-75.5866233333

¿Alguna idea?
« Última modificación: 23 de Enero de 2017, 17:21:43 por cvargcal »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:grados a decimales
« Respuesta #1 en: 23 de Enero de 2017, 19:59:16 »
Ni lo probe al codigo... Pero aca va:

Código: C
  1. //Datos Finales
  2.  
  3. struct DatosGPS {
  4.         float   NumLatitud;
  5.         float   NumLongitud;
  6.         char    DireccionLatitud;
  7.         char    DireccionLongitud;
  8. };
  9.  
  10. struct DatosGPS DatosGPS;
  11. char * strGPS = "0610.9689,N,07535.1974,W";
  12.  
  13. void main(void)
  14. {
  15.         while(1)
  16.         {
  17.                 ParserGPSData(strGPS,&DatosGPS);
  18.         }
  19. }
  20.  
  21. void ParserGPSData(char * ptr, struct DatosGPS * Datos)
  22. {
  23.  
  24.         uint8_t i = 0;
  25.         struct Parserptrs Tmp;
  26.         char *  ptrArray[4];
  27.         char    NumLat[3];
  28.         char    NumLong[4];
  29.  
  30.         // Primer inicio de string
  31.         ptrArray[i] = ptr;
  32.  
  33.         // Separo los string, cambio la coma por un caracter nulo y guardo los punteros de cada inicio de string
  34.         while(*ptr) {
  35.                 if(*ptr == ',') {
  36.                         *ptr++='\0';
  37.                         ptrArray[++i] = ptr;
  38.                 }
  39.         }
  40.  
  41.         //Separo los primeros 2 digitos de Lat y Long y cierro el string. Adelanto los punteros para quitar esos caracteres.
  42.         memcpy(NumLat,ptrArray[0],2);
  43.         memcpy(NumLong,ptrArray[2],3);
  44.         ptrArray[0] += 2;
  45.         ptrArray[2] += 3;
  46.         NumLat[3] = '\0';
  47.         NumLong[4] = '\0';
  48.  
  49.         //Es hora de la conversion y guardado de datos.
  50.         Datos->NumLatitud = atoi(NumLat) + (atof(ptrArray[0]) / 60);
  51.         Datos->NumLongitud = atoi(NumLong) + (atof(ptrArray[2]) / 60);
  52.         if(*ptrArray[1] == 'S') Datos->NumLatitud *= -1;
  53.         if(*ptrArray[3] == 'W') Datos->NumLongitud *= -1;
  54. }

El proceso (o la idea) es el siguiente, suponiendo que puedo modificar el string que pasa inicialmente.

Primer parte, transformar esto:
Citar
0610.9689,N,07535.1974,W\0

En esto:
Citar
0610.9689\0N\007535.1974\0W\0

Y guardar el comienzo de cada string, es decir que si ahora considero las string que apuntan ptrArray serian:

Código: [Seleccionar]
*ptrArray[0] = "0610.9689"
*ptrArray[1] = "N"
*ptrArray[2] = "07535.1974"
*ptrArray[3] = "W"

De aca ahora solo me queda separar los numeros. Con el memcpy, solo muevo 2 o 3 elementos segun sea Lat o Long a otro string, tambien modifico los punteros para quitar esa parte del string, es decir quedaria:

Código: [Seleccionar]
*NumLat = "06"
*NumLong = "075"
*ptrArray[0] = "10.9689"
*ptrArray[1] = "N"
*ptrArray[2] = "35.1974"
*ptrArray[3] = "W"

Ahora ya tengo los string de cada uno, solo me falta pasarlos a enteros o float segun sea el caso. Y aplicar las formulas que pasaste. Que es la ultima parte del programa.

---------------------------

Ojo, respete y acepto solamente el formato que me pasaste, es decir:

dd + mm.mmmm   para latitud
ddd + mm.mmmm para longitud
« Última modificación: 23 de Enero de 2017, 20:06:04 por KILLERJC »

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Re:grados a decimales
« Respuesta #2 en: 23 de Enero de 2017, 22:10:34 »
Ni lo probe al codigo... Pero aca va:


Genial!! muchas gracias, aunque el código no me compila... me dio algunas ideas. :mrgreen:
en realidad la trama la tengo separada por punteros, entonces cada trozo de la trama GPS lo tengo en un array distinto y ya al final lo envio todo concatenado.

Código: C
  1. &dat_GPRMC[3][0])  //0610.9689  
  2. &dat_GPRMC[4][0])  //N
  3. &dat_GPRMC[5][0])  //07535.1974
  4. &dat_GPRMC[6][0])  //W

Pienso que haciendo esto es mas corto y sabiendo que si es W o S, el signo es negativo.
0610.9689/100=6.109689, saco el entero 6, y  109680/10000=10.968,    entonces 6+(10.968/60)  =6.182815
07535.1974/100 =75.351974,saco el entero 75 y 351974/10000=35.1974,  entonces 6+(35.1974/60)  =75.5866233333

¿como podría hacerlo?
Debo convertirlo a numero y luego separar la parte entera de la decimal, para luego hacer las operaciones.




Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:grados a decimales
« Respuesta #3 en: 23 de Enero de 2017, 23:19:18 »
Bueno, no sabia como lo tenias, pero si lo tenes ya separado mejor.

Citar
0610.9689/100=6.109689, saco el entero 6, y  109680/10000=10.968,    entonces 6+(10.968/60)  =6.182815
07535.1974/100 =75.351974,saco el entero 75 y 351974/10000=35.1974,  entonces 6+(35.1974/60)  =75.5866233333

Tal ves en decimal es mas corto. Pero en binario es un dolor de cabeza dividir por 10 o multiplos de 10.. Podes usar esta parte, y si no queres que cambie el valor que tenes en dat_GPRMC:

Código: C
  1. memcpy(NumLat,&dat_GPRMC[3][0],2);
  2.         memcpy(NumLong,&dat_GPRMC[5][0],3);
  3.         ptrLat = &dat_GPRMC[3][0] + 2;
  4.         ptrLong = &dat_GPRMC[5][0] + 3;
  5.         NumLat[3] = '\0';
  6.         NumLong[4] = '\0';
  7.  
  8.         //Es hora de la conversion y guardado de datos.
  9.         Latitud = atoi(NumLat) + (atof(ptrLat) / 60);
  10.         Longitud = atoi(NumLong) + (atof(ptrLong) / 60);
  11.         if(dat_GPRM[4][0] == 'S') Latitud *= -1;
  12.         if(dat_GPRM[6][0] == 'W') Longitud *= -1;

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Re:grados a decimales
« Respuesta #4 en: 24 de Enero de 2017, 00:43:18 »
.....
Creo que debe ir así:

     
Código: C
  1. char    NumLat[3];
  2.         char    NumLong[4];
  3.         int       ptrLat;
  4.         int       ptrLong;
  5.         float    Latitud,Longitud;
  6.  
  7. //En este punto ya tengo   (perdon, este es el indice correcto del array)
  8. //&dat_GPRMC[2][0])  //0610.9689  
  9. //&dat_GPRMC[3][0])  //N
  10. //&dat_GPRMC[4][0])  //07535.1974
  11. //&dat_GPRMC[5][0])  //W
  12.  
  13.         memcpy(NumLat,&dat_GPRMC[2][0],2);      //Lat  06
  14.         memcpy(NumLong,&dat_GPRMC[4][0],3);   //Long 075
  15.        
  16.         ptrLat = &dat_GPRMC[2][0] + 2;
  17.         ptrLong = &dat_GPRMC[4][0] + 3;
  18.         NumLat[3] = '\0';
  19.         NumLong[4] = '\0';
  20.  
  21. //Es hora de la conversión y guardado de datos.
  22.  
  23.         Latitud = atoi(NumLat) + (atof(ptrLat) / 60);    
  24.         Longitud = atoi(NumLong) + (atof(ptrLong) / 60);
  25.         if(dat_GPRMC[3][0] == 'S')  Latitud *= -1;
  26.         if(dat_GPRMC[5][0] == 'W') Longitud *= -1;
  27.        
  28.        
  29.        
  30.         fprintf(debug,"\r\n");
  31.         fprintf(debug,"%01.2f\r\n",Latitud);
  32.         fprintf(debug,"%01.2f\r\n",Longitud);

Imprime
6.00
0.00

 :?
« Última modificación: 24 de Enero de 2017, 01:56:48 por cvargcal »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:grados a decimales
« Respuesta #5 en: 24 de Enero de 2017, 02:06:51 »
Lo verifique con gcc de la PC, tambien intente usar los mismos nombres de variables que tenes en tu programa, asi cambiaba lo menos posible. Lo unico que cambia es que use bastantes printf para que me muestre en la consola el paso a paso como queda y veas como va formandose.. Asi queda el codigo utilizado:

Código: C
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. char dat_GPRMC[6][20];
  6.  
  7. int main(void)
  8. {
  9.  
  10.         char    NumLat[3];
  11.     char    NumLong[4];
  12.     char *  ptrLat;
  13.     char *  ptrLong;
  14.     float   Latitud,Longitud;
  15.  
  16.     strcpy(dat_GPRMC[2],"0610.9689");
  17.     strcpy(dat_GPRMC[3],"N");
  18.     strcpy(dat_GPRMC[4],"07535.1974");
  19.     strcpy(dat_GPRMC[5],"W");
  20.  
  21.     //En este punto ya tengo
  22.     //&dat_GPRMC[2][0])  //0610.9689
  23.     //&dat_GPRMC[3][0])  //N
  24.     //&dat_GPRMC[4][0])  //07535.1974
  25.     //&dat_GPRMC[5][0])  //W
  26.  
  27.     printf("\ndat_GPRMC[2] : %s",dat_GPRMC[2]);
  28.     printf("\ndat_GPRMC[3] : %s",dat_GPRMC[3]);
  29.     printf("\ndat_GPRMC[4] : %s",dat_GPRMC[4]);
  30.     printf("\ndat_GPRMC[5] : %s",dat_GPRMC[5]);
  31.  
  32.  
  33.     printf("\n\nComienzo el tratamiento de variables\n");
  34.     printf("Nuevos valores en string\n");
  35.  
  36.     memcpy(NumLat,&dat_GPRMC[2][0],2);      //Lat  06
  37.     memcpy(NumLong,&dat_GPRMC[4][0],3);   //Long 075
  38.  
  39.     ptrLat = &dat_GPRMC[2][0] + 2;
  40.     ptrLong = &dat_GPRMC[4][0] + 3;
  41.     NumLat[2] = '\0';
  42.     NumLong[3] = '\0';
  43.  
  44.     printf("\n1er parte Lat : %s",NumLat);
  45.         printf("\n1er parte Long : %s",NumLong);
  46.         printf("\n2da parte Lat : %s",ptrLat);
  47.         printf("\n2da parte Long : %s",ptrLong);
  48.  
  49. //Es hora de la conversión y guardado de datos.
  50.  
  51.     printf("\n\nComienzo conversion a numeros\n");
  52.     printf("Nuevos valores en numeros\n\n");
  53.  
  54.     Latitud = atoi(NumLat) + (atof(ptrLat) / 60);
  55.     Longitud = atoi(NumLong) + (atof(ptrLong) / 60);
  56.     if(dat_GPRMC[3][0] == 'S')  Latitud *= -1;
  57.     if(dat_GPRMC[5][0] == 'W') Longitud *= -1;
  58.  
  59.     printf("Resultado final:");
  60.     printf("\nLat: %f",Latitud);
  61.     printf("\nLong: %f",Longitud);
  62.  
  63.     return EXIT_SUCCESS;
  64. }

Hasta el comienzo del memcpy podes observar que todo lo anterior es solo para setear los valores de los string y mostrar los valores iniciales del array. La respuesta en consola del paso a paso es este ( segui el codigo y vas a ver)

Código: [Seleccionar]
dat_GPRMC[3] : 0610.9689
dat_GPRMC[4] : N
dat_GPRMC[5] : 07535.1974
dat_GPRMC[6] : W

Comienzo el tratamiento de variables
Nuevos valores en string

1er parte Lat : 06
1er parte Long : 075
2da parte Lat : 10.9689
2da parte Long : 35.1974

Comienzo conversion a numeros
Nuevos valores en numeros

Resultado final:
Lat: 6.182815
Long: -75.586624

Como podes observar es el MISMO MISMO programa que tenes.. una cosa que podrias hacer es imprimir el resultado del atoi() y atof(), Solamente agarra la latitud por ejemplo y crea alguans variables para guardar los valores de las operaciones atof y atoi, si alguna falla entonces estan mal las funciones esas, sino puede llegar a ser un problema del fprintf.
O tambien verificar los indices, por que me diste ya 2 indices distintos.
« Última modificación: 24 de Enero de 2017, 02:15:44 por KILLERJC »

Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Re:grados a decimales
« Respuesta #6 en: 24 de Enero de 2017, 02:28:15 »
......

Ahora si funciona!! :) Muchas gracias!! :-/ ((:-))

EDIT
Una ultima cosa, para no tragar entero, explícame por favor porque suma 2 y 3:
        ptrLat = &dat_GPRMC[2][0] + 2;
        ptrLong = &dat_GPRMC[4][0] + 3;

No entiendo porqué 2 y porqué 3
Gracias
« Última modificación: 24 de Enero de 2017, 02:35:54 por cvargcal »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:grados a decimales
« Respuesta #7 en: 24 de Enero de 2017, 04:53:56 »
No entiendo porqué 2 y porqué 3

Teniendo este string

Código: C
  1. dat_GPRMC[4][] = "07535.1974";

El primer elemento es:

Código: C
  1. dat_GPRMC[4][0] = '0'

La direccion donde esta almacenado el primer elemento es:

Código: C
  1. &dat_GPRMC[4][0]

Ahora viene la parte divertida. La direccion del segundo elemento es decir el '7' es:

Código: C
  1. &dat_GPRMC[4][1] o &dat_GPRMC[4][0] + 1.

En resumen por si no lo entendiste, lo que hago es guardar la direccion (mi puntero) del '3' que seria el 4to elemento, que se encuentra a 3 lugares mas a la derecha que mi primer elemento.
Voy a intentar hacer algo mas grafico

Código: [Seleccionar]
{ '0' , '7' , '5' , '3' , '5' , '.' , '1' , '9' , '7' , '4' , '\0' }
   |      |     |     |
   |      |     |     |
   |      |     |    +3
   |      |    +2
   |     +1
 &dat_GPRMC[4][0]

Entonces si ahora considero que una string comienza desde ese lugar y termina en el \0, entonces me queda que la string es: "35.1974" por que comienza desde ese otro punto.
El +2 en el otro caso es por que dijiste que la latitud solo poseia 2 valores asi y este poseia 3. Por eso dije que es valido solo si se respeta ese formato.


Desconectado cvargcal

  • PIC16
  • ***
  • Mensajes: 166
Re:grados a decimales
« Respuesta #8 en: 24 de Enero de 2017, 10:12:26 »
No entiendo porqué 2 y porqué 3

Teniendo este string
......

 :-/ Ahora sí, todo muy claro.
Muchas gracias.


 

anything