How to know VCC voltage in arduino ?

I use AA battery for arduino . I want to display the battery voltage level in lcd , but how to know the vcc voltage ?

1 AA battery will not run an Arduino.

Tell use what model Arduino you want help with.

Weedpharma

The built-in A/D hardware of the ATmega328p can read the "1.1V" (1.0 to 1.2V) internal voltage standard. Once you calibrate the "1.1V" standard you can use that to calculate the VCC voltage.

long readVcc() {
  long result;
  // Read 1.1V reference against AVcc
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = 1126400L / result; // Back-calculate AVcc in mV
  return result;
}

Note: this code assumes the "1.1V" is exactly 1.1V. You should measure Vcc with an accurate meter and then adjust the constant to get the right result.

1 Like

weedpharma:
1 AA battery will not run an Arduino.

Tell use what model Arduino you want help with.

Weedpharma

I use 4 AA battery

  result |= ADCH<<8;
  result = 1126400L / result; // Back-calculate AVcc in mV

Looks like a typo in that last line? Should be "*=" ?

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

It looks correct to me. The analog reading 'result' is 1024 * (1100mV / Avcc)

For example, if Avcc == 5000mV you should get an analog reading of 225.

If you plug that into the formula: Avcc = 1126400L / 225 you get 5006mV or 5.006V. That is correct to three decimal places.

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

It looks correct to me. The analog reading 'result' is 1024 * (1100mV / Avcc)

Oops. I misread the division as the start of a comment, so I was seeing "result = constant" Hmmph. I'm not usually so bleary-eyed at only 0130...
Never mind.

This sketch will give you the value needed to calculate the internal voltage reference given the voltage at AREF. In my case the "1.1V" reference was actually 1.094238468V. Multiplying by 1024000 gave me a constant of 1120500UL.

void setup() {
  Serial.begin(9600);
  delay(1000);

  // Read "1.1V" reference against AREF
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA, ADSC));
  unsigned int reading = ADC;
  // unsigned int reading = ADCL | (ADCH << 8);
  float fraction = reading / 1024.0;
  Serial.println(F("Use a meter to measure the voltage between GND and AREF pins."));
  Serial.print(F("Multiply that voltage by "));
  Serial.print(fraction, 7);
  Serial.println(F(" to get the value of the internal voltage reference."));
  Serial.println(F("Then multiply that by 1204000 to get the constant to use in readVCC()."));

  // unsigned long VCC = 1120500UL / reading;
}

void loop() {}

Hello, @johnwasser. I tried to measure the internal voltage reference with your method for my Arduino Uno board and noticed that at different supply voltages, different calculated Vref values are obtained. At Vcc = 3.00V internal Vref = 1098 mV, at Vcc = 4.00V internal Vref = 1090 mV, at Vcc = 5.00V internal Vref = 1079 mV. Why is it so? Do you know anything on this subject?

Just what I read in the datasheet.

It looks like a variance of about 2 millivolts (+/-0.001V) across the 3 to 5V range is normal. The '1.1V' bandgap voltage reference is also temperature sensitive: about 12 mV across the -40 to +80°C range.

If you need higher accuracy you should probably be investing in a precision external A/D converter.

Thanks for the answer. I think that this is quite enough for measuring the battery voltage.

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