Skip to content

Instantly share code, notes, and snippets.

@JChristensen
Last active August 15, 2024 14:22
Show Gist options
  • Save JChristensen/5616922 to your computer and use it in GitHub Desktop.
Save JChristensen/5616922 to your computer and use it in GitHub Desktop.
AVR microcontroller sleep demonstrations
Simple demonstrations of putting AVR microcontrollers to sleep in power-down mode,
which results in minimum current. Coded with Arduino IDE version 1.0.4 (and with
the Arduino-Tiny core for the ATtiny MCUs, http://code.google.com/p/arduino-tiny/)
For ATmega328P, ~0.1µA.
For ATtinyX5 revisions that implement software BOD disable, ~0.1µA,
for ATtinyX5 revisions that don't, ~20µA.
/*----------------------------------------------------------------------*
* Sleep demo for ATmega328P. *
* Wire a button from digital pin 2 (INT0) to ground. *
* Wire an LED with an appropriate dropping resistor from pin D13 to *
* ground. *
* Pushing the button wakes the MCU. *
* After waking, the MCU flashes the LED, then waits 10 seconds before *
* going back to sleep. *
* *
* Jack Christensen 07May2013 *
* *
* Tested with Arduino 1.0.5 and an Arduino Uno. *
* Test conditions for all results below: *
* 5V regulated power supply, fed to the Vin pin *
* 16MHz system clock *
* Fuse bytes (L/H/E): 0xFF / 0xDE / 0x05 *
* Optiboot bootloader *
* *
* Uno R1 *
* 38mA active, 26mA with MCU in power-down mode. *
* *
* Uno SMD edition *
* 42mA active, 31mA power-down. *
* *
* Adafruit Boarduino *
* Power select jumper set to "USB", USB (FTDI) not connected. *
* 15mA active, 3mA power-down. *
* *
* Adafruit Boarduino without power LED *
* 12mA active, 0.1µA power-down. *
* *
* Breadboarded ATmega328P-PU *
* 12mA active, 0.1µA power-down. *
* *
* This work is licensed under the Creative Commons Attribution- *
* ShareAlike 3.0 Unported License. To view a copy of this license, *
* visit http://creativecommons.org/licenses/by-sa/3.0/ or send a *
* letter to Creative Commons, 171 Second Street, Suite 300, *
* San Francisco, California, 94105, USA. *
*----------------------------------------------------------------------*/
#include <avr/sleep.h>
const int LED = 13; //LED on pin 13
const unsigned long KEEP_RUNNING = 10000; //milliseconds
void setup(void)
{
//to minimize power consumption while sleeping, output pins must not source
//or sink any current. input pins must have a defined level; a good way to
//ensure this is to enable the internal pullup resistors.
for (byte i=0; i<20; i++) { //make all pins inputs with pullups enabled
pinMode(i, INPUT_PULLUP);
}
pinMode(LED, OUTPUT); //make the led pin an output
digitalWrite(LED, LOW); //drive it low so it doesn't source current
}
void loop(void)
{
for (byte i=0; i<5; i++) { //flash the LED
digitalWrite(LED, HIGH);
delay(100);
digitalWrite(LED, LOW);
delay(100);
}
delay(KEEP_RUNNING); //opportunity to measure active supply current
digitalWrite(LED, HIGH); //one blink before sleeping
delay(100);
digitalWrite(LED, LOW);
goToSleep();
}
void goToSleep(void)
{
byte adcsra = ADCSRA; //save the ADC Control and Status Register A
ADCSRA = 0; //disable the ADC
EICRA = _BV(ISC01); //configure INT0 to trigger on falling edge
EIMSK = _BV(INT0); //enable INT0
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
cli(); //stop interrupts to ensure the BOD timed sequence executes as required
sleep_enable();
//disable brown-out detection while sleeping (20-25µA)
uint8_t mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE);
uint8_t mcucr2 = mcucr1 & ~_BV(BODSE);
MCUCR = mcucr1;
MCUCR = mcucr2;
//sleep_bod_disable(); //for AVR-GCC 4.3.3 and later, this is equivalent to the previous 4 lines of code
sei(); //ensure interrupts enabled so we can wake up again
sleep_cpu(); //go to sleep
sleep_disable(); //wake up here
ADCSRA = adcsra; //restore ADCSRA
}
//external interrupt 0 wakes the MCU
ISR(INT0_vect)
{
EIMSK = 0; //disable external interrupts (only need one to wake up)
}
/*----------------------------------------------------------------------*
* Sleep demo for ATtinyX4. *
* Wire a button from pin D2 (INT0, PB2, DIP pin 5) to ground. *
* Wire an LED with an appropriate dropping resistor from pin *
* D0 (PB0, DIP pin 2) to ground. *
* Pushing the button wakes the MCU. *
* After waking, the MCU flashes the LED, then waits 10 seconds before *
* going back to sleep. *
* *
* Jack Christensen 04Nov2013 *
* *
* Developed with Arduino 1.0.5. *
* Test conditions for all results below: *
* 5V or 3.3V regulated power supply *
* 8MHz system clock (internal RC oscillator) *
* Fuse bytes (L/H/E): 0xE2 / 0xD5 / 0xFF *
* Arduino-Tiny core, http://code.google.com/p/arduino-tiny/ *
* *
* ATtiny84A-PU *
* Vcc=5V: 4.9mA active, 0.1µA power-down. *
* Vcc=3.3V: 3.1mA active, 0.1µA power-down. *
* *
* This work is licensed under the Creative Commons Attribution- *
* ShareAlike 3.0 Unported License. To view a copy of this license, *
* visit http://creativecommons.org/licenses/by-sa/3.0/ or send a *
* letter to Creative Commons, 171 Second Street, Suite 300, *
* San Francisco, California, 94105, USA. *
*----------------------------------------------------------------------*/
#include <avr/sleep.h>
const int LED_PIN = 0;
const unsigned long KEEP_RUNNING = 10000; //milliseconds
void setup(void)
{
//to minimize power consumption while sleeping, output pins must not source
//or sink any current. input pins must have a defined level; a good way to
//ensure this is to enable the internal pullup resistors.
for (byte i=0; i<11; i++) { //make all pins inputs with pullups enabled
pinMode(i, INPUT_PULLUP);
}
pinMode(LED_PIN, OUTPUT); //make the led pin an output
digitalWrite(LED_PIN, LOW); //drive it low so it doesn't source current
}
void loop(void)
{
for (byte i=0; i<5; i++) { //wake up, flash the LED
digitalWrite(LED_PIN, HIGH);
delay(100);
digitalWrite(LED_PIN, LOW);
delay(100);
}
delay(KEEP_RUNNING); //opportunity to measure active supply current
digitalWrite(LED_PIN, HIGH); //blink LED once before sleeping
delay(100);
digitalWrite(LED_PIN, LOW);
goToSleep();
}
void goToSleep(void)
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
MCUCR &= ~(_BV(ISC01) | _BV(ISC00)); //INT0 on low level
GIMSK |= _BV(INT0); //enable INT0
byte adcsra = ADCSRA; //save ADCSRA
ADCSRA &= ~_BV(ADEN); //disable ADC
cli(); //stop interrupts to ensure the BOD timed sequence executes as required
byte mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE); //turn off the brown-out detector
byte mcucr2 = mcucr1 & ~_BV(BODSE);
MCUCR = mcucr1;
MCUCR = mcucr2;
sei(); //ensure interrupts enabled so we can wake up again
sleep_cpu(); //go to sleep
sleep_disable(); //wake up here
ADCSRA = adcsra; //restore ADCSRA
}
//external interrupt 0 wakes the MCU
ISR(INT0_vect)
{
GIMSK = 0; //disable external interrupts (only need one to wake up)
}
/*----------------------------------------------------------------------*
* Sleep demo for ATtinyX5. *
* Wire a button from pin D2 (INT0, PB2, DIP pin 7) to ground. *
* Wire an LED with an appropriate dropping resistor from pin *
* D4 (PB4, DIP pin 3) to ground. *
* Pushing the button wakes the MCU. *
* After waking, the MCU flashes the LED, then waits 10 seconds before *
* going back to sleep. *
* *
* Jack Christensen 07May2013 *
* *
* Developed with Arduino 1.0.4. *
* Test conditions for all results below: *
* 5V regulated power supply *
* 8MHz system clock (internal RC oscillator) *
* Fuse bytes (L/H/E): 0xE2 / 0xD5 / 0xFF *
* Arduino-Tiny core, http://code.google.com/p/arduino-tiny/ *
* *
* Note that only the ATtinyX5 devices below have BOD disable *
* functionality implemented. With Vcc=5V, the BOD will draw *
* 20-25µA, depending on temperature. *
* ATtiny25, revision E, and newer *
* ATtiny45, revision D, and newer *
* ATtiny85, revision C, and newer *
* *
* ATtiny45V-10PU, Rev. G *
* 7.4mA active, 0.1µA power-down. *
* *
* ATtiny85V-10PU, Rev. B *
* 7.1mA active, 21µA power-down. *
* *
* This work is licensed under the Creative Commons Attribution- *
* ShareAlike 3.0 Unported License. To view a copy of this license, *
* visit http://creativecommons.org/licenses/by-sa/3.0/ or send a *
* letter to Creative Commons, 171 Second Street, Suite 300, *
* San Francisco, California, 94105, USA. *
*----------------------------------------------------------------------*/
#include <avr/sleep.h>
#define LED 4 //LED on pin 4, PB4, DIP pin 3
#define KEEP_RUNNING 10000 //milliseconds
#define BODS 7 //BOD Sleep bit in MCUCR
#define BODSE 2 //BOD Sleep enable bit in MCUCR
void setup(void)
{
//to minimize power consumption while sleeping, output pins must not source
//or sink any current. input pins must have a defined level; a good way to
//ensure this is to enable the internal pullup resistors.
for (byte i=0; i<5; i++) { //make all pins inputs with pullups enabled
pinMode(i, INPUT);
digitalWrite(i, HIGH);
}
pinMode(LED, OUTPUT); //make the led pin an output
digitalWrite(LED, LOW); //drive it low so it doesn't source current
}
void loop(void)
{
goToSleep();
for (byte i=0; i<5; i++) { //wake up, flash the LED
digitalWrite(LED, HIGH);
delay(100);
digitalWrite(LED, LOW);
delay(100);
}
delay(KEEP_RUNNING); //opportunity to measure active supply current
}
void goToSleep(void)
{
byte adcsra, mcucr1, mcucr2;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
MCUCR &= ~(_BV(ISC01) | _BV(ISC00)); //INT0 on low level
GIMSK |= _BV(INT0); //enable INT0
adcsra = ADCSRA; //save ADCSRA
ADCSRA &= ~_BV(ADEN); //disable ADC
cli(); //stop interrupts to ensure the BOD timed sequence executes as required
mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE); //turn off the brown-out detector
mcucr2 = mcucr1 & ~_BV(BODSE); //if the MCU does not have BOD disable capability,
MCUCR = mcucr1; // this code has no effect
MCUCR = mcucr2;
sei(); //ensure interrupts enabled so we can wake up again
sleep_cpu(); //go to sleep
sleep_disable(); //wake up here
ADCSRA = adcsra; //restore ADCSRA
}
//external interrupt 0 wakes the MCU
ISR(INT0_vect)
{
GIMSK = 0; //disable external interrupts (only need one to wake up)
}
@OsoianMarcel
Copy link

Thank you for sharing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment