Seite 1 von 1
Taster entprellen mit der Funktion bouncetime
Verfasst: Sonntag 13. November 2016, 18:33
von PatrickH
Hallo,
ich möchte für mein Projekt ein Taster interrupt gesteuert abfragen. Nun hat dieser Taster die unangenehme Eigenschaft zu Prellen.
In meinem Programm habe ich in der Funktioen GPIO.add_event die Möglichkeit dieses mittels bouncetime zu unterdrücken.... theoretisch.
Leider wird diese Funktion mindstens zwei mal ausgeführt. Wenn ich mit extremen Werten für bouncetime heran gehe (z.b. 5000) kommt der zweite event eben später, aber er kommt.
Code: Alles auswählen
#!/usr/bin/python
import RPi.GPIO as GPIO
import time, sys
import urllib2
import datetime
# Variabelen deklarieren
Schalter_PIN = 12 # Eingang GPIO1
EVENT = 'person_enter_leave'
BASE_URL = 'https://maker.ifttt.com/trigger/'
KEY = 'hier ist der key'
# Pin-Nummern verwenden (nicht GPIO-Nummern!)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(Schalter_PIN, GPIO.IN)
#Funktion definieren, um beim Schalterwechsel den IFTTT trigger zu setzen
def send_event(pin):
response = urllib2.urlopen(BASE_URL + EVENT + '/with/key/' + KEY)
print(response.read())
# switch_on-Funktion aufrufen, wenn das Signal wechselt
GPIO.add_event_detect(12, GPIO.BOTH, bouncetime=200)
GPIO.add_event_callback(12, send_event)
# mit minimaler CPU-Belastung auf das Programmende durch Strg+C warten
try:
while True:
time.sleep(5)
except KeyboardInterrupt:
GPIO.cleanup()
print("\nBye!")
sys.exit()
Angeschlossen habe ich den Schalter Über einen pull up Widerstand von 10k Ohm (von pin1 3,3Volt) und einen Vorwiderstand von 1k Ohm an Pin 12. Der Schalter liegt nun mit der einen Seite zwischen den beiden Wiederständen und mit der anderen Seite an Masse (pin6)
Es würde mich freuen, wenn hier jemand eine Lösung finden könnte.
LG
Patrick
Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Sonntag 13. November 2016, 18:46
von BlackJack
@PatrickH: Nur um das offensichtliche auszuschliessen: Das ist ein *Taster* und kein *Schalter* und Du reagierst explizit auf *beide* Flanken. Dir ist klar, dass die Rückruffunktion aufgerufen wird wenn man den Taster drückt *und* wenn man ihn wieder loslässt‽
Edit: Die Rückruffunktion kann man übrigens schon bei `add_event_detect()` angeben.
Und der Kommentar über das CPU-schonende warten stimmt auch nicht ganz, denn es wird immer noch ab und zu Python-Code in einer Schleife ausgeführt. `signal.pause()` wäre noch ein klein wenig weniger CPU-Zeit.

Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Sonntag 13. November 2016, 18:57
von PatrickH
Hallo BlackJack,
vielen Dank für die schnelle Antwort. Ja, mir ist klar, dass auf beide Flanken reagiert wird. Das ist auch so gewollt. Leider halt pro Flanke zwei Mal.
Das bedeutet der *Taster* wird gedrückt (es werden zwei Events getriggert) .... und losgelassen (es werden wieder zwei Events getriggert)
In Summe vier getriggerte Events anstelle von zweien.
Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Sonntag 13. November 2016, 23:32
von __deets__
Die traurige Wahrheit ist - RPi.GPIO ist Mist. Auch andere berichten von dem Problem:
https://www.raspberrypi.org/forums/view ... 32&t=50833
Nimm besser PIGPIO. Das funktioniert fuer mich deutlich zuverlaessiger. Alternativ kannst du natuerlich auch um dein Problem rumkodieren, indem du dir merkst, ob du steigend/fallend schon bekommen hast. Ist aber natuerlich murksig...
Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Sonntag 13. November 2016, 23:40
von BlackJack
Das ist von 2013, hat das echt noch keiner gefixt?

Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Montag 14. November 2016, 22:54
von __deets__
Keine Ahnung. Das Funktionsprinzip von RPi.GPIO ist auch eher mau. Es arbeitet auf den Linux-eigenen GPIO-sysfs-Abstraktionen. Klingt gut, ist faktisch schlecht. Man bekommt nur mit vom Kernel, *das* was passiert ist - aber nicht was. Das muss man dann selber einlesen, und das haengt natuerlich davon ab, wieviel Zeit zwischen Ereignis & Scheduler entscheided "jetzt ist Python mal wieder dran" so vergeht.
Ich empfehle dieser Tage PIGPIO. Das arbeitet mit einem DMA-Kanal, der einfach alle GPIOs permanent mit 1M sampled. Aus einem Echtzeitthread wird man dann benachrichtigt (in C), oder per Socket. Und zwar gleich mit Flanke & ggf. mehreren Events, die seit dem letzten mal angefallen sind. Viel robusteres Design.
Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Dienstag 15. November 2016, 19:56
von PatrickH
Hallo,
vielen Dank für die vielen Antworten.
Aufgrund dieser Infos konnte ich nun auch nachlesen, dass bei event getriggerten Ereignissen RPi.GPIO nicht zu empfehlen ist, und das scheinbar mindestens schon seit 2013.
Okay, soweit so gut. Nun wird mein weiteres Vorgehen PIGPIO einbeziehen.
Dies muss ich vermutlich erst noch installieren...
Code: Alles auswählen
sudo apt-get update
sudo apt-get install pigpio python-pigpio python3-pigpio
jedoch ist die Verwendung einigermaßen verschieden...
Ich würde mich über eine Hilfestellung bezüglich meines Ursprungs Programmes für die Verwendung von PIGPIO freuen
LG
Patrick
Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Donnerstag 17. November 2016, 18:52
von PatrickH
Hallo,
nach einiger Recherche habe ich nun folgenden code mit pigpio zum laufen bekommen
Code: Alles auswählen
#!/usr/bin/python
import pigpio
import time, sys
import urllib2
import datetime
import time
# Variabelen deklarieren
Schalter_PIN = 18 # Eingang GPIO1 (BCM)
EVENT = 'person_enter_leave'
BASE_URL = 'https://maker.ifttt.com/trigger/'
KEY = 'hier ist ein key'
pi = pigpio.pi()
counter = 0
# GPIO 18 = Input
pi.set_mode(Schalter_PIN, pigpio.INPUT)
#pi.set_pull_up_down(Schalter_PIN, pigpio.PUD_UP)
#Funktion definieren, um beim Schalterwechsel den IFTTT trigger zu setzen
def send_event(gpio, level, tick):
global counter
if counter < 2:
response = urllib2.urlopen(BASE_URL + EVENT + '/with/key/' + KEY)
print(response.read())
print(counter)
counter = counter + 1
else:
time.sleep(2)
counter = 0
# switch_on-Funktion aufrufen, wenn Signal wechselt
pi.callback(Schalter_PIN, pigpio.EITHER_EDGE, send_event)
#auf das Programmende durch Strg+C warten
try:
while True:
time.sleep(5)
except KeyboardInterrupt:
print("\nBye!")
sys.exit()
das Ergebnis sieht so aus:
Code: Alles auswählen
>>> ================================ RESTART ================================
>>>
Congratulations! You've fired the person_enter_leave event
0
Congratulations! You've fired the person_enter_leave event
1
Congratulations! You've fired the person_enter_leave event
0
Congratulations! You've fired the person_enter_leave event
1
Congratulations! You've fired the person_enter_leave event
0
Congratulations! You've fired the person_enter_leave event
1
Congratulations! You've fired the person_enter_leave event
0
Congratulations! You've fired the person_enter_leave event
1
Congratulations! You've fired the person_enter_leave event
0
Congratulations! You've fired the person_enter_leave event
1
Congratulations! You've fired the person_enter_leave event
0
Congratulations! You've fired the person_enter_leave event
Bedeutet auch mit pigpio kann ich ein Schalterprellen nicht beseitigen (also die Auswirkungen davon). Scheinbar wird die Anzahl des events gespeichert und nacheinander der callback ausgelöst.
Vielleicht hat jemand Erfahrung und kann mir hierzu einen tipp geben.
LG
Patrick
Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Donnerstag 17. November 2016, 21:02
von BlackJack
@PatrickH: Ich sehe da jetzt aber auch nicht das Du die Filterfunktion verwendest‽
Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Freitag 18. November 2016, 05:56
von PatrickH
Hallo BlackJack
ja, so richtig habe ich keine Filterfunktion a la "bouncetime" in der pigpio gefunden. Daher habe ich mir die Geschichte mit der if - else Abfrage ausgedacht.
Möglicherweise könnte noch die Funktion "edge_detect" zum Ziel führen.
LG
Patrick
Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Freitag 18. November 2016, 10:50
von __deets__
Natuerlich kann PIGPIO nicht magisch das Prellen eliminieren - woher soll es wissen, dass dein Schalter prellt, statt das er so arbeiten soll?
Du kannst zB die Funktion
http://abyz.co.uk/rpi/pigpio/python.htm ... tch_filter ausprobieren, oder
http://abyz.co.uk/rpi/pigpio/python.htm ... ise_filter
Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Freitag 18. November 2016, 10:52
von DeaD_EyE
Du möchtest folgende Funktion verwenden:
http://abyz.co.uk/rpi/pigpio/python.htm ... tch_filter
Den Schalter/Taster kann man auch Hardwareseitig mit einem Kondensator zu entprellen.
Wie das geht, kann man hier nachlesen:
http://www.mikrocontroller.net/articles/Entprellung.
Im Artikel steht unter anderem auch, dass Hardware-Entprellung immer seltener gemacht wird,
da die Mikrocontroller das Softwaremäßig billiger lösen können.
Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Freitag 18. November 2016, 12:40
von PatrickH
Hallo,
der "glitch_filter" oder "noise_filter" hören sich vielversprechend an... das wird mein nächster Versuch.
@DeaD_EyE: hardwareseitig habe ich schon Versuche mit Kondensator gefahren (noch mit rpi.GPIO). War jedoch nur mäßig erfolgreich. Vermutlicherweise weil die Ladekurve vom Kondensator recht lange im "verbotenen Bereich" rum dümpelt.
Sollten die oben genannten Funktionen nicht klappen werde ich das mal mit einem Wechsler und RS-Flipflop testen.
LG
Patrick
Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Freitag 18. November 2016, 23:41
von __deets__
Ich wuerde ja denken Kondensator + Schmitt-Trigger, und gut ist. Aber wie gesagt, das geht in Software, und eigentlich sollte das mit dem PIGPIO-Ding funktionieren.
Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Samstag 19. November 2016, 19:04
von PatrickH
Hallo,
also mein glitchFilter macht mir Sorgen...
Eingebunden habe ich diesen auf folgende Art
Code: Alles auswählen
#!/usr/bin/python
import pigpio
import time, sys
import urllib2
import datetime
import time
# Variabelen deklarieren
Schalter_PIN = 18 # Eingang GPIO1 (BCM)
EVENT = 'person_enter_leave'
BASE_URL = 'https://maker.ifttt.com/trigger/'
KEY = 'hier key einfügen'
pi = pigpio.pi()
counter = 0
# GPIO 18 = Input
pi.set_mode(Schalter_PIN, pigpio.INPUT)
#Funktion definieren, um beim Schalterwechsel den IFTTT trigger zu setzen
def send_event(gpio, level, tick):
global counter
print (counter, 'Auslösungen')
counter = counter + 1
# switch_on-Funktion aufrufen, wenn Signal wechselt
pi.gpioGlitchFilter(Schalter_PIN, 300)
pi.callback(Schalter_PIN, pigpio.EITHER_EDGE, send_event)
#auf das Programmende durch Strg+C warten
try:
while True:
time.sleep(5)
except KeyboardInterrupt:
# GPIO.cleanup()
print("\nBye!")
sys.exit()
und als Ergebnis kommt dies...
Code: Alles auswählen
>>> ================================ RESTART ================================
>>>
Traceback (most recent call last):
File "/home/pi/Documents/Python Projects/Python 2/person_enter_leave_v3.py", line 28, in <module>
pi.gpioGlitchFilter(Schalter_PIN, 300)
AttributeError: pi instance has no attribute 'gpioGlitchFilter'
>>>
es scheint, ich habe die Funktion noch nicht richtig angewendet.
@BlackJack: wenn Du mir mal zeigen könntest wie ich den Quelltext in Python-Codebox-Tags setzen kann, würde ich das gerne so tun.
Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Samstag 19. November 2016, 19:18
von __deets__
Aus dieser Doku
http://abyz.co.uk/rpi/pigpio/python.htm ... tch_filter hast du den Aufruf fuer glitch-Filter offensichtlich nicht. Woher dann?
Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Sonntag 20. November 2016, 06:29
von PatrickH
@_deets_: Doch schon, nur von einer anderen Stelle:
http://abyz.co.uk/rpi/pigpio/cif.html#gpioGlitchFilter
Das war offensichtlich nicht so die richtige Stelle
Re: Taster entprellen mit der Funktion bouncetime
Verfasst: Sonntag 20. November 2016, 06:51
von PatrickH
Hurra, der glitch_filter scheint zu klappen.
Kaum macht man es richtig, funktionniert's.
Nun kann ich mich meiner nächsten Aufgabe widmen... mit hilfe der urllib2 meinem aufgerufenen link noch JSON Daten mitzugeben
Vielen Dank für Eure Unterstützung,
Patrick