TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: migsantiago en 11 de Mayo de 2014, 18:35:44

Título: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: migsantiago en 11 de Mayo de 2014, 18:35:44
Hola

Estoy usando un PIC18F26K20 y el XC8 v1.30. Incluí la librería math.h y puse el linker para trabajar con float/double de 32 bits. Estoy llamando funciones sin/cos/acos en mi código y los resultados son aproximadamente correctos. Aún asú, la precisión no me es suficiente, es menor a la de una PC. Uso lo anterior en esta funcón de cálculo de distancias GPS:

Código: [Seleccionar]
float SIM_GPS_Distance(float lat1, float lon1, float lat2, float lon2)
{
   float theta;
   float dist;

   theta = lon1 - lon2;

   lat1 = SIM_Degree_to_Radian(lat1);
   lat2 = SIM_Degree_to_Radian(lat2);
   theta = SIM_Degree_to_Radian(theta);

   dist = (sin(lat1) * sin(lat2)) + (cos(lat1) * cos(lat2) * cos(theta));
   dist = acos(dist);

// dist = dist * 180.0 / SIM_PI_VALUE;
// dist = dist * 60.0 * 1.1515;
// /* Convert to km */
// dist = dist * 1.609344;

   dist *= 6370.693486F;

   return (dist);
}

Cuando depuro con MPLAB X, obtengo estos datos:

Código: [Seleccionar]
dist = (sin(lat1) * sin(lat2)) + (cos(lat1) * cos(lat2) * cos(theta)); -----> 0.99999994
dist = acos(dist); -----> 3.452301E-4
dist *= 6370.693486F; -----> 2.1993551

El último valor me indica 2.2km, pero debería ser 0.

Ahora, el mismo código en una PC regresa:

Código: [Seleccionar]
dist = (sin(lat1) * sin(lat2)) + (cos(lat1) * cos(lat2) * cos(theta)); -----> 1
dist = acos(dist); -----> 0
dist *= 6370.693486F; -----> 0

0km, que son correctos.

Sé que las funciones trigonométricas son aproximaciones con tablas y otros algoritmos que hacen su cálculo eficiente, pero no me molestaría que ocuparan mucha ROM ni que fueran lentas con tal de obtener más precisión.

¿XC8 tiene forma de lograr lo anterior? ¿Podría usar alguna librería externa para mejorarlas?

¿Conviene usar un dsPIC on punto fijo mejor?

Gracias  :mrgreen:
Título: Re: XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: elgarbe en 11 de Mayo de 2014, 20:45:34
Tiro una idea al aire, no sé si lo que voy a decir es correcto o no, pero aqui va:

yo provaría calcular la distancia entre dos latitutdes/longitudes distintas y compararía con lo obtenido en la PC. Puede que el problema sea en la funcion ACOS cuando el argumento se hacerca a 1 y cuando no está tan cerca quizá la funcion funcione bien. En cuyo caso quizá podrías poner un if despues del ACOS, si es menor a un valor determinado le asignas 0 directamente. lo que quiero decir es que no creo que sea problema de presicion de las funciones en todo el rango, sino que las funciones no deben funcionar bien cuando el argumento se hacerca a 1 o 0...

saludos!
Título: Re: XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: migsantiago en 11 de Mayo de 2014, 21:03:43
Hola Elgarbe

También lo había pensado, el descartar valores muy pequeños... el detalles es que esos valores tan pequeños podrían equivaler a unos 20m por ejemplo. El objeto que estamos rastreando podría perderse en una zona así y pues no me gustaría redondear tan bruscamente el dato.

 :police:
Título: Re: XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: elgarbe en 11 de Mayo de 2014, 21:25:49
Entiendo... igual chequearía que realmente sea un problema de presicion del float...

otra cosa, los modulos GPS puede que no te den resolucion menor a 10-5 mts. tendrías que tener muchos stélites linkeados para que tengas buena resolucion...

Saludos!
Título: Re: XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: MGLSOFT en 11 de Mayo de 2014, 21:55:27
Es extraño, uso ese mismo PIC y calculo varias cosas con el (uso CCS) y nunca me dio problemas, es mas lo comparamos en los cálculos durante el desarrollo, haciendo los mismos cálculos en PC y la única diferencia la obtuvimos en el sexto decimal.
No habrá un bug en la librería del XC8 ?
Título: Re: XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: willynovi en 11 de Mayo de 2014, 22:21:46
Los FLoat siempre van a tener un error, y como dice mglsoft, en el sexto decimal ha comprobado eso, pero si tu multiplacas en el orden de los 1000, como lo haces en la última multiplicación, ese error lo tienes ahora en el segundo decimal.

