Putting your Arduino to sleep can save a lot of power, but makes it harder to respond to serial commands. The Arduino does not receive serial messages when it is asleep. So, even if the micro wakes every few seconds to read a sensor, you have to time the serial message just right so that the Arduino is not asleep when the message arrives.
We found a simple hack using pin-change interrupts that wakes the Arduino when it sees activity on the serial port:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// Make sure all serial messages have been sent. Serial.flush(); // Enable the pin change interrupt on the receive pin // so that serial activity will wake the device. pinMode(SERIAL_RX_PIN, INPUT_PULLUP); PCintPort::attachInterrupt(SERIAL_RX_PIN, &WakeHandler, LOW); // Enter power down state. We'll wake periodically. LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); // Detach pinchange interrupts & reconfigure serial port. PCintPort::detachInterrupt(SERIAL_RX_PIN); Serial.begin(SERIAL_BAUD); |
Almost every digital pin on the Arduino can generate an interrupt when low or high, even when the micro is asleep. So just before putting the micro to sleep, we attach a pin-change interrupt to the serial receive pin. Serial activity will pull this pin low sometimes and trigger the interrupt to wake the device. When the device wakes, we detach the interrupt and reinitialize the serial port. The internal pull-up is turned on so the pin is in a well defined state even if a serial port is not attached.
It works best if you send a few characters to wake the device, wait a short time (50 ms is enough), then start sending the real message. Serial characters are not properly received until the Arduino wakes and initializes the serial port so the first few characters are lost. I also found it doesn’t work reliably if you try to send the whole message without any pause between the wake characters and the real message.
Libraries
We use the Arduino LowPower library from Rocket Scream, which can be downloaded from GitHub.
We used the PinChangeInt library from the Arduino playground to setup the pin-change interrupts. It can be downloaded from Google Code.
Example
Download an example program to count sheep from GitHub. This example wakes every 8 seconds, counts a few sheep then goes back to sleep. Send the ‘w’ character to keep the program awake, counting sheep as fast as it can. Then ‘s’ to put it back to sleep.
The download includes all the libraries needed (copy them into your Arduino libraries folder) and a MegunoLink Pro project with an interface panel to control the Arduino. Download MegunoLink Pro and load the project file. Double click the “Wake” button on the interface panel to wake the Arduino. This sends two ‘w’ characters, with a little delay between them. Click the “sleep” button to put the Arduino back to sleep.