Read arduino supply voltage, giving garbage on sleep?


Have tried all afternoon but cannot find out why, if I add a sleep function, the supply voltage reads as garbage, its ok if I don't use the sleep function ? It maybe the ADC is being turned off ?

Any help would be appreciated. :)



  Read arduino battery 
  Print to serial port the voltage 
  Sleep for 4 seconds

  int led = 13;

  ISR(WDT_vect) // watchdog interrupt
  wdt_disable();  // disable watchdog
void setup() 
  pinMode(led, OUTPUT);     

void loop() 
  Serial.println(" LED ON");
  digitalWrite(led, HIGH);   
  digitalWrite(led, LOW);    
  Serial.println(" LED OFF");
  readVcc() ; // Read Arduino  battery voltage
  Serial.print(" ");
  Serial.println( readVcc(), DEC );
  myWatchdogEnable (B0100000);  // Sleep 4 seconds //   *** Goes wrong when I add this line  ***

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;

void myWatchdogEnable(const byte interval)
  MCUSR = 0;                          // reset various flags
  WDTCSR |= 0b00011000;               // see docs, set WDCE, WDE
  WDTCSR =  0b01000000 | interval;    // set WDIE, and appropriate delay

  set_sleep_mode (SLEEP_MODE_PWR_DOWN); 
  sleep_mode();            // now goes to Sleep and waits for the interrupt

Have you tried doing a few analogRead()s in succession and discarding all but the last one?

It may also be worth trying a short wait between the reads.


myWatchdogEnable (B0100000)

You've only got 7 bits there. Did you miscount, or is that on purpose?

Anyway, I don't like the B defines. Change it to 0b00100000 if you want to use binary notation, it's the official C way of doing it. Of course, changing that doesn't change the problem. I'm trying some things out right now.


It looks like Serial.print() and Serial.println() are non-blocking functions. Apparently they just fill a TX buffer and let interrupts handle outputting the data. The trouble with your code is that right after you fill the TX buffer, you send it to sleep in the middle of transmitting. That's why you get garbled characters.

Solution, just put delay(10); after you print the characters to ensure the TX buffer gets transmitted out.

I noticed something weird when adding the WDT seemed to change the timing of transmitting the Serial messages. I added some Serial.println()s is various places to test before I figured it out.

I believe the ADC needs an extra analogRead() performed after reset or wake-up to stabilise anyway...

Solution, just put delay(10); after you print the characters to ensure the TX buffer gets transmitted out.

That's a band-aid, not a solution. The solution is one of the rare times when Serial.flush() is useful. flush() blocks until the outgoing buffer is empty, which is exactly what is needed in this case.

Thanks to you all for your help, funny thing is I just did a search and found Serial.flush() ; and it does work.

Then came on here to let you know and PaulS has just written about it :astonished: