In the process of trying to make a small system that will last a while on 4 AA batteries, I've reduced my Arduino project to a barebones system that when asleep draws a tiny amount of current from the batteries.
However, to achieve this, I found it would be necessary to cut power to the two attached peripheral devices (connected to an ATMega328P-PU). One of them is an I2C device, and the other is a serial device, and both are attached to the hardware serial/I2C pins as appropriate.
In terms of powering the peripherals, the bases of two transistors are connected to two of the digital pins, and power to them is controlled from code via these transistors. Both devices are 5V, and when the system is running the total current draw is around 200mA.
Basically this setup works, however I'm getting "random" system hanging and essentially an unreliable project. Sometimes when I power it up it will work as normal, but then hang and not sleep. Other times, it will sleep, but then freeze after waking or just get stuck during waking (which I can tell because the serial device powers up first and does nothing, but the I2C device remains off).
My best guess is the root of the cause is either something to do with the serial communication being interrupted by sleeping the MPU (I'm using the maximum power saving sleep, which is woken by an external interrupt on pin 2), or possibly some sort of power problem (sudden current draw from battery?) that occurs when the peripherals are powered on in code (though I don't know how I should test this).
So far, I've tried calling Serial.end()
before sleeping the MPU, and Serial.being(9600)
on waking, and have scattered delay(1000)
s throughout to ensure everything has enough time to get running, but the problem still remains.
Does anyone have any pointers on things I could change/test, or an alternative approach I could take to make the same power savings?
EDIT: Some more details
The transitors used are TIP 120's. The connections are essentially an exact copy of the image here: https://ctheds.files.wordpress.com/2007/10/tip120.jpg, except the resistors used are 560 Ohms (just what I had to hand, no other reason, didn't think it would change anything).
The I2C peripheral is a 20x4 LCD (which I believe is HD44780 compliant). The serial device is an GT511C3 fingerprint sensor. I don't believe either of them have any automatic power saving features, though I haven't looked for such things in the documentation explicitly.
The exact code I use to call sleep is
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();
which I'm lead to believe is the lowest power mode, and aside from this problem works well for my system.