0

I used the method described here and here , which is a python script based on interrupts, to enable safe shutdown via push-button press.

These are the steps in short:

1-

sudo nano test.py

2- and then:

# 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 to look for button presses

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

3- and then add the following to /etc/rc.local :

python /home/pi/test.py

4- and these are the circuits:

enter image description here

and

enter image description here

However, it didn't work.

The on-button and the hard-off-button work well. But when I press the soft-off-button, nothing happens at all.

My system is Xbian/Kodi on RPi B+ .

What's wrong with this method !!? And what should I do to get it to work !?

Thanks for your time and help.

  • All the comments, answers, hints, and notes are totally appreciated. – Omid1989 Jun 8 '15 at 5:42
  • I've very newbie in electronics but I know a bit about linux and python. What do you mean by "soft" button? – Eric Jun 8 '15 at 6:15
  • Oh, I think I get it, you have a button to like, cut the power and disregard the software state and another one to proceed with smooth, OS controlled shutdown – Eric Jun 8 '15 at 6:17
  • Thanks @Eric for your comment. There are 3 buttons: (1) On, (2) Hard-Off, and (3) Soft-Off. The soft-off button is for os-controlled shutdown via interrupts in a python script. But it doesn't work. – Omid1989 Jun 8 '15 at 6:26
1

I'm am not sure this is not a wiring issue, but I see some problems with the python approach here.

In the article, they define another "loop" later on with admittedly better code than raw_input. Adding the python line to rc.local also seems like a sketchy idea.

raw_input blocks until the user types something in and presses enter. During boot time, nobody WANTS to press press anything in order for the system to boot. Also, blocking forever during boot is usually frowned upon.

rc.local is executed everytime the system changes runlevel. See more info on runlevels. Basically, during a normal boot, your script will be executed at least once, but it is difficult to say since embedded devs sometimes use tricks in order to get things going. It is also possible that python will not load correctly during that time.

Here are my suggestions :

Try your script by starting it manually. I assume you can get a shell to your pi, so run it on a terminal an see if it works. If it doesn't then the fault is not related to the boot sequence.

After you've booted, you can use ps aux and check which process are running. You should see a python yourscript.py somewhere.

Use shutdown now instead of halt. I am not familiar with the later and trying it on my computer made it behave strangely. Alternatively, you can use shutdown -r now to reboot.

You can check your current runlevel with runlevel. In /etc/rcX.d where X is the runlevel, you can see all services that are started when the system enters that runlevel. I would suggest adding another entry there, near the end like S98mybuttonhandler which will be a sh/bash script calling nohup python myscript.py &. & is a command line trick to tell the shell not to wait on the program, "detach it". nohup is used to prevent SIGHUP from terminating your program. This is usually called when the shell which started your program closes, even if you used &.

Finally, consider using the suggested code in your loop (as the tutorial suggested) :

while True: # Setup a while loop to wait for a button press
   if(GPIO.input(7)): # Setup an if loop to run a shutdown command when button press sensed
      os.system("sudo shutdown -h now") # Send shutdown command to os
      break
   time.sleep(1) # Allow a sleep time of 1 second to reduce CPU usage
  • Thanks @Eric for your answer. I'll try your suggestions to see which works. – Omid1989 Jun 8 '15 at 6:50
  • 1
    I tend to rant a lot =). First change the loop code, then try the command line call. The rest doesn't matter much in reality – Eric Jun 8 '15 at 6:51
0

Using raw_input in the loop will prevent the script from running in background. Test yourself:

start the script manually with

python /home/pi/shutdown.py &

and press the button. Nothing will happen. I assume the script already stopped as there is no raw_input or so! if you start the script manually like this in foreground

python /home/pi/shutdown.py

the system will shutdown when you press the button. But this line is unusable in rc.local and crontab (@reboot python /home/pi/shutdown.py)

I had to change the script to:

# Import the modules to send commands to the 
# system and access GPIO pins for startup 
# sudo nano /etc/rc.local python 
# /home/pi/shutdown_watch.py & ... exit 0
#
# LCD board keys 0 to 2, I am using a JoyIT touchscreen LCD
# key 0 -> P1 = Pin GPIO 12
# key 1 -> P4 = Pin GPIO 16
# key 2 -> P5 = Pin GPIO 18

from subprocess import call
import RPi.GPIO as gpio
import time

# Define a function to keep script running
def loop():
while True:
   time.sleep(0.2)
#    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(12, gpio.IN, pull_up_down=gpio.PUD_UP) # Set up pin 12 (was 7 GPIO4) as an input
gpio.add_event_detect(12, gpio.FALLING, callback=shutdown, bouncetime=200) # Set up an interrupt to look for button presses

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

The above works for me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.