Raspberry Pi shutdown/reboot button

RPi GPIORPi GPIO

Your Raspberry Pi (RPi) has the usual interfaces (USB, HDMI, Ethernet) just like any other personal computer. But the cool thing about Raspberry Pi is that it has general purpose input output pins (GPIO). This means that such pin can act as an input or output pin which is determined by the software. In that way you can connect different devices like buttons, LEDs, sensors or even other microcontrollers to your Raspberry Pi and interact with the physical world around yours RPi. The usual name for this interface is Low-level peripherals. These pins can be found on the 2 x 13 pin male header terminal. See the image on right (image taken from elinux.org).

In this article we are going to explain how to wire a simple mechanical push button to your RPi and then use this button for RPi shutdown or reboot. This can be especially useful when you don't have access to your RPi OS and you want to shutdown it properly to avoid any damage to your SD card.

The image below shows the wiring of a simple push button to your RPi. One leg of the push button is connected to the GND, while the other leg is connected to the 3.3V with a 10k ohms resistor. This leg is also connected via much smaller resistor (or even without it) to the RPi GPIO pin (I used GPIO 25). So what is actually happening here? When the button is not pressed, the GPIO pin is tied to 3.3V via 10k resistor so RPi senses high voltage level on this pin or logical "1". When the button is pressed, the RPi senses low voltage level (or logical "0") on GPIO pin due to a much smaller resistor path to GND pin. In that way the push button is "active low". You can connect the push button to be "active high" - just swap GND and 3.3V wires.

The following images are showing the push button and how did I attach it to my Raspberry Pi. I drilled the whole in my RPi case to mount the push button. Find the right spot on your case where you will have enough empty space beneath the button. Then I soldered three wires with the appropriate resistors to the push button. I used heatshrink to isolate the wires. In the end, connect the wires to 3.3V, GND and GPIO pin on RPi header terminal and close the case.

The RPi shutdown (halt) or reboot are performed through Python script RPi_h_r.py which is running in the background and monitoring the state of GPIO pin. The RPi should be rebooted if the button is pressed for less than approximately 3 seconds (i.e. short press). If the button is kept pressed for more than approximately 3 seconds, the RPi should halt. First we have to import all the necessary modules:

import RPi.GPIO as GPIO
import time
import os

The button is wired to GPIO 25 in my case, so I am using this pin as input:

GPIO.setmode(GPIO.BCM)
GPIO.setup(25,GPIO.IN)

Initialize the variables:

button_previous = 1
button_current = 1
brojac = 0
flag_pressed = 0

Here comes the main program. It is while loop where button state is constantly examined. Since the all mechanical switches bounce when pressed, the software based "debouncing" should be applied by comparing the current state of the button with the previous one, with some time delay:

while True:
  button_current = GPIO.input(25);
  flag_pressed = button_previous + button_current

  if (not(flag_pressed)):
    brojac += 1
  else:
    brojac = 0

  if (button_current and (not button_previous)):
    os.system("sudo shutdown -r now")
  if ((not flag_pressed) and  brojac >= 100):
    os.system("sudo shutdown -h now")
    break

  button_previous = button_current
  time.sleep(0.03)

The last thing to do is to run this script in background when the RPi boots. This is simply done by editing rc.local file. Open rc.local:

sudo nano /etc/rc.local

and add the following line before exit 0 line, assuming that script is in Pi home folder:

sudo python /home/pi/RPi_h_r.py &

The presented python script can give you an insight about working with the push buttons and GPIO pins. However, you will probably shutdown or reboot RPi with this button ocassionaly (rarely). Therefore, there is no need for frequent checking of the button state as the presented solution does (it does it approximately every 30 ms). More efficient way is to use the interrupt functionality of GPIO pins. In that way CPU load will be decreased which is important when dealing with such underpowered CPUs like the one in RPi.

Download script: RPi_h_r.py

Share:  Add to Facebook Tweet This Add to Delicious Submit to Digg Stumble This