He realizado un contador de pulsos que que coge valores de 2 contadores y además de dar valores de m3/h instantáneos, acumuladors,.... en una pantalla LCD, también los va grabando en una memoria SD.
Y todo bien hasta que llegó un día que uno de los contadores dejó de contar.
Venga revisar cableado, señales, .... hasta que al final caí de la burra. Al sumar a un float grande un múmero decimal muy pequeño, llega un momento que si el float alcanza cierto valor ya desprecia los decimales.
Pero hasta que llegué la problema ya os hacéis a la idea del tiempo que perdí intentando entender la causa
Para qeu hagáis pruebas probar con este código a modo ejemplo
float Factor_Contador = 0.25; // 4 pulsos -> 1 L para pasar de pulsos a m3
float m3_Contador_1=8191;// totalizador de m3 del contador
float m3_Contador_2=0;
float m3_Contador_2b=8191;
float m3_Contador_3=0;
void setup() { Serial.begin(9600); }
void loop() {
m3_Contador_1 = m3_Contador_1 + Factor_Contador/1000.0;
m3_Contador_2 = m3_Contador_2 + Factor_Contador/1000.0;
m3_Contador_3 = m3_Contador_2+m3_Contador_2b;
Serial.print("contador 1: "); Serial.print(m3_Contador_1,3);Serial.print(" // ");Serial.print("contador 3: "); Serial.println(m3_Contador_3,3);
}
// Curioso el contador 1 avanza más que el contador 3 hasta que llega a 8192 y ahí ya no suma más
¿alquien sabría como aumentar la precisión de un float? (si es que se puede).
Hola.
Float viene precisamente de eso: de que el punto decimal es "flotante". Esto quiere decir que puede representar números muy grandes o muy pequeños, pero la precisión es limitada. Digamos que dispones de ocho cifras y una más para indicar la posición del punto decimal. Las ocho cifras son 12345678. Si desplazamos el punto 8 posiciones podríamos representar 1234567800000000 y si desplazamos 8 posiciones negativas podríamos representar 0,12345678. Sin embargo, el primer número no va a poder modificar ninguna de las cifras (ceros) inferiores, porque sólo dispone de ocho modificables, así que aunque le sumáramos 90000 no se iba a enterar, porque no afecta a sus cifras "móviles". Del mismo modo, si al segundo número le sumamos 1, como sólo puede representar ocho cifras "móviles" perderemos un decimal de precisión por la derecha. No sé si me he explicado.
Ahora, a tu problema:
En C existe también el tipo double, que almacena números de 64 bits en punto flotante; pero creo que aunque arduino admite su declaración por no hacerte el feo, siguen siendo float, es decir 32 bits.
Un pequeño arreglo que te podría dar un poco más de margen para lo que propones sería trabajar con long o mejor, si no vas a usar negativos, unsigned long. Claro que, entonces deberíamos olvidarnos de los decimales. La solución sería trabajar todos tus datos en centilitros, convirtiendo a m3 cuando necesites representarlos:
unsigned long Factor_Contador = 25; // 4 pulsos -> 1 L
float cl_Contador_1=819100000;// totalizador de cl del contador
float cl_Contador_2=0;
float cl_Contador_2b=819100000;
float cl_Contador_3=0;
void setup() { Serial.begin(9600); }
void loop() {
cl_Contador_1 += Factor_Contador;
cl_Contador_2 += Factor_Contador;
cl_Contador_3 = cl_Contador_2 + cl_Contador_2b;
Serial.print("contador 1: ");
imprime_m3(cl_Contador_1);
Serial.print(" // contador 3: ");
imprime_m3(cl_Contador_3);
}
void imprime_m3(unsigned long cl){
Serial.print(cl / 100000);
Serial.print(","); // para chulos, ponemos coma en lugar de punto
Serial.print(cl % 100000);
}
El máximo número de centilitros en unsigned long serían 4.294.967.295, es decir 42.949,67295 metros cúbicos.
Si no es suficiente, otra opción es trabajar con un contador parcial de centilitros, y un total de metros cúbicos. Sumas al parcial, y cuando llegue al metro cúbico se lo traspasas al otro contador y se lo quitas al parcial.
Saludos.