ats1080
Posts: 44
Joined: Thu Sep 27, 2012 2:10 pm

Push Button Input Troubles

Tue Jan 05, 2016 2:22 pm

I'm using the RPi.GPIO library to detect when a button is pressed. The issue is that it will detect RISING two times per button press. Once on the down press and once on the release. Oddly enough the FALLING detection seems to be OK. BOTH seems to be obviously affected by the RISING being detected twice per press. I spent a few hours on this and I think I have finally narrowed this down to a software issue. I realize that the bouncetime parameter can be adjusted, but in my opinion, that is not really a solution since you are then limiting how you can press the button. In reality if someone with no knowledge of your program tried to use it they would run in to issues if pushing the button for too long or pushing it too fast.

My button schematic is below. It's worth noting that even with the button simply hooked to 3.3v and the input pin it also works fine with FALLING as long as the bouncetime parameter is set to 300, but RISING give the same behavior. With the button hooked up to this schematic and the software set to FALLING there is about 95% success rate with bouncetime turned off and very close to (if not) 100% with bouncetime set to even 100.
Image

Here is my code that works:

Code: Select all

import RPi.GPIO as GPIO  
import time
GPIO.setmode(GPIO.BCM)

GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 
presses = 1

def my_callback(channel): 
    global presses
    print "callback called " + str(presses) + " times"
    presses += 1
    
GPIO.add_event_detect(24, GPIO.FALLING, callback=my_callback, bouncetime=100)

print "Waiting"  
while True:
    try:  
        time.sleep(5)
    except KeyboardInterrupt:  
        GPIO.cleanup()
        break
If line 13 is changed to below, you will see the "callback called" line two times per button press.

Code: Select all

GPIO.add_event_detect(24, GPIO.RISING, callback=my_callback, bouncetime=100)
Going off this web page (http://raspi.tv/2014/rpi-gpio-update-an ... ling-edges) I modified my code a bit. I have read that this can be unreliable because of how fast the pin can change state and the delay that python can read it, so this may not be helpful.

Code: Select all

import RPi.GPIO as GPIO  
import time
GPIO.setmode(GPIO.BCM)

GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 
presses = 1

def my_callback(channel): 
    global presses
    print "callback called " + str(presses) + " times"
    if GPIO.input(24):
        print "RISING"
    else:
        print "FALLING"
    presses += 1
    
GPIO.add_event_detect(24, GPIO.BOTH, callback=my_callback, bouncetime=100)

print "Waiting"  
while True:
    try:  
        time.sleep(5)
    except KeyboardInterrupt:  
        GPIO.cleanup()
        break
The output of this code is below, you can see that FALLING is rarely displayed:

Code: Select all

[email protected] ~/myproject/python/schedule $ python test.py
Waiting
callback called 1 times
RISING
callback called 2 times
FALLING
callback called 3 times
RISING
callback called 4 times
RISING
callback called 5 times
RISING
callback called 6 times
FALLING
callback called 7 times
RISING
callback called 8 times
RISING
callback called 9 times
RISING
callback called 10 times
RISING
callback called 11 times
RISING
callback called 12 times
FALLING
callback called 13 times
RISING
callback called 14 times
RISING
callback called 15 times
RISING
callback called 16 times
RISING
callback called 17 times
RISING
callback called 18 times
RISING
callback called 19 times
RISING
callback called 20 times
RISING
callback called 21 times
RISING
callback called 22 times
RISING
callback called 23 times
RISING
callback called 24 times
RISING
callback called 25 times
RISING
callback called 26 times
RISING
So, after all that, am I doing something wrong, or is this a software bug?

JimmyN
Posts: 1109
Joined: Wed Mar 18, 2015 7:05 pm
Location: Virginia, USA

Re: Push Button Input Troubles

Tue Jan 05, 2016 5:25 pm

It looks like you're using an external 47K resistor as a pull-up, and at the same time you're setting the pin to use the internal pull-down?

I'd get rid of the 3.3V connection, the 47K resistor, and the capacitor. Just tie the switch across the GPIO pin and ground. Then I'd set the pin to "GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_UP) and use the internal pull up to keep it high.

Then it should detect the GPIO.FALLING reliably when the switch closes.

ats1080
Posts: 44
Joined: Thu Sep 27, 2012 2:10 pm

Re: Push Button Input Troubles

Tue Jan 05, 2016 5:31 pm

I hooked up one post of the button to ground, the other to the GPIO pin, and changed my code to the following. Still get 2 detects per button press.

Code: Select all

import RPi.GPIO as GPIO  
import time
GPIO.setmode(GPIO.BCM)

GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_UP) 
presses = 1

