[SOLVED] GPIO Interrupt for Shutdown with Button

Hey everyone,

So I’ve been trying to get a button setup that will be used to shutdown a Raspberry Pi B+ when pressed. I have a python script called “/root/buttonShutdown.py” as follows:

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

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

# Define a function to run when an interrupt is called
def shutdown(pin):
  call('halt', shell=False)

gpio.setmode(gpio.BOARD) # Set pin numbering to board numbering
gpio.setup(7, gpio.IN) # Set up pin 7 as an input
gpio.add_event_detect(7, gpio.RISING, callback=shutdown, bouncetime=200) # Set up an interrupt
loop() # Run the loop function to keep script running

This works well on its own, but I need it to run in the background. I’ve tried to throw “python /root/buttonShutdown.py &” within “/etc/rc.local” in order to have the python script startup at boot time, but I end up with an EOF error which closes the script.

The next attempt I tried is to build a daemon that would run in the background with a scripted called “/etc/init.d/buttonShutdown.sh” which is as follows:

#!/bin/sh

### BEGIN INIT INFO
# Provides:          buttonShutdown
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Background button system halt
# Description:       Uses background python script to set a button interrupt to call for a system halt
### END INIT INFO

# Change the next 3 lines to suit where you install your script and what you want to call it
DIR=/root
DAEMON=$DIR/buttonShutdown.py
DAEMON_NAME=buttonShutdown

# Add any command line options for your daemon here
DAEMON_OPTS=""

# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
DAEMON_USER=root

# The process ID of the script when it runs is stored here:
PIDFILE=/var/run/$DAEMON_NAME.pid

. /lib/lsb/init-functions

do_start () {
    log_daemon_msg "Starting system $DAEMON_NAME daemon"
    start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
    log_end_msg $?
}
do_stop () {
    log_daemon_msg "Stopping system $DAEMON_NAME daemon"
    start-stop-daemon --stop --pidfile $PIDFILE --retry 10
    log_end_msg $?
}

case "$1" in

    start|stop)
        do_${1}
        ;;

    restart|reload|force-reload)
        do_stop
        do_start
        ;;

    status)
        status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
        ;;

    *)
        echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
        exit 1
        ;;

esac
exit 0

Symbolic links were created in the “/etc/rc?.d” folders by using “sudo update-rc.d buttonShutdown.sh defaults”. I then ran the script “/ect/init.d/buttonShutdown.sh start”, of which the code notified that it has started correctly, as expected. Although, when the button was pressed nothing happened which leads me to believe the daemon did not execute the python script correctly or the script closed out in some fashion (I can’t tell because nothing was printed to the terminal). Any ideas why this is the case or any other options I might be able to take for this task?

I should also note that both script files are executable through “chmod”.

but I end up with an EOF error which closes the script.

Most likley you’ll need to set Unix line endings to the script.

Can you paste the contents of your /etc/rc.local? Make sure you have the following at the END of the file:

exit 0

You can set line endings with: ARMbian First Run Config by Fourdee · Pull Request #490 · armbian/build · GitHub

So in this case try:

sed -i $'s/\r$//' /etc/rc.local
sed -i $'s/\r$//' /root/buttonShutdown.py
sed -i $'s/\r$//' /etc/init.d/buttonShutdown.sh

Hey, sorry for the late reply, Fourdee.

Today, I was able to figure a way to run the python script. I believe the issue is with how raw_input() works. Since raw_input() is looking for data from the user, it would have to be tied with some keyboard file (I’d assume some file in the /dev/input/ folder). By running the python command in the background, the keyboard file seems to be “disconnected” and can not be read by the script, hence the EOF error.

I corrected this issue by replacing raw_input() with an infinite while loop and a thread sleep for a full day. Seems like it catches the button interrupt as it should without errors or hindering processing power for other tasks.

import time
def loop():
  while True:
    time.sleep(86400)

Here is the contents of my /etc/rc.local in case your still curious to see it:

#!/bin/bash
ech -e "$(cat /proc/uptime | awk '{print $1}') Seconds" > /var/log/boottime
if (( $(cat /DietPi/dietpi/.install_stage) == 1 )); then
	/DietPi/dietpi/dietpi-services start
fi
/DietPi/dietpi/dietpi-banner 0
echo -e " Default Login:\n Username = root\n Password = dietpi\n"
python /root/buttonShutdown.py &
exit 0

Here is the contents of my /etc/rc.local in case your still curious to see it:

Great to hear its now working.

missing an o at the echo line in /etc/rc.local, aside from that, looks good

Yours:

ech -e "$(cat /proc/uptime | awk '{print $1}') Seconds" > /var/log/boottime

Should be:

echo -e "$(cat /proc/uptime | awk '{print $1}') Seconds" > /var/log/boottime

Ah yes, I ended up hand typing this during that post… I didn’t have an easy way to copy and paste the code at the time. Good catch though, and thanks again for the help.