When designing a circuit that is meant to run on low power, I have found that is is a good start to choose a microcontroller board that is has a lower base voltage level than 5V. The reasons are twofold. First, a lower voltage means lower power consumed, period. Second, there are many other boards and modules that are for 3.3V applications and using a 5V levels for a supply or communications like UART, I2C or SPI can actually damage them without other protective parts of the circuit.

An Arduino Pro Micro 3.3V sold SparkFun is a good basis for the 3.3V designs. It uses an ATmega32U4 microcontroller running at 8MHz. The lower frequency further helps keep the current drain low, although this only counts while the micro is not asleep. Putting the micro into the sleep mode is almost a must with any application running on limited power, especially when powered from a battery.

External interrupt pins

To wake the micro from the sleep, or power down mode based on some external event, either the external interrupt pin or the reset pin can be used. One notable example of using the reset pin was a TV-B-Gone circuit, but even it seems to be using interrupts now. The boards based on ATmega328p have only two external interrupts, situated on the digital pins 2 and 3. The ATmega32u4 however has three more external interrupt pins, making up a total of five sources of external, possibly non-periodical sources of wakeup. Two of the five are however used on the UART pins. Using them complicates the serial communication and sketch upload at the same time. For something so delicately working with the serial connection as ATmega32u4 based boards, this is not a simple task.

Next two are used on the pins 3 and 2, similarly to the ATmega328p, but with their numbering swapped. The swap wouldn't be a such a big deal, but these two pins are used for I2C on the ATmega32u4. With the designs reliant on I2C communication, this is also quite a problem. This one can be solved with the software I2C library, but this always poses some downsides as opposed to hardware peripherals.

There is however the fifth external interrupt on ATmega32u4 that is not used for anything communication related, and it is a pin 7. The external interrupt 4 is attached to it. The useful details can be seen from the table below:

Boardint.0int.1int.2int.3int.4int.5
328p based (Uno, Ethernet)23
2560 based (Arduino Mega)2321201918
32u4 based (Leonardo, Micro)32017

The pin 7 in the table here is shown in bold. Note that ATmega2560 powering Arduino Mega has one additional external interrupt source, but is shown in the table only for comparison.

Waking from a power down mode

I have spent a considerable amount of time trying to make this procedure work, following multiple forum posts and guides, but nothing seemed to work for me. There is also a Low-power library that is sometimes recommended and claims to support 324u but I could not make it work for the purpose of using the pin 7 (an external interrupt number 4) to initiate the wakeup.

Instead, I have modified a code from multiple posts found around gammon.com.au:

#include <Arduino.h>
#include <avr/sleep.h>

const int wakeUpPin = 7;
const int ledPin = 17;

void wake()
{
    sleep_disable();
    detachInterrupt(digitalPinToInterrupt(wakeUpPin));
}

void sleepNow()
{
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    noInterrupts();
    sleep_enable();
    attachInterrupt(digitalPinToInterrupt(wakeUpPin), wake, LOW);
    interrupts();
    sleep_cpu();

}

void setup()
{
    pinMode(wakeUpPin, INPUT_PULLUP);
}

void loop()
{
    // Do something here
    // Example: Read sensor, data logging, data transmission.
    pinMode(ledPin, OUTPUT);
    delay(200);
    digitalWrite(ledPin, HIGH);
    delay(500);
    digitalWrite(ledPin, LOW);
    delay(200);
    pinMode(ledPin, INPUT);

    // Now go to sleep
    sleepNow();
}

The most critical modification here is in the INPUT_PULLUP pin mode. Without the pullup with the pin dangling, the behavior of the micro in relation to the sleep was very storage. On some pins the led was even dimming. Using the internal pullup resistor proved to work reliably wakeup the Arduino Pro Micro's ATmega32u4 by shorting the pin to the GND. It even allows for uploading a new sketch without a problem, which is obviously not possible when the micro is powered down.

Note that in case of problems, short RST pin to the ground once for a 750ms window until the sleep initiates or twice for a 8s window, to load a new sketch when you mess up and waking from sleep is not easy/possible.

This is a 61th post of #100daystooffload.