# How can I detect how long a button is pressed?

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

• 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. Mar 18 '17 at 9:02

## 2 Answers

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.

• 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
• 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
• 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

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.