// Calculates the VCC voltage in an Arduino Nano/Uno/Mega board using the internal bandgap reference.
// The user must measure the internal bandgap reference (InternalReferenceVoltage)
// using my function: Determine_internal_bandgap_voltage.
// Useful if using a battery to power the Arduino from pin 5V so we can measure the battery voltage.
// Also useful if a correct value of Vcc is needed for internal calculations.
// Works for 168/328 and mega boards.
// Made by Juan 02/2025.
// Based in a "retrolefty" original code.
// https://forum.arduino.cc/t/measurement-of-bandgap-voltage/38215/17
void setup()
{
Serial.begin(9600);
Serial.println("Welcome to the internal Vcc measurement tool.");
Serial.println("Measure the bandgap voltage with my other program.");
Serial.println();
delay(100);
}
void loop()
{
int Vcc = getVcc();
// Ver si es necesario promediar estos valores o dan más o menos lo mismo.
Serial.print("The Vcc voltage is (in mV) = ");
Serial.println(Vcc);
delay(1000);
}
int getVcc()
// Returns the Vcc voltage (in mV).
{
constexpr long InternalReferenceVoltage = 1056L; // Adjust this value to your boards specific internal BG voltage in mV.
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
// For mega boards
// REFS1 REFS0 --> 0 1, AVcc internal ref. -Selects AVcc reference
// MUX4 MUX3 MUX2 MUX1 MUX0 --> 11110 1.1V (VBG) -Selects channel 30, bandgap voltage, to measure
ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<ADLAR)| (0<<MUX5) | (1<<MUX4) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (0<<MUX0);
#else
// For 168/328 boards
// REFS1 REFS0 --> 0 1, AVcc internal ref. -Selects AVcc external reference
// MUX3 MUX2 MUX1 MUX0 --> 1110 1.1V (VBG) -Selects channel 14, bandgap voltage, to measure
ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<ADLAR) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (0<<MUX0);
#endif
delay(50); // Let mux settle a little to get a more stable A/D conversion
// Start a conversion
ADCSRA |= _BV( ADSC );
// Wait for it to complete
while( ( (ADCSRA & (1<<ADSC)) != 0 ) );
int result = ((InternalReferenceVoltage * 1024L) / ADC) + 5L; // calculates for straight line value.
return result;
}