I have the following script I used for testing:
#!/usr/bin/env python2.7
import RPi.GPIO as GPIO, time, subprocess, threading, socket, signal
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
button=21
led=19
GPIO.setup(button, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(led, GPIO.OUT)
GPIO.output(led,True)
def buttonpressed(channel):
if GPIO.input(button):
GPIO.output(led,True)
print "rising edge detected on " + str(button)
else:
GPIO.output(led,False)
print "falling edge detected on " + str(button)
# when a falling edge is detected on button, regardless of whatever
# else is happening in the program, the function my_callback will be run
GPIO.add_event_detect(button, GPIO.BOTH, callback=buttonpressed, bouncetime=200)
print "Waiting for button to be pressed"
while True:
try:
time.sleep(3600)
print "still waiting for button..."
except KeyboardInterrupt:
print "Exption caught after timer."
if killer.kill_now:
break
GPIO.cleanup() # clean up GPIO on normal exit
schematic
simulate this circuit – Schematic created using CircuitLab
Using an NO button on testing only the first button press is reliably sensed, but occasionally other presses are. Sample output:
$ ./test.py
Waiting for button to be pressed
falling edge detected on 21
rising edge detected on 21
rising edge detected on 21
rising edge detected on 21
rising edge detected on 21
rising edge detected on 21
rising edge detected on 21
rising edge detected on 21
rising edge detected on 21
rising edge detected on 21
falling edge detected on 21
rising edge detected on 21
rising edge detected on 21
rising edge detected on 21
rising edge detected on 21
rising edge detected on 21
If I remove the bouncetime I get a lot of false positives, and if I put it to 1ms it is relatively reliable but still not great.
As it seems to be clear that I need to put a capacitor in place is there any alternative to adding this, and if not what size of capacitor should I need? Are there any other attributes I should be mindful of when shopping for a capacitor?
-
It's early morning so I may be missing something, but shorting pin 21 directly to ground through the switch doesn't seem right...stevieb– stevieb2017年01月04日 14:32:44 +00:00Commented Jan 4, 2017 at 14:32
-
How else would you do it?fileinsert– fileinsert2017年01月04日 21:09:51 +00:00Commented Jan 4, 2017 at 21:09
-
I was just misunderstanding what you were trying to achieve here.stevieb– stevieb2017年01月04日 21:17:39 +00:00Commented Jan 4, 2017 at 21:17
4 Answers 4
Your problem is probably caused by the state of the switch which may change between the event triggering and your call to
GPIO.input(button)
I think that the only solution is to use hardware debouncing with a small capacitor in parallel to the switch.
Reduce or remove bouncetime=200
entirely in
GPIO.add_event_detect(button, GPIO.BOTH, callback=buttonpressed, bouncetime=200)
Then in your callback, add a static variable and a condition statement that will accept the input only if the edge is different from the previous one :
def buttonpressed(channel):
if "previous_edge" not in buttonpressed.__dict__:
buttonpressed.previous_edge = None
if GPIO.input(button) != buttonpressed.previous_edge:
if GPIO.input(button):
GPIO.output(led,True)
print "rising edge detected on " + str(button)
else:
GPIO.output(led,False)
print "falling edge detected on " + str(button)
buttonpressed.previous_edge = GPIO.input(button)
That should get rid of the bounces.
Add two resistors and a capacitor to the contact switch to form a deboucing circuit such as this:
This will correct your signal input.
I suggest that you read A Guide to Debouncing August 2004 by Jack G. Ganssle, August 2004 by Jack G. Ganssle.
My take in two parts:
The edge detection is a simple algorithm, you keep track of the current state of the pin and when the next state is read you compare the two. You then decide wether it was an edge or not: https://fritzenlab.net/2024/04/20/falling-and-rising-edge-input/ .
The debounce can also be made by algorithm, this way: once you detect an edge (step above) you wait for a couple of milisseconds, for the physical switch to stabilize. Once that time has passed you are good to go.