def my_callback(channel): 
    global presses
    print "callback called " + str(presses) + " times"
    presses += 1
    

GPIO.add_event_detect(24, GPIO.FALLING, callback=my_callback, bouncetime=100)

print "Waiting"  
while True:
    try:  
        time.sleep(5)
    except KeyboardInterrupt:  
        GPIO.cleanup()
        break

ats1080
Posts: 44
Joined: Thu Sep 27, 2012 2:10 pm

Re: Push Button Input Troubles

Tue Jan 05, 2016 5:34 pm

Actually, changing line 14 to "GPIO.add_event_detect(24, GPIO.RISING, callback=my_callback, bouncetime=300)" works semi reliably now. About 75% of the time it will only detect once per button press.

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4258
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

Re: Push Button Input Troubles

Tue Jan 05, 2016 6:31 pm

An SPDT switch with a capacitor and no pulls -up or -down is the best solution
BadScribble.png
BadScribble.png (3.62 KiB) Viewed 11000 times
but I guess you've got the switch that you want to use.

You don't want to pull in both directions at once, but the capacitor is probably a good idea. The problem you are seeing is due to the switch contacts bouncing -- hence switch bounce. There is no perfect software solution; it seems your switch is particularly badly behaved.

User avatar
karrika
Posts: 1075
Joined: Mon Oct 19, 2015 6:21 am
Location: Finland

Re: Push Button Input Troubles

Tue Jan 05, 2016 6:45 pm

Forget this part. Making lasagna and following the forum does not work.
If you connect the capacitor directly to GND or 3.3V it has no time to charge or discharge.

The resistor needs to be between the switch and the capacitor to eliminate key bounces. Then opening or closing the switch makes the current flow through the resistor to the capacitor charging it.

So if you want to switch between 3.3V and GND then move the capacitor between the GPIO pin and ground.
GoodScribble.png
GoodScribble.png (3.65 KiB) Viewed 10974 times
Last edited by karrika on Tue Jan 05, 2016 7:39 pm, edited 3 times in total.

ats1080
Posts: 44
Joined: Thu Sep 27, 2012 2:10 pm

Re: Push Button Input Troubles

Tue Jan 05, 2016 6:46 pm

Currently I'm using a PCB mount button just like this one:
Image
I had been using a button that was the power switch out of an old Dell computer, but that thing was worthless and bounced no matter what I tried. My current button seems much better but it could also be the problem. I do happen to have an SPDT switch, would that work better? For my final product I will need a push style button. Are there any kinds of push buttons that will work?

ats1080
Posts: 44
Joined: Thu Sep 27, 2012 2:10 pm

Re: Push Button Input Troubles

Tue Jan 05, 2016 6:50 pm

karrika wrote:If you connect the capacitor directly to GND or 3.3V it has no time to charge or discharge.

The resistor needs to be between the switch and the capacitor. Then opening or closing the switch makes the current flow through the resistor to the capacitor charging it.

So if you want to switch between 3.3V and GND then move the capacitor between the GPIO pin and ground.
GoodScribble.png
I'm not very good with reading schematics, but is that not what is happening in the one I posted?

User avatar
karrika
Posts: 1075
Joined: Mon Oct 19, 2015 6:21 am
Location: Finland

Re: Push Button Input Troubles

Tue Jan 05, 2016 6:55 pm

No, it is not. You are shorting the capacitor to ground directly when you close the switch. This means that the key bounces are not filtered by the RC circuit. The current needs to run through a resistor when you close the circuit.

If you add a second resistor between S2 and C1. It could be 1k. Then the system works.

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4258
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

Re: Push Button Input Troubles

Tue Jan 05, 2016 7:23 pm

karrika wrote:So if you want to switch between 3.3V and GND then move the capacitor between the GPIO pin and ground.
You are correct for the original circuit, but not for the one with the SPDT switch.

