An Arduino library for simple means of putting your Arduino into sleep modes in order to save power when you are not doing much, supports a variety of common microcontrollers used with Arduino...
Table of Contents
- ATMega328 Series
- ATMega168 Series
- ATMega48/88
- ATMega8
- ATTiny25/45/85
- ATTiny24/44/84
- ATTiny13 ( recommended to use this core )
- Download: https://sparks.gogo.co.nz/SimpleSleep.zip
- Open the Arduino IDE (this library was tested in 1.8.5, older versions may work)
- Select the menu item Sketch > Include Library > Add Zip Library
- Choose to install the SimpleSleep.zip file you downloaded
- Now you can choose File > Examples > SimpleSleep > HelloWorld
Upload the example to your Arduino and stand back in awe of the results.
Sleeping forever is the simplest type of sleep and uses the least power, but only a RESET (or power-cycle of course) will wake you up. This can be very useful for "hit the button to do a thing" type devices, "hit the button play a sound", "hit the button light a light"... you just stick your button between RESET and Ground then in your code sleep forever when you have done the thing you want to do every time you hit the button...
#include <SimpleSleep.h>
SimpleSleep Sleep;
void setup()
{
}
void loop()
{
/* Do something interesting here */
/* After you are done, sleep forever. */
Sleep.forever();
}
Note that sleep forever does not alter your pin states, a HIGH pin will still be HIGH, a LOW pin will still be LOW, pullups will still be on if so configured. So you should also disable those (set to INPUT is often best for minimising power consumption, but it depends on your devices).
#include <SimpleSleep.h>
SimpleSleep Sleep;
const uint8_t ledPin = 13
void setup()
{
pinMode(ledPin, OUTPUT);
}
void loop()
{
digitalWrite(ledPin, HIGH);
Sleep.deeplyFor(1000);
digitalWrite(ledPin, LOW);
Sleep.deeplyFor(1000);
}
The difference between sleeping deeply and sleeping lightly is chip dependant. In terms of AVR, light sleeping is generally implemented as Extended Stand By or ADC Noise Reduction (with ADC off) modes, this uses more power than deeply but less than idle.
#include <SimpleSleep.h>
SimpleSleep Sleep;
const uint8_t ledPin = 13
void setup()
{
pinMode(ledPin, OUTPUT);
}
void loop()
{
digitalWrite(ledPin, HIGH);
Sleep.lightlyFor(1000);
digitalWrite(ledPin, LOW);
Sleep.lightlyFor(1000);
}
Using lightly/deeply generally is going to stop your serial communications and your millis count will not count during sleeping. The simplest way around this (there are others) is to use "idle" mode, which basically leaves everything running as much as possible, including serial and timers.
#include <SimpleSleep.h>
SimpleSleep Sleep;
const uint8_t ledPin = 13
void setup()
{
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop()
{
// Ask the user a question...
Serial.println(F("How many times to flash 0-99: "));
// Wait using low-power idle...
while(!Serial.available())
{
Sleep.idle();
}
// Read their answer...
char buf[4];
Serial.readBytesUntil('\n', buf, sizeof(buf)-1 );
// And do a thing...
for( int8_t x = atoi(buf); x >= 0; x--)
{
digitalWrite(ledPin, HIGH);
Sleep.deeplyFor(1000); // (we don't need to listen to serial here)
digitalWrite(ledPin, LOW);
Sleep.deeplyFor(1000); // (we don't need to listen to serial here)
}
}
Doing a calibration, which takes up to a few hundred milliseconds, can make for more accurate timing...
#include <SimpleSleep.h>
SimpleSleep Sleep;
SimpleSleep_Cal SleepCal;
const uint8_t ledPin = 13
void setup()
{
SleepCal = Sleep.getCalibration();
pinMode(ledPin, OUTPUT);
}
void loop()
{
digitalWrite(ledPin, HIGH);
Sleep.deeplyFor(1000, SleepCal);
digitalWrite(ledPin, LOW);
Sleep.deeplyFor(1000, SleepCal);
}
Only LEVEL type interrupts generally work and they must be longer than usual so if you connect a button between the interruptPin and ground, hold it down
#include <SimpleSleep.h>
SimpleSleep Sleep;
const uint8_t ledPin = 13
const uint8_t interruptPin = 2;
void setup()
{
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), interruptHandler, LOW);
}
void interruptHandler()
{
// In this example, do nothing we will just wakeup and continue from where-ever
// we went to sleep.
}
void loop()
{
// Blink once then sleep until an external interrupt happens
digitalWrite(ledPin, HIGH); delay(50); digitalWrite(ledPin, LOW);
Sleep.deeply();
}
Sleeping lightly ( Sleep.lightly()
) can also be used (equates to Extended Stand-By where available)
I recommend to just look at the examples which show you how to use all the features, but if you want the nitty-gritty then here is the full class reference