Otro punto a tener en cuenta es que si multiplicas un float por otro float ese error se hace casa vez mayor.

Creo que no puedes comparar los datos con los que te da la PC, digo, no pretendas tener en el microcontrolador el mismo error que en la PC, los micros usados para PC hoy tienen funciones trigonometricas propias de él, y tu usas una libreria que implementa por software los calculos.

Estuve viendo que hay un algoritmo para estos cálculos, y que se usa justamente en microcontroladores que carecen de instrucciones especificas para calculos de trigonometrias, se llama CORDIC (http://en.wikipedia.org/wiki/Cordic).

No se como será el algoritmo de la libreria math, quizás sea ese mismo.
Título: Re: XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: willynovi en 11 de Mayo de 2014, 22:52:56
La AN660 habla sobre los errores que podes encontrarte cuando usas los float, Floating Point Math Functions (http://ww1.microchip.com/downloads/en/AppNotes/00660.pdf)

Título: Re: XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: Nocturno en 12 de Mayo de 2014, 01:43:46
Quizás con esta librería:
GNU Scientific Library (http://www.gnu.org/software/gsl/manual/html_node/)

En la que hay funciones trigonométricas:
Circular trigonometric functions (http://www.gnu.org/software/gsl/manual/html_node/Circular-Trigonometric-Functions.html#Circular-Trigonometric-Functions)
Título: Re: XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: Picuino en 12 de Mayo de 2014, 11:06:16
El problema está en los bits que utilizas.
Con 32 bits, tienes 8 de exponente y 24 de mantisa.

El error que vas a tener puedes calcularlo como:

1 - 2^-24 = 0,99999994039

Que es lo que has conseguido.

Para mejorar los resultados, puedes:
   1.- Pasarte a un PIC24 que creo que tiene soporte para coma flotante de 64 bits
   2.- Intentar calcular de otra forma el número, utilizando las reglas trigonométricas:
        http://people.math.sfu.ca/~cbm/aands/page_72.htm
       Teniendo en cuenta que la resolución se pierde en las sumas y restas
       (no se pierde resolución en las multiplicaciones y divisiones) y que la función
       coseno tiene una resta (pierde resolución cerca del valor cero, es mejor convertirla en ese caso a una función seno).

   3.- Buscar rutinas para coma flotante de 64 bits para PIC18 (creo que Suky había publicado unas, ahora no sé donde)
   4.- Hacer tu mismo las rutinas para 64 bits (poco recomendable)

La mejor resolución que vas a obtener para flotantes de 32 bits es de 1 en 16 millones.

Saludos.
Título: Re: XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: Picuino en 12 de Mayo de 2014, 11:16:35
Algo debe estar mal en el código, porque el error máximo con precisión de coma flotante de 32bits, debería ser de unos 3 metros.

¿Qué valores de latitud y longitud estás poniendo?

Saludos.
Título: Re: XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: Picuino en 12 de Mayo de 2014, 11:37:15
Fórmula:

http://es.wikipedia.org/wiki/F%C3%B3rmula_del_Haversine

d_lat = lat1 - lat2

d_lon = lon1 - lon2

cos(dist/R) = 1 - cos(d_lat) + cos(lat1) * cos(lat2) * (1-cos(d_lon))


dist = R * acos( 1 - cos(d_lat) + cos(lat1) * cos(lat2) * (1 - cos(d_lon)) )

R = radio de la tierra:

   Ecuatorial     6378100 m
   Polar            6356800 m 
   Medio           6371000 m

Saludos.
Título: Re: XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: migsantiago en 12 de Mayo de 2014, 22:26:56
Vaya que me dieron que leer. Gracias!

Tendré qué evaluar por qué camino irme. Por acá  (http://www.microchip.com/forums/m796612.aspx)también me recomendaron el Haversine.

Empezaré a ver qué onda.

Saludos!
Título: Re: XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: migsantiago en 12 de Mayo de 2014, 23:10:31
otra cosa, los modulos GPS puede que no te den resolucion menor a 10-5 mts. tendrías que tener muchos stélites linkeados para que tengas buena resolucion...

Sí, ése detalle es muy importante. Por el momento me estoy enfocando en la precisión de las trigonométricas.

Es extraño, uso ese mismo PIC y calculo varias cosas con el (uso CCS) y nunca me dio problemas, es mas lo comparamos en los cálculos durante el desarrollo, haciendo los mismos cálculos en PC y la única diferencia la obtuvimos en el sexto decimal.
No habrá un bug en la librería del XC8 ?

De hecho las aproximaciones trigonométricas me están dando un error en el octavo decimal, lo cual es bueno, muy bueno, pero no suficientemente bueno para mi cálculo.

El PIC no sabe nada de trigonometría, así que todo viene dado por el compilador y cómo aproxima los cálculos trigonométricos para ahorrar ROM. Sería interesante correr el mismo ejemplo pero con CCS para ver qué tanta precisión ellos aplican en sus funciones trigonométricas.

Creo que no puedes comparar los datos con los que te da la PC, digo, no pretendas tener en el microcontrolador el mismo error que en la PC, los micros usados para PC hoy tienen funciones trigonometricas propias de él, y tu usas una libreria que implementa por software los calculos.

Estuve viendo que hay un algoritmo para estos cálculos, y que se usa justamente en microcontroladores que carecen de instrucciones especificas para calculos de trigonometrias, se llama CORDIC (http://en.wikipedia.org/wiki/Cordic).

No se como será el algoritmo de la libreria math, quizás sea ese mismo.


De acuerdo Willynovi. Tomé como referencia los de la PC porque no sabía si el algoritmo como tal en el PIC estaba funcionando. Sí funciona, pero su margen de error viene dado por las aproximaciones trigonométricas usadas en XC8, no creo que sea por la precisión de 32 bits.

Voy a poner en segundo lugar al CORDIC en mis pruebas. Por ahora el Haversine tiene 2 votos a favor jeje.

En la que hay funciones trigonométricas:
Circular trigonometric functions (http://www.gnu.org/software/gsl/manual/html_node/Circular-Trigonometric-Functions.html#Circular-Trigonometric-Functions)

Gracias Manolo... el implementar las funciones trigonométricas desde cero será mi tercera opción. Tengo un aproximado de 25kB de ROM para quemar... a ver si caben.

El problema está en los bits que utilizas.
Con 32 bits, tienes 8 de exponente y 24 de mantisa.

El error que vas a tener puedes calcularlo como:

1 - 2^-24 = 0,99999994039

Se me hace extraño que el tamaño de 32 bits en los cálculos sea el que determine la calidad de los resultados. Afecta... sí, pero creo que va más por el lado de cómo XC8 implementa los cálculos trigonométricos. Una PC tiene su coprocesador que es súper preciso, pero XC8 implementa tablas de aproximaciones.

Algo debe estar mal en el código, porque el error máximo con precisión de coma flotante de 32bits, debería ser de unos 3 metros.

¿Qué valores de latitud y longitud estás poniendo?

Saludos.

El código es idéntico en el PIC y en la PC. En la PC también uso 32 bits. La diferencia es que la PC usa el coprocesador para trigonometría. Esto es lo que uso:

Código: [Seleccionar]
int main(int argc, char *argv[])
{
  float lat1 = 20.574570;
  float lon1 = -100.382116;
  float lat2 = 20.574570;
  float lon2 = -100.382116;
  
  float result;
  
  result = SIM_GPS_Distance(lat1, lon1, lat2, lon2);
  
  printf("%f\n", result);
  
  system("PAUSE");
  return 0;
}

Ambos datos son idénticos. No he hecho pruebas con metros de distancia, pero el cero de distancia es el que me preocupó.

Voy a hacer pruebas amigos. Gracias de nuevo por sus tips. Qué padre es el foro Todopic  :mrgreen:
Título: Re: XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: migsantiago en 13 de Mayo de 2014, 21:51:50
Hola

Acabo de probar el algoritmo de Haversine y me gustó mucho su rendimiento.

Les dejo el código. Hice pruebas con mapas de Google y calculadoras de distancia en línea. Hice los cálculos en la PC y en el PIC con 32 bits y ambos fueron muy aproximados entre ellos. Con double mejorarían, pero no se puede en el PIC.

El resultado sale en metros, pero lo pueden pasar a km modificando SIM_EARTH_RADIUS.

Saludos y muchas gracias  :mrgreen:

Código: [Seleccionar]
/**
 * Convert degrees to radians
 * @param x - degrees to convert
 * @return radians
 */
static inline float SIM_Degree_to_Radian(float x)
{
   return (x * 0.017453292F);
}

#define SIM_EARTH_RADIUS                     (6372797.560856F)

float SIM_GPS_Distance(float lat1, float lon1, float lat2, float lon2)
{
   float delta_lat;
   float delta_lon;
   float a;
   float c;
   float dist;

   lat1 = SIM_Degree_to_Radian(lat1);
   lat2 = SIM_Degree_to_Radian(lat2);

   delta_lat = SIM_Degree_to_Radian(lat2 - lat1);
   delta_lon = SIM_Degree_to_Radian(lon2 - lon1);

   a = sin(delta_lat / 2.0F) * sin(delta_lat / 2.0F) +
         cos(lat1) * cos(lat2) *
         sin(delta_lon / 2.0F) * sin(delta_lon / 2.0F);
   c = 2.0F * atan2(sqrt(a), sqrt(1.0F - a));
   dist = SIM_EARTH_RADIUS * c;

   return dist;
}
Título: Re: XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: Picuino en 14 de Mayo de 2014, 05:19:47
Con double mejorarían, pero no se puede en el PIC.

Se puede hacer que el pic calcule con más precisión a costa de más esfuerzo programando tus librerías para manejar punto flotante en el pic18.

Librerías de ejemplo:
gnu glibc:      http://www.gnu.org/software/libc/libc.html                  http://ftp.gnu.org/gnu/glibc
softfloat:       http://www.jhauser.us/arithmetic/SoftFloat.html          http://svnweb.freebsd.org/base/head/lib/libc/softfloat
Fdlibm:         http://www.netlib.org/fdlibm
Crlibm:         http://lipforge.ens-lyon.fr/www/crlibm/

En realidad las funciones trascendentes (seno, coseno, tangente, logaritmos, etc) no se implementan con tablas, sino con polinomios.
Hay unos polinomios especiales, denominados polinomios de Chebyshev, que tienen un error absoluto mínimo en la aproximación de funciones.
Esos son los que se utilizan para simular las diferentes funciones

Un ejemplo de implementación de la función seno con la librería fdlibm:
Código: [Seleccionar]
* ====================================================
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
 *
 * Developed at SunSoft, a Sun Microsystems, Inc. business.
 * Permission to use, copy, modify, and distribute this
 * software is freely granted, provided that this notice
 * is preserved.
 * ====================================================
 */

/* __kernel_sin( x, y, iy)
 * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
 * Input x is assumed to be bounded by ~pi/4 in magnitude.
 * Input y is the tail of x.
 * Input iy indicates whether y is 0. (if iy=0, y assume to be 0).
 *
 * Algorithm
 * 1. Since sin(-x) = -sin(x), we need only to consider positive x.
 * 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0.
 * 3. sin(x) is approximated by a polynomial of degree 13 on
 *    [0,pi/4]
 *            3            13
 *     sin(x) ~ x + S1*x + ... + S6*x
 *    where
 *
 * |sin(x)         2     4     6     8     10     12  |     -58
 * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x  +S6*x   )| <= 2
 * |  x            |
 *
 * 4. sin(x+y) = sin(x) + sin'(x')*y
 *     ~ sin(x) + (1-x*x/2)*y
 *    For better accuracy, let
 *      3      2      2      2      2
 * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
 *    then                   3    2
 * sin(x) = x + (S1*x + (x *(r-y/2)+y))
 */

#include "fdlibm.h"

#ifdef __STDC__
static const double
#else
static double
#endif
half =  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
S1  = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
S2  =  8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
S3  = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
S4  =  2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
S5  = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
S6  =  1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */

#ifdef __STDC__
double __kernel_sin(double x, double y, int iy)
#else
double __kernel_sin(x, y, iy)
double x,y; int iy; /* iy=0 if y is zero */
#endif
{
double z,r,v;
int ix;
ix = __HI(x)&0x7fffffff; /* high word of x */
if(ix<0x3e400000) /* |x| < 2**-27 */
   {if((int)x==0) return x;} /* generate inexact */
z =  x*x;
v =  z*x;
r =  S2+z*(S3+z*(S4+z*(S5+z*S6)));
if(iy==0) return x+v*(S1+z*r);
else      return x-((z*(half*y-v*r)-y)-v*S1);
}


Saludos.
Título: Re: XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: migsantiago en 14 de Mayo de 2014, 20:54:51
En realidad las funciones trascendentes (seno, coseno, tangente, logaritmos, etc) no se implementan con tablas, sino con polinomios.

Vaya Picuino, me siento rebasado con lo que algunos de ustedes llegan a saber. Gracias por dejar claro que se puede implementar todo en el PIC, justo como los algoritmos que Manolo también publicó.

Saludos  :angel:
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: BrunoF en 14 de Mayo de 2014, 22:59:26
En la Universidad era normal al ver aplicaciones de las Series de Taylor, ejemplos de aproximación para las funciones trigonométricas.

De hecho, recuerdo que Chaly29, hace muchos años, buscando una manera sencilla de implementar un seno y coseno en assembler, utilizó una serie de taylor para realizar el cálculo. Si hablamos sólo de seno y coseno, técnicamente sólo hace falta una de las dos implementar, ya que la otra se obtiene desplazando el ángulo en PI/2.

Saludos!
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: migsantiago en 14 de Mayo de 2014, 23:17:57
Me sigo sintiendo rebasado estimado Bruno.  :mrgreen:

Mi educación matemática no es tan fuerte, pero lo bueno es que siempre hay alguien que puede ayudarme.  :grin:
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: BrunoF en 14 de Mayo de 2014, 23:45:45
Pues tampoco me considero el haz de la matemática, aunque sí he padecido de muchísima, junto con álgebra y física durante mi formación, por lo que no sé si sentirme afortunado o no. :D

Técnicamente una serie no es más que un polinomio infinito (que obviamente uno hace finito al aplicarlo) y que sigue un determinado patrón. Por lo que no se aleja mucho de los polinomios que mencionó Picuino previamente. Las calculadoras científicas calculan las funciones trigonométricas por aproximación también, siguiendo métodos similares. No hay tablas, como bien dijo Picuino.

Saludos!!
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: migsantiago en 14 de Mayo de 2014, 23:47:40
Entendido  :mrgreen:

A veces yo preferiría haber sufrido más con las matemáticas jeje
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: AKENAFAB en 14 de Mayo de 2014, 23:51:29
Entendido  :mrgreen:

A veces yo preferiría haber sufrido más con las matemáticas jeje

Masoquista!!! :mrgreen:

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

La verdad yo me siento mas alejado matemáticamente  :oops: xD también me falto estudiarle mas en la escuela pero mucho,bueno en mate y otras  :D
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: migsantiago en 14 de Mayo de 2014, 23:52:21
Entendido  :mrgreen:

A veces yo preferiría haber sufrido más con las matemáticas jeje

Masoquista!!! :mrgreen:



jajajaj  :mrgreen:
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: Picuino en 15 de Mayo de 2014, 06:33:50
En la Universidad era normal al ver aplicaciones de las Series de Taylor, ejemplos de aproximación para las funciones trigonométricas.

De hecho, recuerdo que Chaly29, hace muchos años, buscando una manera sencilla de implementar un seno y coseno en assembler, utilizó una serie de taylor para realizar el cálculo. Si hablamos sólo de seno y coseno, técnicamente sólo hace falta una de las dos implementar, ya que la otra se obtiene desplazando el ángulo en PI/2.

Saludos!

Las series de taylor aproximan una función muy bien cerca del punto x=0
A medida que nos alejamos de ese punto, el error se va haciendo mayor.


Los polinomios de Chebyshev aproximan muy bien una función en todo un intervalo (por ejemplo de x=0 a x=PI/2)
Dentro de ese intervalo, el error absoluto se mantiene constante
Fuera de ese intervalo, el error se va haciendo mayor.

A la hora de aproximar una función en un intervalo (no en un punto), es mejor utilizar estos últimos.

Saludos.
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: Picuino en 15 de Mayo de 2014, 08:33:10
Chebyshev Polynomial Approximator Code Generator:

   http://www.goddard.net.nz/files/js/chebyshev/cheby.html


Ejemplo de función seno aproximada con grado 5:
Código: [Seleccionar]
const float my_sin_coefficients[] = {
  0.5692364413309924,
  -0.667166678115238,
  0.1111230022470422
};

float my_sin(float x) {

  float xt2 = x * 2;
  float b_5 = coefficients[2];
  float b_4 = b_5 * xt2;
  float b_3 = b_4 * xt2 + coefficients[1] - b_5;
  float b_2 = b_3 * xt2 - b_4;
  float b_1 = b_2 * xt2 + coefficients[0] - b_3;
  float b_0 = x * b_1 - b_2;
  return b_0;
}

Saludos.
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: RICHI777 en 15 de Mayo de 2014, 11:34:32
Perdón por el off-topic, Picuino es un lujo para el foro tener un forista como vos.

Saludos !
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: Picuino en 16 de Mayo de 2014, 18:58:11
Muchas gracias RICHI

Este tema me interesó mucho en su momento porque me apasionan las calculadoras y los métodos matemáticos que utilizan.

Más tarde descubrí que esos métodos (como los polinomios de Chebyshev), sirven para aproximar cualquier función que quieras.
Puedes utilizarlos para compensar la frecuencia de un oscilador con la temperatura (como en los TCXO), para linelizar el comportamiento de sensores (sondas de temperatura NTC, Termopares, LDR, etc.) y muchas más aplicaciones prácticas.
Merece la pena aprender un poco de estos polinomios. No es necesario meterse de lleno en las matemáticas que hay por debajo, basta con saber manejar un paquete de matemáticas y llamar a la función que te da los coeficientes.

Saludos.
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: RICHI777 en 16 de Mayo de 2014, 18:59:49
Muchas gracias RICHI

Este tema me interesó mucho en su momento porque me apasionan las calculadoras y los métodos matemáticos que utilizan.

Más tarde descubrí que esos métodos (como los polinomios de Chebyshev), sirven para aproximar cualquier función que quieras.
Puedes utilizarlos para compensar la frecuencia de un oscilador con la temperatura (como en los TCXO), para linelizar el comportamiento de sensores (sondas de temperatura NTC, Termopares, LDR, etc.) y muchas más aplicaciones prácticas.
Merece la pena aprender un poco de estos polinomios. No es necesario meterse de lleno en las matemáticas que hay por debajo, basta con saber manejar un paquete de matemáticas y llamar a la función que te da los coeficientes.

Saludos.

+1
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: jhozate en 28 de Julio de 2014, 19:37:25
hola, estoy usando en ccs el código que implementó migsantiago , según las coordenadas que uso en google maps   hay 96 metros, cuando compilo en el micro la función me retorna 68.58m, tambien lo probé con distancias mas grandes de 3.8km segun google maps y el micro devuelve 2.7km.
pongo el código por si ven algo raro

Código: [Seleccionar]
#INCLUDE <24FJ64GA002.h>
#INCLUDE <MATH.H>
#FUSES ICSP1, NOWDT, NODEBUG, NOPROTECT, NOJTAG, FRC, NOWINDIS, NOPR, IOL1WAY, OSCIO, NOCKSFSM, NOIESO
#USE DELAY(clock=8000000)
 
#PIN_SELECT U2TX=pin_b2
#PIN_SELECT U2RX=pin_b3
#PIN_SELECT U1TX=pin_b5
#PIN_SELECT U1RX=pin_b4

#use rs232(baud=9600, Xmit=pin_b5, rcv=pin_b4,   STREAM=UART1)  //PC
#use rs232(baud=9600, Xmit=pin_B2, rcv=pin_b3,   STREAM=UART2) //GPS

#define SIM_EARTH_RADIUS   (6372797.560856)
   
FLOAT LAT1=3.427318;
FLOAT LON1=-76.499700 ;
FLOAT LAT2= 3.427912;
FLOAT LON2=-76.499072;
 
float Degree_to_Radian(float x);
void SIM_GPS_Distance(float lat1, float lon1, float lat2, float lon2);



void main()
{

while(true)
{
SIM_GPS_Distance(lat1,lon1,lat2,lon2);

}

}



  float Degree_to_Radian(float x)
{
   return (x * 0.017453292);
}

void  SIM_GPS_Distance(float lat1, float lon1, float lat2, float lon2)
{
   float delta_lat;
   float delta_lon;
   float a;
   float c;
   float dist;

   lat1 = Degree_to_Radian(lat1);
   lat2 = Degree_to_Radian(lat2);

   delta_lat = Degree_to_Radian(lat2 - lat1);
   delta_lon = Degree_to_Radian(lon2 - lon1);

   a = sin(delta_lat / 2.0) * sin(delta_lat / 2.0) +
         cos(lat1) * cos(lat2) *
         sin(delta_lon / 2.0) * sin(delta_lon / 2.0);
   c = 2.0 * atan2(sqrt(a), sqrt(1.0 - a));
   dist = SIM_EARTH_RADIUS * c;

   FPRINTF(UART1,"%f",dist);
   while(1){}
   
}
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: migsantiago en 28 de Julio de 2014, 20:18:43
Hola Jhozate, ¿de qué precisión son los float en CCS?
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: RALF2 en 28 de Julio de 2014, 21:12:46
Hola Jhozate, ¿de qué precisión son los float en CCS?

32bits para float en ccs  :mrgreen:
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: migsantiago en 28 de Julio de 2014, 23:18:49
OK Ralf.

Jhozate, dale más precisión a estos números.

Código: [Seleccionar]
FLOAT LAT1=3.427318;
FLOAT LON1=-76.499700 ;
FLOAT LAT2= 3.427912;
FLOAT LON2=-76.499072;

Y a ver qué te devuelve el PIC.
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: RALF2 en 28 de Julio de 2014, 23:25:22
6 bits amigo es la precision  :mrgreen:
Los numeros que colocaste arriba los redondeara para que entren en 6bits que es la precision maxima para el float en ccs, sino mal recuerdo  ;-)

Pero claro utilizando el metodo del polinomio deberia mejorar la precision, esperemos los resultados de jhozate entonces a ver que tal  :mrgreen:
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: jhozate en 29 de Julio de 2014, 12:32:22
gracias por responder, a que te refieres con mejorar la precisión de los números?   las coordenadas las tomo enteras desde google maps

edit. parece ser que ya va bien el codigo, sigo haciendo pruebas y pongo los resultados :mrgreen:

edit2: pues bien,  para una distancia medida en google de 103m, el micro calcula 100, la calculadora en linea también devuelve 100m,  para un punto donde la calculadora en linea da 8.73km el micro calcula 8720m  ;-) .  
 
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: migsantiago en 29 de Julio de 2014, 22:33:26
gracias por responder, a que te refieres con mejorar la precisión de los números?   las coordenadas las tomo enteras desde google maps

edit. parece ser que ya va bien el codigo, sigo haciendo pruebas y pongo los resultados :mrgreen:

edit2: pues bien,  para una distancia medida en google de 103m, el micro calcula 100, la calculadora en linea también devuelve 100m,  para un punto donde la calculadora en linea da 8.73km el micro calcula 8720m  ;-) .  
 

Qué bueno :D

¿Qué cambiaste?

Me refería a dar más precisión a agregar más dígitos después del punto.
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: jhozate en 30 de Julio de 2014, 12:38:28
la primera vez compile el código tal cual como lo habías hecho tu y era cuando me daba un error bastante grande, lo único diferente que hice fue declarar dos float adicionales en donde guardo la conversión de las latitudes a radianes

Código: [Seleccionar]
void  SIM_GPS_Distance(float lat1, float lon1, float lat2, float lon2)
float lat1r,lat2r,d_lat,d_lon,a,c,d;
    
lat1r=deg2rad(lat1);
lat2r=deg2rad(lat2);
d_lat=deg2rad(lat2-lat1);
d_lon=deg2rad(lon2-lon1);
.
.
.

si uso directamente lat1 y lat2 para guardar ahí la conversión la distancia difiere mucho  :?
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: migsantiago en 30 de Julio de 2014, 21:17:41
Buen análisis Jhozate. Un saludo.  :mrgreen:
Título: Re: [RESUELTO] XC8 - Mejorar precisión de funciones trigonométricas
Publicado por: jhozate en 31 de Julio de 2014, 12:56:39
Buen análisis Jhozate. Un saludo.  :mrgreen:
:D
quizá cosas de compilador