The capacitor remembers the state while the switch pole is moving and is immediately charged/discharged when the pole makes contact. We need as little resistance between the power lines and the capacitor as possible otherwise we will get an indeterminate voltage on the GPIO. We want as much resistance as possible between the capacitor and the Pi, so that the GPIO has a negligible effect on the charge.

User avatar
karrika
Posts: 1075
Joined: Mon Oct 19, 2015 6:21 am
Location: Finland

Re: Push Button Input Troubles

Tue Jan 05, 2016 7:29 pm

True. Did not notice the change of the role of the capacitor.
Last edited by karrika on Tue Jan 05, 2016 7:32 pm, edited 2 times in total.

ats1080
Posts: 44
Joined: Thu Sep 27, 2012 2:10 pm

Re: Push Button Input Troubles

Tue Jan 05, 2016 7:31 pm

I tried both of your circuits, they both give 2 RISING events whenever the switch is flipped from one position to another back to original position, however, FALLING still works as I would expect with only 1 event per flip (flipped from one position to another back to original position).

User avatar
karrika
Posts: 1075
Joined: Mon Oct 19, 2015 6:21 am
Location: Finland

Re: Push Button Input Troubles

Tue Jan 05, 2016 7:47 pm

This sounds like the voltage at the GPIO pin is in the gray area. A 47k pullup is about the same magnitude as the internal weak pullup of the Pi.

It is important that the internal and external pullups don't pull in opposite directions.

There is now many different schematics. But if we go from your original one I would reduce the 47k to 10k, add a 1k series resistor and perhaps make the capacitor smaller. Around 10n perhaps.

User avatar
joan
Posts: 14585
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Push Button Input Troubles

Tue Jan 05, 2016 7:49 pm

ats1080 wrote:I tried both of your circuits, they both give 2 RISING events whenever the switch is flipped from one position to another back to original position, however, FALLING still works as I would expect with only 1 event per flip (flipped from one position to another back to original position).
Try another Python GPIO module?

ats1080
Posts: 44
Joined: Thu Sep 27, 2012 2:10 pm

Re: Push Button Input Troubles

Tue Jan 05, 2016 7:57 pm

Do any of the other modules support interrupts?

User avatar
joan
Posts: 14585
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Push Button Input Troubles

Tue Jan 05, 2016 8:02 pm

ats1080 wrote:Do any of the other modules support interrupts?
They all support callbacks (to be pedantic Linux handles interrupts).

User avatar
karrika
Posts: 1075
Joined: Mon Oct 19, 2015 6:21 am
Location: Finland

Re: Push Button Input Troubles

Tue Jan 05, 2016 8:06 pm

The problem is that one interrupt makes more than one callback (rising).

I cannot easily explain how this would be caused by software. But I can explain how unfiltered key bounces cause many rising edges and no falling edges. The DC level is just below logic "1" threshold.

User avatar
joan
Posts: 14585
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Push Button Input Troubles

Tue Jan 05, 2016 8:09 pm

karrika wrote:The problem is that one interrupt makes more than one callback (rising).

I cannot easily explain how this would be caused by software. But I can explain how unfiltered key bounces cause many rising edges and no falling edges. The DC level is just below logic "1" threshold.
Possibly, however 300 ms of debounce suggests a very odd switch.

ait
Posts: 127
Joined: Sun Oct 30, 2011 6:51 pm

Re: Push Button Input Troubles

Tue Jan 05, 2016 8:12 pm

Hello,
what happened when you delete "GPIO.cleanup()" ?

ats1080
Posts: 44
Joined: Thu Sep 27, 2012 2:10 pm

Re: Push Button Input Troubles

Tue Jan 05, 2016 8:26 pm

karrika wrote:This sounds like the voltage at the GPIO pin is in the gray area. A 47k pullup is about the same magnitude as the internal weak pullup of the Pi.

It is important that the internal and external pullups don't pull in opposite directions.

There is now many different schematics. But if we go from your original one I would reduce the 47k to 10k, add a 1k series resistor and perhaps make the capacitor smaller. Around 10n perhaps.
I went back to the original schematic (with push button). I don't have a 10n capacitor, but I can check when I get home for one. For now I'm still using the 100n capacitor. I replaced the 47k with a 10k and added a 1k where you said and it didn't help. The FALLING is near perfect as usual and the RISING is still detecting twice per push. Will the 10u capacitor make a difference?

