Issue
The following python script is supposed to wait for a button press, print a button press message, and then exit.
However, when I press the button nothing is printed. Then when I press the enter key, the script prints "Button push detected" then stops.
How might I fix this code so that 'Button push detected' is printed when I push the button?
I followed a tutorial to make this code:
#Button input detection
#by
#Start date: 11th February 2021
#End date: 11th February 2021
#Importing GPIO andtime libraries as per usual with a python script making use of RPi GPIO
import RPi.GPIO as GPIO
import time
#Callback function to print 'Button push detected' when called
def button_callback(channel):
print("Button push detected")
#Disabling annoying GPIO warnings and setting GPIO mode to board
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_UP)
#GPIO event detector that detects a rising edge on pin 11
GPIO.add_event_detect(11,GPIO.FALLING,callback=button_callback)
#Command that does not stop until someone presses enter
quit = input("Press enter to quit")
#Clean up the pins used
GPIO.cleanup()
Solution
The problem is that your script needs a loop that waits until the button is pressed so that when the button press is detected, your script will be able to react to the event.
Right now your script sets the event detection but then sits waiting for input and as soon as the input is made, your script exits.
See this Raspberry Pi forum post, https://www.raspberrypi.org/forums/viewtopic.php?t=201747
which has a program for lighting an LED on and off with button presses.
However it looks to me like you would probably need to make a change to the call back function to raise an exception rather than light the LED if you want the script to end when you press the button.
See below the modified program with some additional annotation along with the LED light/unlight commented out.
However this modified program uses a busy loop that just runs continuously until the button is pressed. Using a busy loop, while it works for simple programs such as yours, is generally not a good idea.
An alternative is to use the GPIO.wait_for_edge()
function that will pause the script until the button is pressed. See Raspberry Pi StackExchange - Pausing code execution till a button is pressed which removes the busy loop.
First the busy loop version.
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
btn_input = 4; # button to monitor for button presses.
LED_output = 17; # LED to light or not depending on button presses.
# GPIO btn_input set up as input.
GPIO.setup(btn_input, GPIO.IN)
# GPIO.setup(LED_output, GPIO.OUT)
# handle the button event
def buttonEventHandler_rising (pin):
# turn LED on
# GPIO.output(LED_output,True)
raise Exception('button pressed')
def buttonEventHandler_falling (pin):
# turn LED off
# GPIO.output(LED_output,False)
raise Exception('button released')
# set up the event handlers so that when there is a button press event, we
# the specified call back is invoked.
# for your purposes you may only want to detect the falling
# indicating that the button was released.
# GPIO.add_event_detect(btn_input, GPIO.RISING, callback=buttonEventHandler_rising)
GPIO.add_event_detect(btn_input, GPIO.FALLING, callback=buttonEventHandler_falling)
# we have now set our even handlers and we now need to wait until
# the event we have registered for actually happens.
# This is an infinite loop that waits for an exception to happen and
# and when the exception happens, the except of the try is triggered
# and then execution continues after the except statement.
try:
while True : pass
except:
GPIO.cleanup()
See as well the explanations as to what is happening in these forum posts
https://www.raspberrypi.org/forums/viewtopic.php?t=128510
https://www.raspberrypi.org/forums/viewtopic.php?t=141520
And this article about exceptions in python. https://realpython.com/python-exceptions/
Answered By - Richard Chambers