2

My Python code is currently looping, and before I want it to re-loop I would really like to be able to detect one of two buttons. Depending what button is pressed, a different part of the code should be executed.

For one button, this would look like this:

while True:
        time.sleep(0.2)
        GPIO.wait_for_edge(button_1, GPIO.FALLING)
        run_button_1_code()

How would I be able to do this for two buttons? I'm thinking something a long the lines of this:

while True:
        time.sleep(0.2)
        GPIO.wait_for_edge(button_1, button_2, GPIO.FALLING)
        if button_1 is pressed:
             run_button_1_code()
        elif button_2 is pressed:
             run_button_2_code()

Or perhaps alternatively:

def button_1():
    GPIO.remove_event_detect(button1)
    print "doing my code here"
    GPIO.add_event_detect(button1, GPIO.BOTH, callback=button_1, bouncetime=800)

def button_2():
    GPIO.remove_event_detect(button2)
    print "doing my code here"
    GPIO.add_event_detect(button2, GPIO.BOTH, callback=button_2, bouncetime=800)

While True:
    time.sleep(0.05)
        print "waiting for button"

I can't think of any other options.. Please advise!

user5740843
  • 1,540
  • 5
  • 22
  • 42

1 Answers1

2

Generally speaking, when interacting with hardware there are two ways to go. If the computer/OS allows interrupt tracking, this will be your best bet. You basically set up a subroutine and let the OS know it is waiting to be woken up if something interesting happens.

If you are developing this on a Raspberry PI there is a Python library to assist with this chore:

GPIO.add_event_detect(GPIO_ONOFF, GPIO.FALLING, callback=quit_loop, bouncetime=300)

If you are on a different system, or you wish to have more control, setting up a second thread/process is the obvious choice. Threading works in much the same way as interrupt processing. You set up a method and then let the OS know it should run independently. The key difference is that the thread/process is always active, and has to be treated as an independent program, while an interrupt routine sits idle until it is needed.

Process(target=processMessages).start()

Both of these solutions are discussed in a resent, related question:

Raspberry Pi Python pause a loop sequence, when button pushed

Community
  • 1
  • 1
codingCat
  • 2,396
  • 4
  • 21
  • 27
  • Thank you for your answer! However, wouldn't adding both event detects be able to start one after the other? I can't have the button being pressed while its still processing the code for the first press. I don't see how this prevents that? – user5740843 Apr 13 '16 at 15:24
  • If you take a look at the example on the linked page you can see how it is using the Process Queue to pass messages between the processes. You can then use this to set flags as needed to handle the pacing. For example, if you set up a separate process for each button... In the loop for button 1 you would have a statement that said something like "if buttonTwoPress == false", followed immediately by an assignment that sets its own flag "buttonOnePress = true". The button two process would have the oppsite: "if buttonOnePress = false" and "buttonTwoPress = true". – codingCat Apr 13 '16 at 18:44
  • Important safety tip: There is a slight but real chance that both buttons get pressed at the same moment. To help handle this possibility most languages have classes and tools to establish Mutexes and Semaphores. This will prevent two singular processes from happening at the same time. – codingCat Apr 13 '16 at 18:49