0

Running Python on a Raspberry Pi Zero. I have one button connected to GPIO26, set for input and pulled up.

I setup my interrupt like this:

GPIO.add_event_detect(26, GPIO.FALLING, callback=myInterrupt, bouncetime=500)

And my interrupt handler is:

def myInterrupt(channel):
    global buttonStatus
    start_time = time.time()

    while GPIO.input(channel) == 0: # Wait for the button up
        pass

    buttonTime = time.time() - start_time    # How long was the button down?

    if buttonTime >= .1:        # Ignore noise
        buttonStatus = 1        # 1= brief push

    if buttonTime >= 2:         
        buttonStatus = 2        # 2= Long push

    if buttonTime >= 4:
        buttonStatus = 3        # 3= really long push

In the main I test buttonStatus to select an action whether the button is pressed briefly, for two seconds or more than three. ButtonStatus 1 and 2 are pretty reliable, but I rarely can get a buttonStatus of 3. I'll hold the button for 6 to 10 seconds, but the function most often returns a buttonStatus of 2.

Any guess why, or is there a better method to determine how long the button is being pressed? Am I getting an interrupt recursion from a dirty button?

Thanks

1
  • You got the logic a bit wrong. Joe Platano's answer is correct. Because when your button time is for example 5, both => 2 and => 4 are true. You should use an if else block, with restrains to handle this.
    – Dr_Bunsen
    Mar 18 '17 at 9:02
1

Pushing the button for more than 4 seconds, there are two valid IF conditions. You can use else if and use a range for the second condition:

if .1 <= buttonTime < 2:        # Ignore noise
    buttonStatus = 1        # 1= brief push

elif 2 <= buttonTime < 4:         
    buttonStatus = 2        # 2= Long push

elif buttonTime >= 4:
    buttonStatus = 3        # 3= really long push

With this little change the buttonStatus should be set correctly.

Edit:fixed elsif .1 as C Malasadas suggested in comments.

6
  • 1
    Suggested an edit that simplifies code. Also, the code provided will not work, and always set the buttonStatus to 1, because 4 and 2 are both greater than .1.
    – user61421
    Mar 31 '17 at 14:27
  • @CMalasadas, cannot see your edit, post the suggestion here in the comment and i will update the answer. Kudos for you Apr 1 '17 at 1:16
  • 1
    Just posted an answer, as it is easier than trying to format in comments and then waiting for an edit.
    – user61421
    Apr 1 '17 at 2:24
  • Also, I'm not sure your code will work (think you need an and statement, but not sure).
    – user61421
    Apr 1 '17 at 2:27
  • 1
    Okay, not used to two logic statements without a relationship. I still decided to post my edit as it is simpler and I thought that the OP might be able to understand the concept better.
    – user61421
    Apr 1 '17 at 3:01
1

Here's the edit I suggested which isn't working:

Pushing the button for more than 4 seconds, there are three valid IF conditions. You can use else if and use a range for the second condition:

if buttonTime >= 4:
    buttonStatus = 3
elif buttonTime >= 2:
    buttonStatus = 2  
elif buttonTime >= .1: 
    buttonStatus = 1

With this little change the buttonStatus should be set correctly.

Back to my post: Basically, this checks first if it's more than 4 seconds, and it it's not, it then checks for it it's more than 2 seconds, and so on.

Before, you were checking if it was above .1, 2, and 4. Say the value was 5. All 3 if statements would trigger as true, and run that code.

While there are other ways to do this, this is the easiest, simplest way to do so.

If you'd like clarification on elif, please ask, as it's important to understand, not just have it work.

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.