In this post, we are going to see a small curiosity that will allow us to obtain more precise measurements from our analog inputs.
It is not widely known that some Arduino models can measure their own supply voltage. This is valid for Arduino models based on AVR 168 and 328 processors.
To do this, the 1.1V reference, which is incorporated in most Arduino models, is used. We can use Arduino’s ADC to measure this reference and, by interpolation, measure the voltage at which Arduino is actually being powered.
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);
}
Where the value 1126400L corresponds to 1.1 x 1024 x 1000. To have adequate precision, we must measure the 1.1V reference of our Arduino with a multimeter to calibrate this value. This value is independent of Vcc, so it only needs to be calibrated once.
What is this for? Mainly to rectify ADC measurements and, thus, achieve more precise analog inputs than we would obtain without this rectification.
The ADC uses Arduino’s Vcc as a reference. Therefore, any variation in the supply voltage translates into a proportional error in the analog measurement.
By measuring the actual supply voltage, we can correct possible deviations due to variations in 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);
}
A small trick that can be useful when we need to perform more precise analog readings in Arduino, when the need for precision justifies the increase in code.
Download the Code
All the code from this post is available for download on Github.

