HiFiPi.net
The blending of the Raspberry Pi with old and new music systems resulting in extreme cases of function and beauty..

Tech: Install a restart/shutdown button


A physical shutdown button is a useful early addition to a Raspberry Pi project, particularly if it is running in headless mode (must include SSH). You don't always wanna log into the thing and just yanking the power can damage SDCard/HDD data. The Pi will reset if the button is held for 2-5 seconds and will shut down (nicely) if the button is held for 5+ seconds. Any more than 10 seconds and it will self-distruct (just kidding)..

It is always best to read through instructions completely before commencing. Stop!This helps get an overall idea and how your system might vary. Remember if you connect something up incorrectly, you can brick your Pi. Those GPIO pins in particular are not well protected from stuff-ups.

The following should work for all late model Pis running operating systems which use systemd. I used Raspbian Stretch Lite Kernel 4.9 (0318) with no monitor. Select a button/switch which does not stay on all the time. Mine is an old reset button from a box of PC parts - push for on, springs back after - just perfect.

Reset switch as power switch

Firstly update the repositories list..

sudo apt update


And then install Python 3..

sudo apt install python3-gpiozero


More information on Gpiozero at the developers' website

Part 1: Adding the code

Using the text editor of your choice, create the following Python script..

sudo vi /usr/local/bin/shutbut.py

Copy and past this code into the file:

#!/usr/bin/python3
# Reboot and a shutdown script

use_button=27                       # lowest button on PiTFT+

from gpiozero import Button
from signal import pause
from subprocess import check_call

held_for=0.0

def rls():
        global held_for
        if (held_for > 5.0):
                check_call(['/sbin/poweroff'])
        elif (held_for > 2.0):
                check_call(['/sbin/reboot'])
        else:
        	held_for = 0.0

def hld():
        # callback for when button is held
        #  is called every hold_time seconds
        global held_for
        # need to use max() as held_time resets to zero on last callback
        held_for = max(held_for, button.held_time + button.hold_time)

button=Button(use_button, hold_time=1.0, hold_repeat=True)
button.when_held = hld
button.when_released = rls

pause() # wait forever

Save and close

Then, make the script executable..

sudo chmod 755 /usr/local/bin/shutbut.py


Next create the button service for systemctl to use..

sudo vi /etc/systemd/system/shutbut.service

Copy and past this code into the file:

[Unit]
Description=GPIO shutdown button
After=network.target

[Service]
Type=simple
Restart=always
RestartSec=1
User=root
ExecStart=/usr/bin/python3 /usr/local/bin/shutbut.py

[Install]
WantedBy=multi-user.target

Save and close

Configure the shutdown button service to run automatically on boot

sudo systemctl enable shutbut.service


A result similar to this should appear..

Created symlink /etc/systemd/system/multi-user.target.wants/shutbut.service ?
/etc/systemd/system/shutbut.service.

Finally start the shutdown button service

sudo systemctl start shutbut.service


Running the systemctl status command at any time should confirm whether the service is running..

sudo systemctl status shutbut.service


Hopefully you'll see something like:

? shutbut.service - GPIO shutdown button
   Loaded: loaded (/etc/systemd/system/shutbut.service; disabled; vendor preset: enabled)
   Active: active (running) since Sat 2018-03-31 00:41:31 UTC; 12s ago
 Main PID: 1080 (python3)
   CGroup: /system.slice/shutbut.service
           +-1080 /usr/bin/python3 /usr/local/bin/shutbut.py

Mar 31 00:41:31 raspberrypi systemd[1]: Started GPIO shutdown button.

Anything other than Active: active (running), means it's up a certain creek without a certain implement and it's time to check you've done everything as described.

Part II: Adding the button/switch

If you're going to start screwing around adding hardware to your Pi, you need to become familiar with the various pins and plugs. The GPIO (General Purpose Input/Output) is the 40 pin connector running along the right hand side of the Raspberry Pi. View the Pi with the USB ports oriented downwards..

GPIO Plug

The GPIO varies with the models and versions of the various Pi incarnations. To check the version of your Pi, run the following command..

cat /proc/cpuinfo

Look for the Hardware Revision number at the bottom. In my case a22062. Pop over to https://elinux.org/RPi_HardwareHistory to confirm your hardware version. You may need to vary these instructions accordingly.

Note that the GPIO pins are numbered 1-40, starting top-left and finishing bottom-right. Each pin has its own number, but also a separate (and different) GPIO code number.

From the diagram above we will be connecting GPIO 27 to ground, which means putting the switch across pins 13 and 14. This is the GPIO pin configured in the Python scipt at the beginning: use_button=27. If you choose a different GPIO pin, you will need to modify the Python script.

For more information on each pin check out the rather useful https://pinout.xyz

And that's about it. With the Pi running, hold down the switch for 5+ seconds, let go and watch your Pi shut down with grace and style. Your SDCards will thank-you for it..

- AndyM