3.1.11 Using Sleep Mode

Power consumption has been reduced, but the CPU is still actively doing nothing. To benefit from an interrupt-driven model, the CPU can be put to sleep while waiting for interrupts. In addition, we will power-down all peripherals not used to further reduce power consumption. The code below is included in project low_power_103.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/power.h>

ISR (TIMER2_OVF_vect)
{
    if (PORTB == 0x00) {
        // LED is OFF, turn it on
        PORTB = (1 << 5);
        // Shortened timeout for on cycle
        TCNT2 = 0x102;
    }
    else {
        // LED is ON, turn it off
        PORTB = 0x00;
    }
}

int main(void)
{
    // Disable digital input buffer on ADC pins
    DIDR0 = (1 << ADC5D) | (1 << ADC4D) | (1 << ADC3D)
    | (1 << ADC2D) | (1 << ADC1D) | (1 << ADC0D);
    // Disable digital input buffer on Analog comparator pins
    DIDR1 |= (1 << AIN1D) | (1 << AIN0D);
    // Disable Analog Comparator interrupt
    ACSR &= ~(1 << ACIE);
    // Disable Analog Comparator
    ACSR |= (1 << ACD);
    // Disable unused peripherals to save power
    // Disable ADC (ADC must be disabled before shutdown)
    ADCSRA &= ~(1 << ADEN);
    // Shut down the ADC
    power_adc_disable();
    // Disable SPI 
    power_spi_disable();
    // Disable TWI
    power_twi_disable();
    // Disable the USART 0 module
    power_usart0_disable();
    // Disable the Timer 1 module
    power_timer1_disable();
    // Disable the Timer 0 module
    power_timer0_disable();

    // Change the clock prescaler
    CLKPR = (1 << CLKPCE);
    // Scale by DIV64
    CLKPR = (1 << CLKPS2) | (1 << CLKPS1) | (0 << CLKPS0);
    // Port B5 to output
    DDRB = (1 << 5);
    // Timer2 DIV 1024 
    TCCR2B = (1 << CS22) | (1 << CS21) | (1 << CS20); 
    // Overflow interrupt enable
    TIMSK2 = (1 << TOIE2); 
    // Interrupts on
    sei();
    while (1) {
        set_sleep_mode(SLEEP_MODE_PWR_SAVE);
        sleep_mode();
    }	
}
Todo:
  • Build the project/solution (F7)
  • Program the application into the target device using Start Without Debugging (Ctrl+Alt+F5)
  • Switch to Data Visualizer to see the results
Important: Because the previous example prescaled the clock to 8 MHz/64, the ISP programming clock must be set to less than 32 kHz to be below 1/4 of the main clock.
Important: Remember to disable on-board power on the Xplained Mini.
What can we see from this plot?
  • The kit now draws less than 1 mA with the LED OFF
  • Current draw increases to about 7 mA when the LED is pulsed ON
  • The 1% duty cycle still seems approximately correct
Result: Power consumption has again been improved by using Sleep mode and disabling unused peripherals.