RPI Computers

Shutdown button with Raspberry PI and Python

Because of their low price, mini button switches are useful for many purposes. We have already analyzed how they work (ref. Using mini Switch Button with Raspberry PI and Python) and a funny use case (ref. Reaction Game (v2) with Raspberry PI and Mini Button Switch).

One more way to use these buttons allows people to solve a practical need: shutting down their Raspberry PI.

You know that powering off a RPI requires being logged in and following the procedure:

In this tutorial, I’m going to show you how to create a physical shutdown button for Raspberry PI.

I’ll use a Raspberry PI Zero W, but this tutorial applies to all Raspberry PI boards.

What We Need

As usual, I suggest adding from now to your favourite e-commerce shopping cart all the needed hardware, so that at the end you will be able to evaluate overall costs and decide if to continue with the project or remove them from the shopping cart. So, hardware will be only:

You can also evaluate the useful Elegoo kit, including electronic components (excluding Raspberry PI and it accessories) plus many other useful sensors.

Wiring Diagram

This wiring diagram is really simple to arrange, as it requires only 2 wires, a button and a button. Please note that cables are connected to ground and GPIO 21 (according to Raspberry PI pinout):

Please find below some detailed pictures:

Step-by-Step Procedure

Prepare Operating System

Start installing Raspberry PI OS. You can both install Raspberry PI OS Lite (for headless, fast environments) or Raspberry PI OS Desktop (in this case, using its internal terminal).

Make your OS up-to-date. From the terminal, issue the following command:

sudo apt update -y && sudo apt upgrade -y

You don’t need to install Python, as it is already installed in all Raspberry PI OS distros.

RPI.GPIO should be already installed (otherwise, you can get it installed with the command “sudo apt install python3-rpi.gpio”).

Prepare Shutdown Button Script with Python

You can easily get a copy of my shutdown script directly in your Raspberry PI with the following terminal command:

wget https://peppe8o.com/download/python/shutdown_button.py

The following lines explain script parts.

Required libraries are imported to be used in the script. We use RPI.GPIO library to manage PINs and OS library to get shutdown command working:

import RPi.GPIO as GPIO
import os

Then we associate shutdownPIN variable to improve code reading and PINs management. Change it if you use different wiring:

shutdownPIN = 21

We then set the used PIN according to our needs. The first row set the naming convention to Broadcom (BCM), then shutdownPIN is defined as INPUT, also using a pull-up software-defined resistance to get it up when reading undefined state (please read Using mini Switch Button with Raspberry PI and Python about this configuration):

GPIO.setmode(GPIO.BCM)
GPIO.setup(shutdownPIN,GPIO.IN, pull_up_down=GPIO.PUD_UP)

We also use a shutStarted variable. This will start at 0 and will be set to 1 once a shutdown procedure is started, so avoiding repeated shutdown commands if the button is keep pushed:

shutStarted = 0

Then the main program starts. The “try:” … “except” statement manages script running, catching and driving correctly exceptions.

All the work is performed by an endless while loop. Only if a previous shutdown has not been performed by this script (“not(shutStarted)“) and the button is pressed (“not(GPIO.input(shutdownPIN))“), then shutStarted variable is set to 1 and a “systemctl poweroff” command is sent to the operating system.

while True:
    if not(shutStarted) and not(GPIO.input(shutdownPIN)):
      shutStarted = 1
      os.system("sudo systemctl poweroff")

Last script part only manages script interruption (CTRL+C from keyboard), by cleaning GPIO status and printing an “interrupted” message on console:

except KeyboardInterrupt:
  print('interrupted!')
  GPIO.cleanup()

Managing Poweroff Permissions

As you know, poweroff/shutdown command in Raspberry PI requires root privileges (“sudo shutdown -h“). To avoid the script from going in error because of missing superuser authentication, we need to allow pi user to execute poweroff command in “raspberrypi” host without needing to type root/superuser password. This can be achieved by appending a specific row in sudoers file. Open to edit this file:

sudo nano /etc/sudoers

And append at the end following row, where “pi” must be changed with your Raspberry PI user and “raspberrypi” must be substituted with your Raspberry PI hostname:

pi raspberrypi =NOPASSWD: /usr/bin/systemctl poweroff

Save and exit. You could need a reboot for this change to be running.

Test Shutdown Script

From here, you can test your shutdown script by using the following command:

python3 shutdown_button.py

Then push your button and Raspberry PI will immediately start to power off.

