Buenos días, es mi primer post en este foro, pero llevo bastante tiempo informándome de dudas con antiguos posts y doy mi más sincera enhorabuena a todos aquellos que intentan ayudar constantemente a todos los usuarios de este foro.
Bueno vamos al grano, estoy haciendo un medidor de corriente para conectarlo a la salida de la batería del robot y comprobar el consumo total en cada instante de tiempo para saber la autonomía que le queda, el porcentaje de batería en cada momento y el consumo acumulado hasta el momento.
Estoy usando baterías LiFePO4 de 8 o 16 celdas (según robot) y como bien sabréis, las baterías no tienen una curva de tensión de carga-descarga en las que se pueda calcular fácilmente el consumo y la autonomía, ya que desde el 80% hasta el 20% aproximadamente entrega la misma tensión. Por tanto, usando un medidor de corriente CZH-LABS D-1085 de 50A (https://images-na.ssl-images-amazon.com/images/I/81fxkdlqZML.pdf) calculo una media de 1000 medidas de corriente (pasadas a mVoltios por el medidor) cada 10 segundos. Con esta parte del programa no hay ningún problema.
El problema viene cuando quiero enchufarlo a cargar y quiero que el programa diferencie entre un pico de tensión por frenada o perturbación y un pico de tensión cuando la batería está 100% cargada.
La forma en la que he pensado abordar este problema es activando un timer de 10 segundos mientras la entrada analógica de tensión (TensionIN = 1023) sea máxima. Si el timer cumple los 10 segundos registrando tensión máxima, dado que mi robot no va a hacer nunca una frenada de 10 segundos porque el terreno va a ser 100% llano en la totalidad de sus situaciones, saber que es porque está 100% cargado. Si no cumple ese tiempo (10 segundos) sabremos que el pico ha sido puntual.
En el caso de que la batería esté al 100%, quiero que siga midiendo pero muestre un 100% de batería y un 0.00 Ah de consumo hasta que la señal de tensión no sea máxima, que eso es fácil de hacer pero os lo digo para que tengáis más detalles.
En el caso de que el pico sea por frenada y no cumpla los 10 segundos, quiero que siga midiendo y que siga el bucle de forma normal.
Habréis notado que soy algo nuevo en esto así que mis dudas concretas son las siguientes:
-
¿Cómo debo estructurar la parte del programa de la tensión? ¿Con un "while" para tensión máxima y una activación del timer el dicho "while" y despues "if" para cada caso? ¿Dónde lo pongo?
-
¿Cómo puedo hacer para que en esos 10 segundos del timer, el programa siga midiendo normalmente?
Puede que sean dudas sencillas pero es mi "primer" programa así de extenso y me está costando estructurarlo bien. Me haríais un gran favor si me ordenárais la cabeza un poco.
MUCHIIIIIISIMAS GRACIAS DE ANTEMANO!
Espero haberme explicado bien, soy muy nuevo en este mundo comparado con vosotros pero intentaré ayudar en lo que pueda y sin ninguna duda, me mantendré informado de muchos posts que me sirvan de ayuda.
Un saludo
PD: Os facilito la parte del programa que tengo.
PD2: No sé si he insertado bien el código, no he encontrado el botón de "Insertar Código".
#include <EEPROM.h>
const int n = 100; // Número de veces a medir
float D1;
float D2; // transformación a corriente
int indice = 0; // indice de medida, 0-100
float totalD2 = 0; // total 100 medidas
float mediaD2 = 0; // media de las 100 medidas
const int eeAddress = 0;
float mediatotalD2 = 0;
int contador = 0;
float autonomia;
float consumo = 0;
int intervalo = 3600000;
float levelbattery = 15; // en Ah
float tempshs;
float porcentaje = 0;
unsigned long Tiempoprevio = 0;
union Float_byte {
float datoF;
byte datoB[4];
} unionFB;
const int CurrentIN = A0; // Entrada analógica 0
const int TensionIN = A1; // Entrada analógica 1
void setup() {
Serial.begin(9600) ; // Inicializa comunicación serie
//analogReadResolution(8) ; // Entrada analógica 8 bits (1024)
//porcentaje = EEPROM.read(eeAddress); // función para rescatar el
// último dato una vez reiniciado
unionFB.datoF = 0.0;
unionFB.datoB[0] = EEPROM.read(0);
unionFB.datoB[1] = EEPROM.read(1);
unionFB.datoB[2] = EEPROM.read(2);
unionFB.datoB[3] = EEPROM.read(3);
}
void loop() {
unsigned long Tiempo = millis();
int lect;
if (indice < n)
for (indice = 0; indice < n; indice++) {
delay(10); // para que lo haga en 10 segundos aprox
lect = analogRead(CurrentIN)-512; //Porque la medida tiene un offset de 2,5V (512 de 1023)
D1 = lect/10.23;
D2 = D1 * 125.0/100; // Valor en Amperios (1V = 25A), (1A = 0.04V)
totalD2 = totalD2 + D2; // acumulador de las medidas
}
else if (indice >= n && mediatotalD2 == 0) { // función para ejecutar las medias
mediaD2 = totalD2 / n; // media de las 100 medidas
mediatotalD2 = (mediatotalD2 + mediaD2); // sumatorio de medias
indice = 0; // retorno del indice a 0
totalD2 = 0; // retorno del total a 0
contador++; // incremento de uno del contador para sacar el total cada 10 iteraciones
}
else if (indice >= n && mediatotalD2 != 0) {
mediaD2 = totalD2 / n; // media de las 100 medidas
mediatotalD2 = (mediatotalD2 + mediaD2) / 2; // media de las medias
indice = 0;
totalD2 = 0;
contador++;
}
if (contador == 10) {
contador = 0;
totalD2 = 0;
consumo = (mediatotalD2 * Tiempo) / 3600000; // Cantidad de corriente respecto al tiempo
autonomia = levelbattery - consumo;
// guardar un float en la EEPROM en las posiciones 0-3
unionFB.datoF = consumo;
EEPROM.write(0, unionFB.datoB[0]);
EEPROM.write(1, unionFB.datoB[1]);
EEPROM.write(2, unionFB.datoB[2]);
EEPROM.write(3, unionFB.datoB[3]);
porcentaje = (autonomia/maxbattery)*100;
//EEPROM.write(eeAddress, autonomia); // guardamos la capacidad
// para poder tener registrado el último dato cuando
//se vuelva a iniciar el arduino
tempshs = Tiempo/3600000.00;
}
}