Secret Arduino Voltmeter

About: ProvideYourOwn.com is a website devoted to people who want to make their own things and provide for their own needs. We provide information, encouragement and resources to empower people to become free from ...
A little known feature of many AVR chips is the ability to measure the internal analog voltage reference. This trick can be used in all sorts of ways such as:
  • Monitoring battery voltage to your Arduino
  • Checking to see if A/C power is running
  • Improve accuracy of analogRead() in many situations
The way to perform these feats is use the internal reference to actually measure Vcc. In the code following, we will actually measure the internal voltage reference, and then use this value to calculate our actually Vcc. Here is the code:

long readVcc() {
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
     ADMUX = _BV(MUX5) | _BV(MUX0) ;
  #else
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #endif  
 
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring
 
  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH  
  uint8_t high = ADCH; // unlocks both
 
  long result = (high<<8) | low;
 
  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return result; // Vcc in millivolts
}
There are some limitations in accuracy due to tolerances on the internal voltage reference. You can however, calibrate the scale factor for greater accuracy. This code runs on all Arduino variants as well as the ATtinyx4 series chips.

For a more in-depth article, which includes calculation details, applications and calibration how-to, see Secret Arduino Voltmeter – Measure Battery Voltage.

Share

    Recommendations

    • First Time Author

      First Time Author
    • Make it Glow Contest 2018

      Make it Glow Contest 2018
    • Toys Contest

      Toys Contest

    4 Discussions

    0
    None
    latestrevisionmajrooo

    Reply 2 years ago

    I'm sure you already sorted this out on your own, but, for future readers, you can use the same calculation used for the ATmega1280 for the ATmega1284.

    0
    None
    ooda55james34602

    Reply 5 years ago on Introduction

    Yes, with the appropriate voltage divider. The chip must only receive max 5 volts on the ADC.