Thursday, December 11, 2014

Reducing Arduino’s Power Consumption Part 3

Welcome to part 3 of reducing Arduino's power consumption, a must watch series for anybody building a battery powered project with Arduino. In part 3 we will look at how to use the Watch Dog Timer like an alarm clock to wake Arduino up from sleep mode. We we also look at some additional techniques to save power.


*****************************************Arduino Code*************************************************
/*
Example program for using sleep modes and watch dog timer in Arduino. This example code was used in a sleep mode tutorial video on the ForceTronics YouTube Channel.
This code is open for anybody to use at their own risk*/
     
/*WDT BYTE variables for setting timer value
     WDTO_15MS
WDTO_30MS
WDTO_60MS
WDTO_120MS
WDTO_250MS
WDTO_500MS
WDTO_1S
WDTO_2S
WDTO_4S
WDTO_8S */
     
#include <avr/sleep.h>
//We use part of the WDT library, but have to use registers as well since library does not support interrupt mode for WDT
#include <avr/wdt.h> 

int led = 13; //variable for pin that the LED is on
int tog = 1; //variable that toggles between traditional delay() function and WDT sleep delay function

void setup() {
  wdt_disable(); //Datasheet recommends disabling WDT right away in case of low probabibliy event
   pinMode(led, OUTPUT); //set up the LED pin to output
}

void loop() {
  
  if(tog) { //use traditional delay function
    digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);               // wait 
    digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);       // wait 
    tog = 0; //toggle variable
  }
  else { //after blinking LED setup interrupt and then go to sleep. Note that sleep will only happen once sinc
    digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);   // turn the LED on (HIGH is the voltage level)//  
    digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
    delayWDT(WDTO_1S);   // Use WDT sleep delay function, argument is byte variable from WDT Library
    //delayWDT(0x06);      //Use WDT sleep delay function, argument is byte value that sets timer to 1 second
    tog = 1; //toggle variable
  }
   
}

//This function serves as a power saving delay function. The argument is a Byte type variable that is used to set the delay time
//The function sets up sleep mode in power down state. The function then sets up the WDT timer in interrupt mode and sets it.
//It then puts the Arduino to sleep for the set time. Upon wake up the WDT and sleep mode are shut off
void delayWDT(byte timer) {
  sleep_enable(); //enable the sleep capability
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //set the type of sleep mode. Default is Idle
  ADCSRA &= ~(1<<ADEN); //Turn off ADC before going to sleep (set ADEN bit to 0)
  WDTCSR |= 0b00011000;    //Set the WDE bit and then clear it when set the prescaler, WDCE bit must be set if changing WDE bit   
  WDTCSR =  0b01000000 | timer; //Or timer prescaler byte value with interrupt selectrion bit set
 // WDTCSR = 0b01000110; //This sets the WDT to 1 second
  wdt_reset(); //Reset the WDT 
  sleep_cpu(); //enter sleep mode. Next code that will be executed is the ISR when interrupt wakes Arduino from sleep
  sleep_disable(); //disable sleep mode
  ADCSRA |= (1<<ADEN); //Turn the ADC back on
}

//This is the interrupt service routine for the WDT. It is called when the WDT times out. 
//This ISR must be in your Arduino sketch or else the WDT will not work correctly
ISR (WDT_vect) 
{
  wdt_disable();
   MCUSR = 0; //Clear WDT flag since it is disabled, this is optional

}  // end of WDT_vect