I also tried not specifying a software pull down using "GPIO.setup(24, GPIO.IN)" and I still get the same results.

ats1080
Posts: 44
Joined: Thu Sep 27, 2012 2:10 pm

Re: Push Button Input Troubles

Tue Jan 05, 2016 8:28 pm

ait wrote:Hello,
what happened when you delete "GPIO.cleanup()" ?
GPIO.cleanup() only resets the pins to default values. I don't think this would have any effect, would it?
joan wrote:
ats1080 wrote:Do any of the other modules support interrupts?
They all support callbacks (to be pedantic Linux handles interrupts).
Some suggestions would be helpful

User avatar
karrika
Posts: 1075
Joined: Mon Oct 19, 2015 6:21 am
Location: Finland

Re: Push Button Input Troubles

Tue Jan 05, 2016 8:37 pm

The capacitor value makes no difference.

I believe we are overlooking something. But the lasagna is ready and my teenagers are rushing in for food.

Signing out for tonight.

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4258
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

Re: Push Button Input Troubles

Tue Jan 05, 2016 8:41 pm

What happens if you take the capacitor out entirely and drop to 1k? I agree it is beginning to sound like the voltage at the GPIO is marginal.

User avatar
joan
Posts: 14585
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Push Button Input Troubles

Tue Jan 05, 2016 8:55 pm

ats1080 wrote:
joan wrote:
ats1080 wrote:Do any of the other modules support interrupts?
They all support callbacks (to be pedantic Linux handles interrupts).
Some suggestions would be helpful
http://elinux.org/RPi_GPIO_Code_Samples#Python

I'm interested in whether my pigpio shows the same behaviour.

Code: Select all

#!/usr/bin/env python

import time
import pigpio

BUTTON=24

presses = 1

def my_callback(gpio, level, tick):
    global presses
    print "callback called " + str(presses) + " times"
    presses += 1
   
pi = pigpio.pi() # connect to Pi

if not pi.connected:
   exit(0)

pi.set_mode(BUTTON, pigpio.INPUT)
pi.set_pull_up_down(BUTTON, pigpio.PUD_DOWN)
pi.set_glitch_filter(BUTTON, 0) # no glitch filter

cb = pi.callback(BUTTON, pigpio.FALLING_EDGE, my_callback)

print "Waiting" 

while True:
    try: 
        time.sleep(5)
    except KeyboardInterrupt: 
        break

cb.cancel() # cancel callback
pi.stop() # disconnect from Pi

ats1080
Posts: 44
Joined: Thu Sep 27, 2012 2:10 pm

Re: Push Button Input Troubles

Tue Jan 05, 2016 9:31 pm

rurwin wrote:What happens if you take the capacitor out entirely and drop to 1k? I agree it is beginning to sound like the voltage at the GPIO is marginal.
Are you talking about the circuit I originally posted, or the one you posted?
joan wrote:
ats1080 wrote:
joan wrote: They all support callbacks (to be pedantic Linux handles interrupts).
Some suggestions would be helpful
http://elinux.org/RPi_GPIO_Code_Samples#Python

I'm interested in whether my pigpio shows the same behaviour.

Code: Select all

#!/usr/bin/env python

import time
import pigpio

BUTTON=24

presses = 1

def my_callback(gpio, level, tick):
    global presses
    print "callback called " + str(presses) + " times"
    presses += 1
   
pi = pigpio.pi() # connect to Pi

if not pi.connected:
   exit(0)

pi.set_mode(BUTTON, pigpio.INPUT)
pi.set_pull_up_down(BUTTON, pigpio.PUD_DOWN)
pi.set_glitch_filter(BUTTON, 0) # no glitch filter

cb = pi.callback(BUTTON, pigpio.FALLING_EDGE, my_callback)

print "Waiting" 

while True:
    try: 
        time.sleep(5)
    except KeyboardInterrupt: 
        break

cb.cancel() # cancel callback
pi.stop() # disconnect from Pi
Your code works perfect for both RISING and FALLING! So...what's the deal with rpi.gpio? I should add that I'm still using the circuit karrika suggested. I went back to My code again without changing anything just to double check that my Pi2 at home was not somehow acting differently than my other Pi2 and it is not. I still get the double RISING detects.
Last edited by ats1080 on Tue Jan 05, 2016 9:35 pm, edited 1 time in total.

Return to “Troubleshooting”