Making Our Simple App Low Power
In this Lesson
- Using sleep modes to reduce power consumption.
- Active clock domains and wake-up sources in the different sleep modes.
- Using the Power Reduction Register to turn off the clocks to unused peripherals.
- AVR® Libc support for sleep modes.
- Choosing and setting a sleep mode.
- Enabling sleep, putting the CPU to sleep, and disabling sleep on waking up.
- A recommended application note, AVR4013: picoPower Basics.
In the last lesson, we used a pin change interrupt to determine whether a switch was pressed or not. The main benefit of using interrupts instead of polling a pin is that you are not keeping the microprocessor busy with one particular task and it gives us the opportunity to put the device into a low-power Sleep mode and dramatically reduce the power consumption of an application. This benefit is particularly important for battery-driven applications.
Procedure
1. Review the Datasheet
Review the datasheet for the ATmega328PBto determine which sleep modes are available.
Search for Sleep Modes in the datasheet and the section titled PM - Power Management and Sleep Modes will show the accompanying table. It shows what Sleep Modes are available to us based on which wake up sources we will be using. In our case, we are using PCINT so all of the Sleep Modes are available to us.
Of these Sleep Modes, the Power-down mode has the lowest current consumption. In this mode, the CPU and all peripherals are powered off, except for the asynchronous timer and external interrupts. In Power-down mode, the current consumption is typically around 100 nA at 1.8V and room temperature, making it ideal for battery-powered applications that require long battery life. We'll focus on implementing this Sleep Mode in our application.
2. Review the Compiler Guide
Review the MPLAB XC8 C Compiler User Guide for AVR for how to implement Power-down Sleep Mode
Open the MPLAB XC8 C Compiler User Guide for AVR MCU and search for "sleep". You should land on the section that describes the Sleep mode mmacro.
3. Implement the Code Changes
Make the changes needed in the code to implement Power Down sleep mode.
From Step 2 we see that we need to include the header file avr/sleep.h into our code which looks like this:
Then we need to implement this line above our while() loop inside our main()
Finally, we put the following code inside our while() loop so that we are always in Power-Down mode unless the interrupt occurs which wakes up the micro to service the ISR.
Now let's put it all together
#include <avr/interrupt.h>
#include <avr/sleep.h>
#define LED_ON PORTB |= (1<<PORTB5)
#define LED_OFF PORTB &= ~(1<<PORTB5)
#define LED_TOGGLE PINB |= (1<<PINB5)
#define SWITCH_PRESSED !(PINB & (1<<PINB7))
ISR(PCINT0_vect){
if(SWITCH_PRESSED) //If PINB7 is low
{
LED_ON;
}
else
{
LED_OFF;
}
}
int main(void) {
DDRB |= (1 << PB5); // set PB5 as output pin
DDRB &= ~(1<<DDB7); //set PB7 as an input pin
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
PCMSK0 |= (1<<PCINT7);
PCICR |= (1<<PCIE0);
sei();
while (1) {
sleep_mode();
}
}
4. Program the Device
- Select the Program button from the top menu
The application should display the same behavior when the button is pressed. What you do not see, without some method to measure it, is that when the button is not pressed, the micro is drawing significantly less current.
For more information and details about low power, view the app note AVR4013.