I found yet another way to create a GPIO pin that signals the end of the shutdown sequence, and that is posted here : viewtopic.php?f=41&t=114975
I liked SparkyPi's idea of using a simple chip to create a start-stop button, so I ordered some LTC2951-1 Pushbutton On/Off Controller chips. I was able to build and verify a prototype and was pleased to find that it does not even need Device Tree features, although that can be used to extend the functionality.
Initially, I wanted to control an XL6009S Buck Convertor with the EN output from the LTC 2951, to shut the power to the Pi. I use the combination Boost-Buck to always supply a precise 5V0 to the Pi, measured at TP-1 and TP-2, or at the end of the USB cable. However, I completely overlooked the real meaning of the EN input for the XL6009S. My initial understanding was that by driving the EN input low, the output would be cut. Not so! The EN input only disables the working of the chip, but the input power still goes to the output. If you look at the schematic, you'll see why. Duh! Even if the chip has been disabled by pulling the EN low, the input voltage still goes through the coil and the Schottkey diode.
So the result was that I used one of my earlier trusted power switches in the schematic below: Let's go over the building blocks. It makes sense to also look at the datasheet of the controller for more details. http://cds.linear.com/docs/en/datasheet/295112fb.pdf In short, U1 is the Start/Stop controller. It gets activated by a simple push button. When the power comes on, the Pi is powerless. When you push the button, the controller debounces the button, adds some delay and activates the EN output. The EN output goes to a power switch configured with an N-channel and a P-channel MOSFET. I selected a small device (Si4563DY) that packages both FET's. Most MOSFET's that are able to switch with a low voltage come in an SMD package, typically 3 pins, so why not go through the trouble to solder a few more and have a complete solution.
Note that if you use the LTC2951-2 variant, you don't need the N-FET. The polarity of the EN signal is inverted so it can drive the P-FET directly.
In any case when the EN signal goes high, power is applied to the Pi and it can boot.
When you push the button again, the /INT output goes low, to signal that power will be cut. This output needs to go to a GPIO input and needs to be monitored by a (daemon) program running on the Pi. As soon as the low has been detected, the Pi must start a shutdown sequence. After some delay, the controller drives the EN output low and the power to the Pi will be cut.
The required delay, needed for the shutdown sequence to finish, can be set by a capacitor on the KILLT input. I selected a 4.7uF to give me about 35 seconds between the button press and the EN signal going low.
To avoid an accidental shutdown by touching the button, a capacitor can be added to the OFFT input. I selected 470nF to create a delay of about 4 seconds. This means that you need to press the button for at least 4 seconds for the chip to validate this as a valid shutdown request. Note that this does not change the turn-on button press. I have added an LED to the output of the /INT output, because that LED will turn on as soon as the validation period has been met. So you have a visual indication. The LED will turn off when the EN signal is driven low at the end of the delay period, or the /KILL has been asserted.
Note that the (red) LED together with the 4K7 bias resistor lowers the 5V1 supply to about 3V6. This makes the LED light rather dim, but together with the series resistor of 1K, it provides sufficient protection for the GPIO input port so everything can be powered from the 5V1 coming from the wallwart. (tks Jojopi) If you cut a good quality (thick power wires) USB cable, you can easily put this circuit in the middle.
If you're concerned, or want a brighter LED, use a low current 3V3 Zener diode between the junction of the LED and the 1K series resistor and GND.
This is optional:
If you want to be really clever, you can use the procedure I wrote about in this post viewtopic.php?f=41&t=114975, and program a GPIO pin that changes state when the Pi is halted. The added benefit is that as soon as the Pi is telling us that the shutdown is finished, by changing the GPIO port, it will send the /KILL signal to the LTC-2951 and it will immediately cut the power to the Pi. In effect, cutting the delay period (set by C3) short. This can be useful if you need to do a lot of work to save the state of your environment on the Pi (making a backup of whatever) before the shutdown. You can now easily make C3 larger, knowing that the power will be cut anyway. If, for whatever reason, the Pi does not signal the /KILL, the Controller will still cut the power at the end of the delay period.
All in all, with two tiny SMD packages, a few resistors and capacitors and a very small piece of code, you can now create a start/stop button and remove the power to the Pi.
Note that the Pi will not start automatically when main power is switched on, you have to push the button.
Here is an example of the code to detect the /INT signal as an interrupt. This code needs to run as a daemon at startup.
Code: Select all
#!/usr/bin/env python
#-------------------------------------------------------------------------------
# Name: module1
# Purpose:
#
# Author: Paul
#
# Created: 15-06-2015
# Copyright: (c) Paul 2015
# Licence: <your licence>
#-------------------------------------------------------------------------------
import RPi.GPIO as GPIO
import subprocess
DEBUG = True
GPIO.setmode(GPIO.BCM) # use GPIO numbering
GPIO.setwarnings(False)
INT = 17 # GPIO-17 /INT signal
GPIO.setup(INT, GPIO.IN)
def main():
while True:
# set an interrupt on a falling edge and wait for it to happen
GPIO.wait_for_edge(INT, GPIO.FALLING)
if DEBUG: print "edge detected on /INT", GPIO.input(INT)
subprocess.call(['halt'], shell=True, \
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if __name__ == '__main__':
main()