Voltaje de batería "impreciso" (SOLUCIONADO)

Hola
Llevo una temporadita volviéndome loco con el medición desde arduino de la batería de 12V de plomo.
La instalación está hecha con un divisor de 100k a positivo y 50K a negativo y cada 2 minutos repaso el estado con este código

  //voltaje de bateria
#define BAT 3.133 // relacion voltaje/medidor

int sensor = analogRead(BATERIA);          // realizar la lectura A1

float value = (float)sensor * 5 / 1024;

value *= BAT; // BAT relacion entre la real

La batería se alimenta de una placa solar con un regulador que se estabiliza a 13.7 (hay medidor)

El problema. Cada vez me mide una cosa distinta aunque aproximada. estando estable a 13.7 según el medidor del regulador y varios testers (entre 13.65 y 13.80) el arduino me mide desde 13.25 a 14.1.
¿Hay algo que pueda hacer para solucionarlo?

Gracias y saludos

El error parte de cometer justamente la misma falla sistemática en la que todos incurrimos (me incluyo) al presuponer que la tensión con la que se alimenta el arduino será estable.
Justamente si algo no es estable es la tensión del regulador que si mal recuerdas esta conectada a AVref y por lo tanto cuando presupones que tiense 5V resulta que son 4.85, 4.93 etc etc. etc.

El arduino dispone de una fuente de referencia de 1.10 V y si usas un MEGA tiene de 1.00 y de 2.5 si mal recuerdo.
Estas tensiones de referencias son ESTABLES ante cambios de tension externa y son mas prácticas para obtener lecturas correctas.

Existe una rutina muy ingeniosa que te permite MEDIR o automedir la tensión del arduino y de ese modo QUITARTE el problema.
La busco y luego la comparto para que lo compruebes.

También puedes implementar un filtro por software, como el de Luis Llamas( un filtro de media móvil ).

Muchas gracias por vuestras respuestas.

Ahora veo que no es "fallo" mio.
Lo único para lo que me sirve esa medición es para saber si la batería ha bajado demasiado o si se ha roto. Pero con esas "tolerancias" en las mediciones es imposible saberlo.

surbyte espero con impaciencia esa respuesta. O cualquier otra que, aunque no sea precisa la medición, al menos nos pueda servir para tener una idea de como está la batería

Saludos y gracias a los 2

Hi,
Puedes tratar de anadirle un condensador de 0.1ufd a la entrada del puerto analogo para eliminar ruidos de electromagneticos. No dices que tipo de regulador usas pero tambien puedes anadirle un capacitor de 100ufd electrolitico y otro de 0.1ufd en paralalelo a la salida del regulador.

Esta es la rutina que he usado antes y realmente es muy precisa.

long readVcc() {
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
    ADMUX = _BV(MUX5) | _BV(MUX0);
  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
    ADMUX = _BV(MUX3) | _BV(MUX2);
  #else
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #endif  

  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring

  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH  
  uint8_t high = ADCH; // unlocks both

  long result = (high<<8) | low;

  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return result; // Vcc in millivolts
}

El valor expresado esta en milivolts pero divide x 1000 y estará en float.

Hola tauro0221. El regulador de la carga es un MPPT de 15A conectado a una placa solar de 150W. Si te refieres al regulador del arduino uno, es el propio. Lo alimento a través del jack con los 12V de la batería.

Gracias surbyte. Lo he estado mirando y me he perdido. No entiendo de donde saca el voltaje a medir. Parece que son puertos internos. Eso, entiendo, derivará a que yo use uno de los pins que revisa?. Resumiendo: no entiendo nada

Gracias y saludos

Ya he mirado por internet y...
En esta web lo explican perfectamente, pero sigo dudando de mis arduinos y/o de mi.
Tengo un mega que la patilla ARef con GND me marca 0,19. Espero que sea esa la patilla.
Hoy debo estar mas espeso que de costumbre y sigo sin pillar el truquillo

Saludos

Hi,
Aqui como dice esa la tutoria es que la referencia es usando los 5 voltios que alimentan al arduino y cualquier variacion se va a notar en las lecturas. Yo cuando quiero leer con precision uso un MCP1541 para alimentar A ref. Este mantiene una referencia constante de 4.096 sin importar las variaciones de los 5 voltios. otra cosa es que el voltaje que se usa para calcular la lecturas de las senales analogas la mayoria usan 5 voltios y no es asi. Yo leo el voltaje del arduino y uso ese valor que es normalmente 4.95. No es mucha la diferencia pero dependiendo que uno esta leyendo puede ser emnos precisa. Aqui si uno quire medir con precision entonces debe de usar un A/D externo ya sea de 12 bits o 16 bits.