Running Shutdown Script as a Daemon

You can also need to use the shutdown script as daemon, running in background from boot and managing its status from systemctl.

To reach this, move shutdown_button.py in /usr/bin/ folder:

sudo mv shutdown_button.py /usr/bin/

Create a new service under /etc/systemd/system/ folder:

sudo nano /etc/systemd/system/shutdownButton.service

and add the following lines:

[Unit]
Description=Shutdown button python script
After=network.target
StartLimitIntervalSec=0

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

[Install]
WantedBy=multi-user.target

Close and save. Start your new service with the command:

sudo systemctl start shutdownButton.service

Check it is running correctly with systemctl status, getting something similar to the following:

pi@raspberrypi:~ $ sudo systemctl status shutdownButton.service
shutdownButton.service - Shutdown button python script
Loaded: loaded (/etc/systemd/system/shutdownButton.service; disabled; vendor
Active: active (running) since Tue 2020-11-24 16:52:11 GMT; 22s ago
Main PID: 1088 (python3)
Tasks: 1 (limit: 881)
CGroup: /system.slice/shutdownButton.service
└─1088 python3 /usr/bin/shutdown_button.py
Nov 24 16:52:11 raspberrypi systemd[1]: Started Shutdown button python script.

Moreover, if you want this script running after each reboot, enable it with systemctl:

sudo systemctl start shutdownButton.service

And test your button.

Final thoughts

Before closing this tutorial, I want to share some considerations.

Using a mini button switch for shutdown is a simple and practical way to trigger RPI power off without the need of entering its desktop or terminal and avoiding risks to corrupt the filesystem with mere power supply detachment.

If you use RPI.GPIO python library within other scripts and closing them with GPIO.cleanup(), you need to manage the shutdown PIN from being cleaned and disabled.

An alternative way to implement a shutdown button is also acting on overlay settings from /boot/config.txt (refer to https://github.com/raspberrypi/firmware/blob/master/boot/overlays/README for more info).

Enjoy!

peppe8o

Open source and Raspberry PI lover

View Comments

  • Sorry, not so good:
    As soon as shutdownButton.service is active the CPU is running 99.7% on python3.

    • Thank you for your feedback. I prepared a modified version of shutdown_button code using python threading. You can get it with:
      wget http://peppe8o.com/download/python/shutdown_button_2.py
      then renaming in shutdown_button.py instead of old code.
      This should fix CPU usage. Please, can you give me a feedback if it works for you?

      Many thanks

  • I'm in a project of a retropi handheld and I'd like to put a safe shutdown/power on button on it to make things easier (and safer to myself XD). I'm learning stuff on the go, so I got some doubts, if you don't bother helping me. I'm using this, https://othermod.com/raspberry-pi-soft-onoff-circuit/
    Am I supposed to do all this circuit in the link or just that single button is enough to power on and off safely the RPI?

    • The referred circuit (described in second half of the page) seems a good solution as this manager the shutdown process beside powering off. But I don't know how the writer manages the shutdown process (if with a python code like mine one or with the power wire from RPI config.txt or other ways). In other words, if you shut down and cut current on same time (from a single button), your RPI will not have enough time to shut down correctly the OS. Please ask the tutorial creator how he manages timing for both turn-off phases: shutdown and power off

Published by
peppe8o

Recent Posts

Some links in this post may be affiliate links. We may get paid if you buy something or take an action after clicking one of these, but without addictional costs for you compared to direct buying.

SPI communication between two Arduinos

In this tutorial, we will use two Arduino Uno to demonstrate the Serial Peripheral Interface…

2 weeks ago

Automatic irrigation system with Arduino and Sensors

In this tutorial, we will be making an automatic irrigation system (AIS) with Arduino and…

3 weeks ago

Beginner’s Guide to Use Python Virtual Environment with Raspberry PI (venv)

This tutorial will show you how to use Python Virtual Environment with Raspberry PI computer…

4 weeks ago

Get Betting Odds with Raspberry PI and Odds-API (free)

This tutorial will show you how to get betting odds with Raspberry PI by using…

1 month ago

Backup Raspberry PI (computer) Data with Rsync to Remote NAS

This tutorial will show you how to perform the backup of Raspberry PI (computer board)…

1 month ago

Honeygain and Raspberry PI: Earn by Sharing Internet Connection

This tutorial will show you how to install Honeygain on a Raspberry PI computer board…

1 month ago