How do you safely shutdown or halt the Pi without turning off USB power?

I have an application where an Arduino is connected to a Pi via USB. The Arduino manages a battery that powers both it and the Pi. I'm now trying to setup a safe self-shutoff routine where the Pi runs sudo halt so no files get corrupted by sudden power failure, and then the Arduino uses a transistor to cut power.

Unfortunately, it seems that after sudo halt finishes, the Pi turns off USB power. Since I'm powering my Arduino via USB, I was stuck with this paradox where I need the Arduino to remain powered so it can turn off the battery...but first it needs to wait until the Pi safely halts itself...but by then the Arduino has lost power where it can't turn off the battery, leaving the Pi still powered but halted while the Arduino is disabled.

My hacky workaround was to modify the Arduino to track a heartbeat signal from the Pi, and once that's lost, then immediately turn off the battery. That way, when the Pi begins to execute sudo halt, it kills the process sending this heartbeat, causing the Arduino to cut power.

However, this doesn't reliably work because it's preventing full execution of sudo halt and therefore sometimes resulting in data corruption on the Pi SD card.

Ideally, I'd like to keep using the loss of the Pi heartbeat to tell the Arduino to shutoff, but add a 30 second delay to ensure sudo halt has completed. However, to do that, I need to keep USB power turned on, even after the Pi has halted. How do I do that?

  • Why don't you just power from the 5V rail? That's still live after halt. Of course then you need a level shifter for the UART... – goldilocks Feb 1 '18 at 14:24
  • Due to some wiring restrictions in my app, my only option is to power from USB. I can't run another wire to the Pi's 5V. – Cerin Feb 1 '18 at 14:39

You can NOT shutdown without shutting down USB.

Rather than trying to look at heartbeat I suggest you use the dtoverlay=gpio-poweroff which is designed for the purpose.

Name:   gpio-poweroff
Info:   Drives a GPIO high or low on poweroff (including halt). Enabling this
        overlay will prevent the ability to boot by driving GPIO3 low.
Load:   dtoverlay=gpio-poweroff,<param>=<val>

I'd like to keep using the loss of the Pi heartbeat to tell the Arduino to shutoff, but add a 30 second delay

If it's an option for you, you could add a buffer on the USB port between the RPi and the arduino in the form of a supercapacitor.

Here is the idea: the Atmega328 (not sure which arduino model you have) can operate within a range of 2.7V to 5.5V, but not at all frequencies. Above 3.78V it can operate at at least 16MHz, which is probably where you are using it. Suppose you arduino is drawing 30mA, we can calculate the required capacity to maintain these 30mA during 30” and for a voltage drop of 1V.

We have I = C dV /dt, with I the intensity in A, C the capacity in Farad, dV voltage drop in V and dt time for the voltage drop in seconds. Putting in the numbers above you get C = 0.03 * 30 / 1 = 0.9F. Adapt these to your case. (using the arduino at lower MHz allows you to go at even lower voltage, e.g 2,7V @ 8MHz). A 1F capacitor rated above 5V can be found (I have on hand a 15F rated 5.6V). Note that here I'm assuming that the arduino sinks current (linear capacitor discharge w.r.t. current) and that it doesn't behave like a resistor (in which case the discharge would follow an inverse exponential). You would need to add a protection diode on the + wire of your USB to protect from the capacitor discharging in the Pi's USB after it's been shut down (not sure if the USB has such protective diode built-in). The protection diode induce a voltage drop which you will have to take into account in your calculations.

To do the above, you need to bypass the 5V regulator of the arduino.

If the supercapacitor is not an option, after a halt or poweroff or shutdown -p, you still get 5V on the 40 pins header number 2 and 4, with respect to that same header GND pins (for example pin 6).


Check out the Linux based commands you can apply by using echo() in your script, you can find them here - https://www.computerhope.com/unix/ushutdow.htm The most suitable for your case is sudo shutdown -p now

  • I believe shutdown still calls halt, as this answer describes. – Cerin Feb 1 '18 at 22:07
  • shutdown and poweroff both cut power on USB ports on the RPi 3 (and likely other Pis), just confirmed with measurements. – calocedrus Feb 2 '18 at 0:17
  • Also, shutdown on Linux has no -p option. Only -P. – Cerin Feb 2 '18 at 15:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.