@surbyte
¿Pero esto cómo se usa en un pin Analógico? A mi me lee demasiada variación (un 10%). ¿Esta función lo puede corregir?

Hi,
Aqui creo que esta pasando es ruido del systema ya que estas usando un divisor de voltaje conectado directamente al bateria. Recuerda que la referencia de las senales analogas usan los 5 voltios en la referencia. Quiere decir que cualquier variacion de los 5 voltios se va a notar el las lecturas. Para solucionar el problema yo usaria un regulador que baje el voltaje de 12 voltios a 5 voltios y se lo conecta a los 5 voltios del arduino.En esta forma cualquier variacioon del voltaje de 12 voltios no van a afectar los 5 voltios del arduino. Tu dices que tienes conectado el arduino directamente a los 12 voltios de la bateria.Posiblemente puedes anadirle un condesador electrolitico a los 12 voltios que alimenta al arduino. Para mi la mejor solucion es usar un regulador que te de 9 voltios y se lo instala por el Vin del arduino.

Gracias tauro0221 por las ideas, pero algo me falla.
El sistema cuenta con 500Ah de batería de 12V alimentado por un MPPT de 15A desde una placa solar de 150W. El consumo es de unos 1.5Ah continuo y no esta cerca de ningún otro sistema eléctrico. Y cerca me refiero a 2 o 3 kilómetros. El mppt mantiene muy estable la batería, exactamente a 13.7V (según varios testers entre 13.65 y 13.80 pero estables)
El sistema podría variar de noche, cuando la batería puede bajar hasta 12V según el mppt. Ahora mismo el arduino está alimentado con este regulador de 12 a 5 por la entrada del USB. Ahora tengo por mppt 13.7 y por arduino 13.31.
He probado a alimentar el arduino con varios convertidores, desde Vin, desde usb y desde el jack a 5, 9 y 12v. No pido precisión. Solo pido aproximación. Si el mppt mide 13.7 (el tester 13.75) que el arduino no me mida hoy 13.30 y mañana 14.2. Y alguna vez 13.69.

Probaré a poner algún condensador en la entrada de 12V antes del arduino como me indicas, pero no creo que esté ahí el error. Debe haber algo que haga "bailar" al puerto analógico.

Lo del Vref 1.1 no lo pillo pero sigo haciendo pruebas

Saludos

No entiendo de donde saca el voltaje a medir. Parece que son puertos internos. Eso, entiendo, derivará a que yo use uno de los pins que revisa?. Resumiendo: no entiendo nada

Disculpa he tenido malos dias y casi no he respondido.
Esa rutina en lugar te proveerá del verdadero valor de tu AVref que claramente no será 5.0V

El valor lo da en milivolts o sea supongamos 4855 mV o 4.855V
Entonces en tus cuentas tu usas asi

  //voltaje de bateria
#define BAT 3.133 // relacion voltaje/medidor

float Vref = readVcc()/1000;
int sensor = analogRead(BATERIA);          // realizar la lectura A1

float value = (float)sensor * Vref / 1024;

value *= BAT; // BAT relacion entre la real

Muchas gracias surbyte, pero tengo la duda con esa linea de la funcion readVcc()

   result = 1126400L / result; // Back-calculate AVcc in mV

En todos los sitios donde he leído algo sobre el tema, dicen que hay que cambiar el 1126400L por la relación medida con tester

Donde el valor 1126400L corresponde a 1.1 x 1024 x 1000. Para tener una precisión adecuada debemos medir la referencia 1.1V de nuestro Arduino con un polímetro para calibrar este valor. Este valor es independiente de Vcc, por lo que sólo hay que calibrar una vez.

También lo he leído en paginas en ingles y quiero entender que dicen lo mismo (mi ingles tiene un nivel de 0 a -1)
¿Donde se "mide" Vref?

Saludos y muchas gracias

Ese valor es el que corresponde a la fuente de referencia de 1.1Volts que puede no tener ese valor, asi que si tienes un buen tester y puedes leer dicho valor porque no poner lo que lees.
Imagina lees
1.098 para 3 1-2 digitos
1.0977 para 4 1/2 digitos
1.09769 para 5 1/2 digitos

entonces pondrías
Edito: había un error. El valor leído debe multiplicarse por 1023 y x 1000.
1.098 => 1123254UL
1.0977 => 1122947UL
1.09769 => 1122937UL

Cualquier cosa mira la guia de Luis Llamas ENTRADAS ANALÓGICAS MÁS PRECISAS MIDIENDO VCC EN ARDUINO

