Entradas analógicas más precisas midiendo Vcc en Arduino


En esta entrada vamos a ver una pequeña curiosidad que nos va a permitir obtener mediciones de nuestras entradas analógicas más precisas.

Es algo poco conocido que algunos modelos de Arduino pueden medir su propio voltaje al que están alimentados. Esto es válido para los modelos de Arduino basados en procesadores AVR 168 y 328.

Para ello se emplea la referencia de 1.1V, que viene incorporada en la mayoría de modelos de Arduino. Podemos emplear el ADC de Arduino para medir esta referencia y, por interpolación, medir la tensión a la que realmente está alimentado Arduino.

long readVcc() {
	ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
	delay(2);
	ADCSRA |= _BV(ADSC);
	while (bit_is_set(ADCSRA, ADSC));
	
	long result = ADCL;
	result |= ADCH << 8;
	result = 1126400L / result; // Back-calculate AVcc in mV
	return result;
}

void setup() {
	Serial.begin(9600);
}

void loop() {
	Serial.println(readVcc(), DEC);
	delay(1000);
}

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.

Anuncio:

¿Para qué sirve esto? Principalmente para rectificar las mediciones de ADC y, así, conseguir unas entradas analógicas más precisas que las que obtendremos sin esta rectificación.

El ADC toma como referencia el Vcc de Arduino. Por tanto, cualquier variación en la tensión de alimentación se traduce en un error proporcional en la medición analógica.

Midiendo la tensión de alimentación real, podemos corregir las posibles desviaciones debidas a variaciones en Vcc.

long readVcc()
{
	ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
	delay(2);
	ADCSRA |= _BV(ADSC);
	while (bit_is_set(ADCSRA, ADSC));
	
	long result = ADCL;
	result |= ADCH << 8;
	result = 1126400L / result; // Back-calculate AVcc in mV
	return result;
}

void setup()
{
	Serial.begin(9600);
}

void loop()
{
	float vcc = readVcc() / 1000.0;
	float voltage = (analogRead(A0) / 1024.0) * Vcc;

	Serial.println(voltage);
	delay(1000);
}

Un pequeño truquito que nos puede ser de utilidad cuando necesitemos realizar lecturas analógicas más precisas en Arduino, cuando la necesidad de precisión justifique el incremento de código.

Si te ha gustado esta entrada y quieres leer más sobre Arduino puedes consultar la sección
tutoriales de Arduino

5 1 vote
Article Rating

Anuncio:

Previous Librería Arduino ColorConverter
Next Vue.JS 2.0, un gran alternativa a AngularJS
9 Comments
oldest
newest
Inline Feedbacks
View all comments
Oscar
3 years ago
Oscar
3 years ago
Reply to  Luis

Ok, muchas gracias!!

Jesús
3 years ago

Hola a todos.

Será que no me quedé con la copla. ¿Qué hace el primer sketch y que hace el segundo? O sea, con el primero vemos la tensión de referencia, pero ¿...con el segundo?

Gracias y saludos.

Jesús
3 years ago
Reply to  Luis

Gracias Luis. Lo probé y efectivamente funciona. Tan solo un pequeño bug. En el segundo sketch, te tira error al compilar debido a la variable Voltaje, la cual no está definida como tal, sino como voltaje (con minúscula). Solucionado ésto, funciona.

Gracias nuevamente.

Jose
3 years ago

Hola Luis,

Nota para Arduino nano.

El modelo nano tiene un diodo entre la entrada USB y Vcc por lo que si lo alimentamos por USB debemos tener en cuanta la caida de tension en el diodo.
Algunas copias del nano usan un diodo normal y he llegado a medir caidas de 0.8V, por lo que Vcc pasa a ser 4.2V en vez de 5V y esto produce por si solo un error de un 16% en las medidas si no lo corregimos con el procedimiento descrito en el articulo.

Un saludo

eusebio
3 years ago

donde se mide esta referencia?. muchas gracias por el artículo.