Accurate adc conversion using a VCC from a battery?

I am building a power pack using two 18650's in series. The output
of the power pack will be adjustable via a switching buck regulator.
Just using it mostly for 5.0 and 3.3 volts.

I want to be able to measure one of the batteries using an analog to digital input
so i know when the pack is about to turn off.

Will VCC affect the accuacy of the measurement since it will be slowly
decreasing from 4 to 3 volts ?. I plan on using the 1.1 volt internal reference.

Accuracy will mainly depend on the stability of the 1.1 V reference.

Measuring only one voltage may not be sufficient. IMO you should build two voltage dividers, from the lower and upper battery + to the analog inputs, and build the difference from the lower and combined battery voltage for the state of the upper battery.

Does the stability of the 1.1 reference vary much with vcc ?
So if I understand, your saying the look at the difference between the two instead of just the
one battery. Will that minimize any error since its common to both?

If you think that both batteries unload in the same way then it's sufficient to measure the entire voltage of the battery pack.

See the data sheet for how the 1.1 V bandgap reference depends on voltage and temperature.

Did you see the Analog Comparator that operates continuously without using the ADC?

I did test to make sure the batteries I have tracked closely when being discharged.

I will take a look at the data sheet on the 1.1 ref.

I looked at the comparator but I don't see how it could be used unless I could put some
feedback on it. If I could I could measure the difference between the 1.1 volt ref and
the input from the battery, other wise it just outputs a high as my battery input will be
below the 1.1v reference. I want to get a feeling about how much charge is left in the battery.

Thanks for your help.

With the comparator again a voltage divider is required. But if you want to know how much capacity might remain then you need the ADC.

On which MCU board?

I've never seen any stability data or specification on the 1.1V internal reference. The initial value is +/- 10% and it has always been assumed to be "stable enough".

The voltage output of the 1.1V reference varied only slightly with Vcc, in the one test I did. But it is not calibrated, and can be anywhere between about 1.0 and 1.2V, so you need to measure it individually for each new chip.

If I could I could measure the difference between the 1.1 volt ref and
the input from the battery

This code does that:

// Read 1.1V reference against AVcc
// return battery voltage in millivolts
// must be individually calibrated for each CPU

int readVcc(void) {

  int result;

   ADCSRA = (1<<ADEN);  //enable and
   ADCSRA |= (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2);  // set prescaler to 128

  // set the reference to Vcc and the measurement to the internal 1.1V reference

   ADMUX = (1<<REFS0) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1);
   delay_ms(1); // Wait for ADC and Vref to settle

   ADCSRA |= (1<<ADSC); // Start conversion
   while (bit_is_set(ADCSRA,ADSC)); // wait until done
   result = ADC;
   // second time is a charm

   ADCSRA |= (1<<ADSC); // Start conversion
   while (bit_is_set(ADCSRA,ADSC)); // wait until done
   result = ADC;
   // must be individually calibrated for EACH BOARD

  result = 1148566UL / (unsigned long)result; //1126400 = 1.1*1024*1000
  return result; // Vcc in millivolts

ACK. Can the reference voltage also be read at the AREF pin?

Yes, this code causes the 1.1V reference to be output on AREF (on an Uno). There are other options on other Arduinos. Yet another option is to adjust the scale factor in the code until the battery voltage returned by the function agrees with the battery voltage as measured by a good multimeter.

void setup ()
  analogReference (INTERNAL);
  analogRead (A0);  // force voltage reference to be turned on
void loop () { }

Thanks for your perfect answer :slight_smile:

Thanks for the code jremington


You can find the AREF voltage with a potentiometer and accurate DMM, connect pot outside pins to Vcc and GND, measure wiper (center pin) voltage to GND with voltmeter and turn pot until volts = 0. Connect wiper to A0 pin and slowly turn pot until ADC value just changes from 1022 to 1023, read AREF voltage on meter.

1 Like

Thanks for that. That makes sense and even I can understand it : )

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.