ATMega328 WDT sleep

From wikipost

For my wireless sensor nodes I have been using the ATmega328P-AU (TQFP) microcontrollers with great success. However, I wanted to make sure that I can get the power consumption down to a minimum whilst in sleep mode as these units will run off a 100mAh LiPo battery. Needless to say, the runtime of the device greatly depends on how low we can get the power consumption when the unit is in sleep mode.

Sleeping-bats.jpeg

The ATMega328 chip is the same as used in the Arduino Uno and should be compatible with the Duemilanove as only the form factor differs (TQFP vs DIP).

With the sketch loaded into the mcu I was able to get the power consumption down to around 5uA.

Brown-out detection is disabled, but if you need that for your project, expect the consumption to go up to about 23uA.




/*
  ATMega328 (same as in Arduino Duemilanove/Uno)

  Watchdog-timer sleep sketch

  Current in sleep mode: ~5uA  
  
 */

#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

#define LED 13

// the setup function runs once when you press reset or power the board
void setup() {
  
  // initialize LED pin as an output.
  pinMode(LED, OUTPUT);
  digitalWrite(LED,LOW);

}

// the loop function runs over and over again forever
void loop() {
  
  
  digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(100);              // wait for a second
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
  
  
  //enter sleep mode
  system_sleep();  
 
}




//initialize watchdog
void setup_watchdog(int ii) 
{
  // 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
  // 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec

  uint8_t bb;
  if (ii > 9 ) ii=9;
  bb=ii & 7;
  if (ii > 7) bb|= (1<<5);
  bb|= (1<<WDCE);

  MCUSR &= ~(1<<WDRF);
  // start timed sequence
  WDTCSR |= (1<<WDCE) | (1<<WDE);
  // set new watchdog timeout value
  WDTCSR = bb;
  WDTCSR |= _BV(WDIE);
}




// system wakes up when watchdog is timed out
void system_sleep() 
{

  ADCSRA = 0;                // switch Analog to Digitalconverter OFF
  
  setup_watchdog(9);         // approximately 8 seconds sleep

    /* The 5 different modes are:
          SLEEP_MODE_IDLE         -the least power savings
          SLEEP_MODE_ADC
          SLEEP_MODE_PWR_SAVE
          SLEEP_MODE_STANDBY
          SLEEP_MODE_PWR_DOWN     -the most power savings
     */
 
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here

  noInterrupts ();           // timed sequence follows
  sleep_enable();
 
  // turn off brown-out enable in software
  MCUCR = bit (BODS) | bit (BODSE);  // turn on brown-out enable select
  MCUCR = bit (BODS);        // this must be done within 4 clock cycles of above
  interrupts ();             // guarantees next instruction executed
  sleep_cpu ();              // sleep within 3 clock cycles of above

  sleep_disable();           // System continues execution here when watchdog timed out 

  ADCSRA = 1;                // switch Analog to Digitalconverter ON
}



// Watchdog Interrupt Service / is executed when watchdog timed out
ISR(WDT_vect)
{
 // nothing here
}