This section describes powering the Raspberry Pi (RPi) on and off after we have “awoken” our Arduino. To look at ways to sleep and wake, refer to the article Sleeping and Waking. The process of powering on is very simple, whereas the process of switching off the power to the Raspberry Pi can be a little more nuanced if we want a “safe” shutdown.
Powering On #
Raspberry Pi #
To power on the Raspberry Pi we simple need to call the following routine:
SleepyPi.enablePiPower(true);
This closes the electronic switch and supplies power to the Raspberry Pi.
Expansion Power #
There is also the option to enable expansion power with:
SleepyPi.enableExtPower(true);
To switch off simple call the routine with “false” instead of “true”. The expansion is an independent set of switches that routes the 3V3, 5V and Vin to the outside. This can be used to power external circuitry.
Note: The Expansion power can be left on when the Arduino is asleep if required.
Powering Off #
If we want things to play nicely and to increase reliability, then our best bet if to first “ask” the Raspberry Pi to shutdown. This triggers the Raspberry Pi to begin it’s Operating System shutdown and then inform us that it has finished. When this happens we cut the power completely to the Raspberry Pi.
Note: when the Raspberry Pi Operating System has shutdown, the Raspberry Pi still draws significant power. This is why we cut the power to reduce the power drawn by the Raspberry Pi to zero
In order to pass state information to and fro we have optional handshaking lines. I say that they are optional, as if you want to save the GPIO overhead, then there are ways to engineer a system to not use GPIO’s. To make it easier to follow, I’ll assume that handshaking is used, then give a few scenarios where we could leave to out.
Handshaking #
By default the setup of the Sleepy Pi 2 uses two GPIO lines on the Raspberry Pi GPIO header. To see the software setup of these on the RPi see here. These are:
- GPIO 24: – Command the RPi to shutdown. Direction: Arduino -> RPi
- GPIO 25: – RPi is running. Direction: Rpi -> Arduino
GPIO 25 is high when the RPi is still running and the Rpi switches this low when it has finished shutting down
GPIO 24 is used by the Sleepy Pi 2 to signal to the Rpi that it should initiate a shutdown sequence.
There are two ways to approach a handshake shutdown: go about it in your own loop, so you can do other things or call a routine to do it all for you. I call thes the “Long-Hand Code” and the “All-in-one”. These two approaches use the following routines:
- SleepyPi.startPiShutdown(); // Kick it off and you code the rest
- SleepyPi.piShutdown(); // Do it all
Long-Hand Method #
This method requires you to code up the loops, but allows the program flow to stay in your domain so to speak, rather than disappear into sub-routine. It requires the described below.
To initiate a shutdown call the following routine:
SleepyPi.startPiShutdown();
This begins the process, which can take while depending on the code running on the Rpi. What we should now do is periodically check in with the following routine:
pi_running = SleepyPi.checkPiStatus(false);
Where pi_running is a boolean true or false. Initially this will likely be true when first called, but at some point it will change to false when the Rpi has shutdown. Once this happens, we are safe to cut the power with:
SleepyPi.enablePiPower(false);
SleepyPi.enableExtPower(false); // Optional
It’s also worth mentioning that SleepyPi.checkPiStatus takes a parameter called “forceShutdownIfNotRunning” and will forcefully cut the power on the Rpi if it is not deemed to be handshaking (maybe it’s hung?).
Putting it all together in pseudocode we have:
SleepyPi.startPiShutdown(); // Start a shutdown sequence
Loop: // Wait for Rpi to finish shutting down
pi_running = SleepyPi.checkPiStatus(false);
if(pi_running == false)
{
// Switch Pi Off
SleepyPi.enablePiPower(false);
SleepyPi.enableExtPower(false); // Optional
}
All-in-one #
This method wraps up the above code into a single routine that once called, initiates shutdown, then waits for it to complete and then cuts the power to the Rpi. It includes a failsafe timeout so that if the Rpi hasn’t shutdown before the timeout then the Rpi will be shut out anyway. The routine doesn’t cut the power to the expansion supplies so you need to do that afterwards if you need to power these off too. It looks like this:
SleepyPi.piShutdown(); // Triggers, waits and cuts the power to the Rpi
SleepyPi.enableExtPower(false); // Optional
Current Measurement to Determine Raspberry Pi State #
If you want to start to go “hand’s free” and not use the handshaking lines, you can free up GPIO 25 “RPi is running” and you look at the using the current draw of the Raspberry Pi to work out when it has shutdown.
When the Rpi is shutdown with a command such as:
sudo shutdown -h now
The Rpi does a controlled shutdown and if you look at the current drawn, it settles into its quiescent state when fully shutdown. The Sleepy Pi 2 has the ability to measure the current drawn by the Rpi and by monitoring this we can work out the it has shutdown.
As in the previous section, there is the long-hand version or the All-in-one.
Long-Hand Method #
We do this in a similar way to the GPIO handshake with the same routine but with an extra parameter:
pi_running = SleepyPi.checkPiStatus(current_threshold_mA,false);
The current_threshold_mA is the threshold below which we reckon that theRpi has shutdown. We can determine this threshold empirically by measuring our setup with the Rpi shutdown and putting a suitable milliamp figure in there or we can use some “rule of thumb” values which are given as enumerated constants in SleepyPi2.h, which the time of writing are:
// Typical shutdown currents of various models of Rpi’s in mA
typedef enum {
eZero = 48,
eA = 70,
eA_Plus = 55,
eB = 75,
eB_PLUS = 73,
eB2 = 70,
eB3 = 75
} eRPI_SHUTDOWN_CURRENT;
Putting it all together we have the same sequence as with handshaking except we add the extra parameter to SleepyPi.checkPiStatus.
Putting it all together in pseudocode we have instead:
SleepyPi.startPiShutdown(); // Start a shutdown sequence
Loop: // Wait for Rpi to finish shutting down
pi_running = SleepyPi.checkPiStatus(current_threshold_mA ,false);
if(pi_running == false)
{
// Switch Pi Off
SleepyPi.enablePiPower(false);
SleepyPi.enableExtPower(false); // Optional
}
All-in-one #
As described in the previous section this wraps up all the above methods into a self-contained routine. It looks like this:
SleepyPi.piShutdown(current_threshold_mA); // Triggers, waits and cuts the power to the Rpi
SleepyPi.enableExtPower(false); // Optional
Examples that use current measurement include: ButtonOnOff3.
Going GPIO Handshake free #
As we have seen by using the current to monitor Rpi state and save GPIO 25, we can go fully “hands-free” by not using GPIO 24 to signal the Rpi to shut down.
There are many scenarios where this handshake is naturally not used. For example imagine a time-lapse camera application. You would wakeup the Rpi to take a photo and then once you’ve finished with saving the image to disk or uploading it to the cloud, your Rpi script would issue a shutdown command. The Sleepy Pi in this case simply monitors the current and when shutdown occurs cuts the power.
Other options you have is to use the i2c bus to handshake between them, but that’s a whole different topic……
Using the Sleepy Pi as a Raspberry Pi Watchdog #
The Sleepy Pi 2 wields supreme executive power, which derives from a mandate from the masses. Calling this routine cuts the power instantly, no messing :
SleepyPi.enablePiPower(false);
As such it can act as a watchdog for the Raspberry Pi. At its simplest it can be a timeout of when we expect the Rpi to have shutdown. If it exceeds this time by a fair margin then we can cut the power anyway.
More involved scenarios can be created where in normal use the Rpi sends a heartbeat to the Sleepy Pi and if it doesn’t receive one then it reboots the Rpi. The existing GPIO’s (24 and 25) could be re-purposed for this or others chosen or even the i2c used.