2

I need to monitor a battery plugged to an ATmega running on standalone mode.

I use the "ATmega on a breadboard (8 MHz internal clock)" bootloader. More info here

When the ATmega is powered with 5V the sketch outputs good values : arround 5100 mV.

But when I power it with 3.3V the sketch gives strange values : arround 178619 mV.

Here is my code Inspired from here

void setup() 
{ 
  Serial.begin(9600);
  Serial.println(F("Internal Voltage Sensor"));
}

void loop() 
{ 
  Serial.println( readVcc()); 
  delay(1000); 
} 

long readVcc() 
{
  long voltage=0;
  uint8_t wADC;

  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  ADCSRA |= _BV(ADEN);  // enable the ADC

  delay(20); // Wait for Vref to settle

  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring

  // Reading register "ADCW" takes care of how to read ADCL first and ADCH then.
  wADC = ADCW;

  voltage = 11253000L / wADC; // Calculate Vcc (in mV); 1125.3 = 1.1*1023*1000
  return voltage; // Vcc in millivolts
}

I don't understand what's going on. The returned value with Vcc=3.3V should be lower than with VCC=5V. Something like 3300 mV !

Michel Keijzers
  • 13,014
  • 7
  • 41
  • 58

1 Answers1

2

Thanks for your answers! Jot gave the solution: wADC must be a uint16_t.

Here is the corrected code :

void setup() 
{ 
  Serial.begin(9600);
  Serial.println(F("Internal Voltage Sensor"));
}

void loop() 
{ 
  Serial.println(readVcc()); 
  delay(1000); 
} 

long readVcc() 
{
  long voltage=0;
  uint16_t wADC;

  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  ADCSRA |= _BV(ADEN);  // enable the ADC

  delay(20); // Wait for Vref to settle

  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring

  // Reading register "ADCW" takes care of how to read ADCL first and ADCH then.
  wADC = ADCW;

  voltage = 1125300L / wADC; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return voltage; // Vcc in millivolts
}