Hi,
Pregunta: Que precision estas buscando de las lecturas del voltaje de la bateria?

Gracias surbyte por tu ayuda. El enlace de Luis Llamas lo había puesto yo muy al principio del post. Pero mi pregunta era como mido, o mejor dicho, donde mido los 1.1V. En la web de Llamas no indica el "pin" donde medir.

Hola tauro0221 y gracias por tu interés. El nivel que busco es el de controlar la batería. Si la batería baja a 11V puedo pensar que no se ha cargado lo suficiente, pero si baja a 10,5... algo le pasa. Con la "resolución actual" de +-0.6V puedo tener la batería mal y tener un voltaje correcto para arduino. Una vez controlada la precisión, la curiosidad me puede.

En estos momentos, y después de muchas pruebas y a surbyte, he "ajustado" la precisión a +-0,15, lo cual ya es suficiente para mi, pero la curiosidad mató al gato.

Saludos

El pin de Referencia esta indicado como AREF y debes buscar el que corresponda a tu Arduino. Cuando no le dices nada, Arduino conecta AREF a VCC y de ahi su dependencia con lo que el regulador le diga.
Cuando le pones un IC o integrado de referencia o usas alguna de las referencias internas esto mejora sustancialmente.
Pero.. los valores siempre son teorícos o estadísticos y por eso conviene medirlo e indicar su verdadero valor teniendo en cuenta la precisión de tu multímetro o tester.

En un UNO. La indicación 21 corresponde al pin del ATmega328 que coincide con los demás.

Acá tienes un link con buena información al respecto Prometec la Referencia Analógica AREF

Hola surbyte. En el post 7, donde paso el link de la pagina de Luis Llamas, también digo que he medido Aref y gnd de un mega con un tester y que me daba 0.19V.
Lo que no he hecho a sido indicarle a Aref que que use el 1.1V con analogReference(INTERNAL1V1); porque entiendo que eso es para limitar la entrada en los pins Ax a 1.1, 2.56, 3.3 o 5v
Yo lo que quisiera es, lo ponen en casi todas las páginas que hablan del tema, medir el 1.1V de mi arduino para hacer que la lectura análoga sea lo mas precisa posible, aunque para el error que describí en este hilo lo doy por resuelto, la curiosidad es insaciable

Muchas gracias por tu interés y paciencia y saludos

Luego me fijo y comparto mi experiencia con la medición.

Bueno tal vez he equivocado mi explicación anterior asi que tuve que ponerme a entenderlo debidamente y mas aún cuando tengo un problema similar.

Cuando con la instrucción le dices

analogReference(INTERNAL);

AREF se desconecta de VCC, lees 0V practicamente y no lees 1.10V, pero ese valor se puede medir indirectamente.

Ya que el método de medir la tensión del procesador usa 1.1V cuando midas la batería obtendrás un dato. Supongamos 5045 mV

Sabemos que si tuvieras 1.10V a la entrada A0 del Arduino con una fuente de 5.0V entonces con analogRead(A0) leerías V = 1.10 = 5.00 * analogRead(A0) / 1023 entonces el valor analogRead para esos 1.10 volt sería 1.10/5.00 * 1023

1100/5000*1023 = 225 cuentas del ADC. Entonces 225 cuentas representa 1.10V si la fuente de referencia fuera 5.0V exactos.

pero resulta que ambos sabemos que en AREF no tienes 5.0V y si con tu tester/multímetro mides la tensión de salida del regulador resulta 5123mV (suponte).

Bueno, tenemos 5045 mV si la referencia fuera de 1.10V y 5123 mV con el tester. A quien le creemos? Pues obviamente al tester pero la anterior nos da un dato que no se puede olvidar y es que ambas lecturas debe coincidir, pero una da diferente (la segunda) porque no hay un pin para medir cuando mide realmente la tensión de referencia 1.10V.

El dato de 5045 mV suponiendo 1.10 V nos dice la cantidad de cuentas medidas por el ADC y el único error es que no tenemos 1.10V sino otro valor.

Entonces si miramos esto

1100/50451023 = cte = X/51231023 donde X es el valor que verdaderamente daría la misma lectura del tester si pudiéramos medir la referencia interna

los 1023 que estan en ambos miembros, se cancelan y nos queda

1100/5045 = X / 5123 => X = 1100 * 5123/5045= 1.117,00693

O sea que nuestro valor sería 1117007UL

Y si miras ese valor nos daría la tensión medida por el tester usando el Arduino.

cuando uses este valor en readVcc() la tensión que reporte será de 5123mV la misma que dice tu tester.