ATX style power-switch for Raspberry Pi

The Raspberry Pi lacks a decent power ON/OFF button. With a handful of cheap components a ATX style power-switch can be build.


Main parts are a PIC microcontroller, a 5V relay, a push button and a LED.

How does it work?

Power UP

When S1 is pushed, the micro controller will be power through D4, D3 en D2. These diodes will reduce the supply voltage for U1 to around 3,3V so it can directly interface with the GPIO pins of the Raspberry Pi.

The embedded PIC software will directly activate RA5 on power-up. This will activate the relay and 5V will be available on P2 to power the Raspberry Pi. The PIC is now powered through D5. Also RA1 is set high to tell the Raspberry Pi to keep running. The LED will blink until a high signal, from the Raspberry Pi, is received on RA0 (the Python script below will handle that).

Power DOWN

When S1 is pushed, to power down the Pi, high signal is received on RA2. Now RA1 is set low to tell the Pi to shutdown (the Python script below will handle that). The LED will start blinking again and we wait for a low on RA0 from the Pi, indicating the Pi has shutdown. Now, with a little delay, the relay is switched off and so is the Raspberry Pi.

Embedded software

I used MPLAB X to write and compile the code using the free compiler from Microchip. I also used the MPLAB Code Configurator that comes with MPLAB X, to setup all the registers and handy functions in no time. The code can be found on GitHub. Clone the repo or download the ZIP. Open the project in MPLAB X to build and program the PIC microcontroller.

The PIC can be programmed by using connector P3. I used an ICD3 but most programmers will work just fine.

Raspberry Pi software

For this part I started with the code from the Pi Supply website. I used GPIO pin 11 as output and pin 13 as input. You can change them if you like to use other pins.

Create a python file with the content below. Save it in your user root folder (probably /home/pi) and name it something like or whatever looks logic to you.

# Import the modules to send commands to the system and access GPIO pins
from subprocess import call
from time import sleep
import RPi.GPIO as gpio

# Define a function to keep script running
def loop():

# Define a function to run when an interrupt is called
def shutdown(pin):
  sleep (0.1); # 100ms debounce delay
  if not gpio.input(13):
    # You might want to do something before shutting down the Pi
    # add these code lines here (see example line below)
    # call(['mpc', 'pause'], shell=False)
    call('halt', shell=False)

gpio.setmode(gpio.BOARD) # Set pin numbering to board numbering
gpio.setup(13, gpio.IN) # Set up pin 13 as an input
gpio.setup(11, gpio.OUT, initial=gpio.HIGH) # Set up pin 11 as an output

gpio.add_event_detect(13, gpio.FALLING, callback=shutdown) # Set up an interrupt to look for button presses

loop() # Run the loop function to keep script running

Next edit the fileĀ /etc/rc.local, by adding the follow line:

python /home/pi/

Just above the (last) line:

exit 0

In some cases it might be necessary to add an ampersand, to run the script in the background, like so:

python /home/pi/ &

How does it work?

When the Raspberry Pi is powered up the rc.local file is executed and so is the script. This script will only set the output pin (11) high on start-up and then “watch” for the input pin (13) to go low. When the input pin goes low the halt command will nicely shutdown the Pi.

That’s it.

Connecting it to the Pi

Connector P2 will power the Raspberry Pi. You can use the USB connector for that or the 5V en GND pins on the GPIO header of the Pi.

Next are the IO lines from P3.

P3 pin 2 RA1 ----------- > --------- GPIO pin 13

P3 pin 3 RA0 ----------- < --------- GPIO pin 11

P3 pin 4 GND ----------------------- GPIO GND