I'm trying to measure the voltage of the battery I use to power my Arduino Pro 3V3.
I have a resistor divider across the battery terminals (100K and 390K) and connect to A0, and set the analog reference to internal. I believe that the internal ref is 1.1V.
Clearly this is not right. I measured the battery under load as 3.5V. I measured the voltage divider as 0.7V which is close enough given the tolerance of the resistors.
Can anyone tell me what I am doing wrong? Is my assumption that the internal ref is 1.1V?
An A/D count of 224 with an input voltage of 0.7volt indicates that Aref hasn't switched to 1.1volt (yet).
Because 1024/224 * ~0.7 = ~3.2volt.
It should be ~750.
This is on the Aref page:
"After changing the analog reference, the first few readings from analogRead() may not be accurate"
The A/D is optimised for input impedances <10kohm.
With those high resistor values, you also need a 100n cap from the analogue input to ground.
And/or read the A/D twice, and use the second reading.
Your code could be compressed to
int A0adc;
float battVolts;
in void setup()
analogReference(INTERNAL);
A0adc = analogRead(A0); // dummy read
There is another approach, that avoids the external voltage divider completely. It uses the battery voltage as the reference and measures the internal voltage reference instead.
Every Arduino needs to be individually calibrated, because the internal reference (although very stable) is not calibrated.
const long InternalReferenceVoltage = 1062; // Adjust this value to your board's specific internal BG voltage
// Code courtesy of "Coding Badly" and "Retrolefty" from the Arduino forum
// results are Vcc * 100
// So for example, 5V would be 500.
int getBandgap ()
{
// REFS0 : Selects AVcc external reference
// MUX3 MUX2 MUX1 : Selects 1.1V (VBG)
ADMUX = bit (REFS0) | bit (MUX3) | bit (MUX2) | bit (MUX1);
ADCSRA |= bit( ADSC ); // start conversion
while (ADCSRA & bit (ADSC))
{ } // wait for conversion to complete (toss this measurement)
ADCSRA |= bit( ADSC ); // start conversion
while (ADCSRA & bit (ADSC))
{ } // wait for conversion to complete
int results = (((InternalReferenceVoltage * 1024) / ADC) + 5) / 10;
return results;
} // end of getBandgap
Works if you have the battery connected to the 5volt pin.
Does not work if you run the battery through the voltage regulator.
In that case you can only get a warning when the battery drops below MCU supply plus the dropout voltage of the regulator.
Leo..