Hallo Leute,
ich wollte die Anzahl der Tastendruecke ueber einen kurzen Zeitraum zaehlen um dann entsprechend eine Aktion auszufuehren. Koennt ihr mir einen Tipp geben. Fuer Python3 natuerlich.
Guten Rutsch,
gutschy
Hallo Leute,
ich wollte die Anzahl der Tastendruecke ueber einen kurzen Zeitraum zaehlen um dann entsprechend eine Aktion auszufuehren. Koennt ihr mir einen Tipp geben. Fuer Python3 natuerlich.
Guten Rutsch,
gutschy
Tasten betaetigungen in einem Zeitraum zaehlen. Z.b. 3 x in 2 Sekunden. gpiozero, Python3? Schau mal ob du hier fündig wirst!
Die Doku lesen und mit Flags und Countern arbeiten? Mal ernsthaft, was für eine Antwort erwartest du hier?
Das ist kein "Wir schreiben deinen Code"-Forum. Probiere es selbst, dann kannst du mit auftauchenden Problemen hier fragen.
Guten Rutsch,
Also bei uns sind noch nicht mal die Weihnachtsfeiertage rum
Hi linusg,
ja, du hast recht aber ich hatte auch eher an einem Codeschnipsel als Insperation gedacht als an fertig geschriebenen Code. Na ja, hier mal mein Versuch. Die Idee ist, Taster 1 wird gedrueckt, dann sollte eine while Schleife 2 Sekunden warten und die Klick-Anzahl des Taster hochzuzaehlen um dann ueber eine zweite if-Schleife die entsprechende Anweisung auszufuehren. Leider geht der Motor schon beim ersten Tastendruck von taster_start an. Deine Vorschlaege mit counter und flags habe ich mal in Google geschmissen, konnte ich aber nicht umsaetzen, bzw. bei flags habe ich nicht mal begriffen worum es geht.
#!/usr/bin/env python3
#H-Bruecke
from gpiozero import Motor, Button
import time
from time import sleep
schalter_start = Button(13)
schalter_vorne = Button(19)
schalter_hinten = Button(26)
position = 3
klick_zahl = 0
klick_max = 3
motor = Motor(forward=4, backward=17)
t_end = time.time() + 2
while True:
if schalter_start.is_pressed and position == 3:
while time.time() < t_end:
while klick_zahl < klick_max:
if schalter_start.is_pressed:
klick_zahl = klick_zahl + 1
if klick_zahl == 2:
motor.forward()
sleep(9)
motor.stop()
position = 2
print("Klickzahl 3")
elif klick_zahl == 1:
motor.forward()
sleep(6)
motor.stop()
position = 2
print("Klickzahl 2")
elif klick_zahl == 0:
motor.forward()
sleep(3)
motor.stop()
position = 2
print("Klickzahl 1")
elif schalter_hinten.is_pressed:
motor.stop()
position = 2
motor.backward()
sleep(1)
motor.stop()
elif schalter_vorne.is_pressed:
motor.stop()
position = 3
motor.forward()
sleep(1)
motor.stop()
elif schalter_start.is_pressed and position == 2:
motor.backward()
klick_zahl = 0
Alles anzeigen
Hoffe du hast da eine Idee wenn du noch magst.
Frohe Weihnachten und einen guten Rutsch!
gutschy
Okay, also nochmal zur Klarstellung: Du möchtest zählen, wie oft ein Button in einem Zeitraum von z.B. zwei oder drei Sekunden gedrückt und losgelassen wird. Richtig? Allgemein solltest du leicht anfangen, dein Code ist schon etwas unübersichtlich und komplex. Versuche es doch erst einmal mit dem einen Button und füge dann erst die anderen Funktionen hinzu.
Ungetestet:
#!/usr/bin/env python3
import time
from gpiozero import Button
TIMEDELTA = 2
last_check = time.time()
n_pressed = 0
button_start = Button(13)
def handle_button_start():
n_pressed += 1
button_start.when_pressed = handle_button_start
while True:
if time.time() - last_check > TIMEDELTA:
print("Button was pressed for {0} times within the last {1} seconds".format(n_pressed, TIMEDELTA))
n_pressed = 0
last_check = time.time()
time.sleep(0.01)
Alles anzeigen
In Python zählt man nicht selber sonder man lässt zählen (Suchfunktion benutzen)...
Auch sollte man aussagekräftige Namen wählen. n_pressed bedeutet, dass die "n" Taste gedrückt wurde oder was?
n wie number ... vermutlich
Hi linusg,
hab dein Skript jetzt mal probelaufen lassen, brachte leider eine Fehlermeldung.
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/gpiozero/pins/rpigpio.py", line 213, in _call_when_changed
super(RPiGPIOPin, self)._call_when_changed()
File "/usr/lib/python2.7/dist-packages/gpiozero/pins/pi.py", line 268, in _call_when_changed
method()
File "/usr/lib/python2.7/dist-packages/gpiozero/mixins.py", line 323, in _fire_events
self._fire_activated()
File "/usr/lib/python2.7/dist-packages/gpiozero/mixins.py", line 355, in _fire_activated
super(HoldMixin, self)._fire_activated()
File "/usr/lib/python2.7/dist-packages/gpiozero/mixins.py", line 301, in _fire_activated
self.when_activated()
File "i_linus_button.py", line 11, in handle_button_start
n_pressed += 1
UnboundLocalError: local variable 'n_pressed' referenced before assignment
Alles anzeigen
Und es gab keine Hochzaehlen von n_pressed.
Button was pressed for 0 times within the last 2 seconds
Button was pressed for 0 times within the last 2 seconds
Button was pressed for 0 times within the last 2 seconds
Button was pressed for 0 times within the last 2 seconds
Button was pressed for 0 times within the last 2 seconds
Button was pressed for 0 times within the last 2 seconds
Button was pressed for 0 times within the last 2 seconds
Button was pressed for 0 times within the last 2 seconds
Button was pressed for 0 times within the last 2 seconds
Immerhin loeste der Button die Fehlermeldung aus. Ich kann sowieso nur die letzte Zeile einigermassen zuordnen.
File "i_linus_button.py", line 11, in handle_button_start
n_pressed += 1
UnboundLocalError: local variable 'n_pressed' referenced before assignment
Aber Variablen in Python muessen doch gar nicht erst referenziert werden, oder? Bzw. habe ich n_pressed auch mal auf Global gesetzt, da brachte aber die gleiche Fehlermeldung.
Sorry, mein Fehler. Ist zwar ne dreckige Lösung, aber setze mal vor n_pressed += 1 eine Zeile global n_pressed.
Nope, wie gesagt, die gleiche Fehlermeldung.
#!/usr/bin/env python3
import time
from gpiozero import Button
TIMEDELTA = 2
last_check = time.time()
global n_pressed
n_pressed = 0
button_start = Button(13)
def handle_button_start():
n_pressed += 1
button_start.when_pressed = handle_button_start
while True:
if time.time() - last_check > TIMEDELTA:
print("Button was pressed for {0} times within the last {1} seconds".format(n_pressed, TIMEDELTA))
n_pressed = 0
last_check = time.time()
time.sleep(0.01)
Alles anzeigen
vor n_pressed += 1 eine Zeile global n_pressed.
Hast du nicht getan, ich hatte dich schon verstanden. Da hat das global aber keinen Effekt. Ist doch eh schon global und nicht lokaler Namespace in ner Funktion.
Ahh, jetzt klappt es. Um die Theorie aus Buechern auch verwerten zu koennen muesste ich mich wirklich oefter damit beschaeftigen. Und bei Stackoverflow steht es ja auch richtig, habe es jetzt erst beim zweiten mal gerafft.
Besten Dank soweit, Linus!
Dir einen guten Rutsch.
Ok, und ich dachte, das sei jetzt ein rantasten
Löst das tatsächlich schon das gesamte Thema des Threads? Oder meinst du nur dieses Test-Programm, dass es geht?
Linus Igitt... Was bringst du ihm hier bei?
lies dir mal gpiozero und motion sensor durch
Ich persönlich würde das so machen:
#!/usr/bin/env python3
import time
from gpiozero import Button
class _Counter:
def __init__(self, start=0, step=1):
self.start=start
self.step=step
self.value=start
def increase(self):
self.value += self.step
def decrease(self):
self.value -= self.step
def get(self):
return self.value
def set(self, new_value):
self.value = new_value
def main(btn_pin=16, delta=2):
try:
counter = _Counter()
last_check = time.time()
with Button(btn_pin) as btn:
btn.when_pressed = counter.increase
while True:
if time.time() - last_check > delta:
print("Button was pressed for {0} times within the last {1} seconds".format(counter.get(), delta))
counter.set(0)
last_check = time.time()
time.sleep(0.01)
except KeyboardInterrupt:
pass
if __name__ == '__main__':
main()
# EOF
Alles anzeigen
ungetestet!
- Iteratoren sind in Python bereits in Klassen implementiert. Also sollte man sie auch nutzen (sofern nur hochgezählt werden soll).
- was auch immer _ (Klasse) bedeutet, das gehört da nicht hin auch # EOF
...das macht das ganze aber IMHO wieder unnötig kompliziert, da nicht nur hoch gezählt wird sondern der counter auch wieder zurückgesetzt werden muss. Zudem ist der Aufruf next(counter) wie ich finde irreführend, kann in der print Ausgabe von Linus 's Script so auch nicht verwendet werden da dann automatisch hoch gezählt wird und somit der tatsächliche Wert verfälscht wird...
_ deshalb weil es über collections bereits Counter gibt, also kein Konflikt entstehen soll. Und # EOF ist ein Kommentar, was ich immer setze um Anfängern zu verdeutlichen dass danach nichts mehr kommt
Tja Leute, kann ich mich ja nur bedanken das hier so intensiv ueber die Loesung meiner Probleme nachgedacht wird. Leider ist dieses Klassen Ding der Hauptgrund warum ich mal mit C angefangen bin. Klassen sind fuer mich echt schlecht nachzuvollziehen, obwohl ich ihren Sinn auch schon mal umrissen hatte. (Das mit den Vererbungen finde sogar ich praktisch.) Leider sind meine Python Anwendungen zumindest im Moment noch sehr sporadisch. Da halte ich das Anwenden von Klassen fuer uebertrieben, ich halte mich da an den Vorschlag von linusg, den kriege ich auch irgendwie in mein Skript eingebaut, hoffe ich mal.
Aber nochmal Danke, nur noetigen mich eure Beispiele wirklich dazu mich nochmal in das Konzept der Klassen einzuarbeiten, was ich frueher oder spaeter auf jeden Fall noch mal machen werde, nur nicht diese Woche. Gibt noch soviel was ich erledigen will.
linusg, meigrafd und bootsmann ich wuenschen euch einen guten Rutsch.
gutschy
P.S. bootsmann, meinst du damit den Bernhardiner?
Hallo,
meigrafd: warum hast du `get` und `set` Methoden, die operieren doch nur auf den Attributen... Wir sind doch nicht bei Java, wo das nötig ist. Warum kein direkter Attributzugriff?
bootsmann: die Implementierung finde ich auch fragwürdig aka verwirrend. Warum implementierst du einen einfacher Zähler, der genau einen Wert hat, als Iterator?
Gruß, noisefloor
meigrafd - da hast du ja aus meinem Gewurschtel doch noch schönen Python Code gemacht
Ich weiß, die _Counter Klasse ist eine allgemeine, aber für diesen simplen Fall würde ich sie doch noch stark vereinfachen, und zu einer Namenskollision sollte es hier wohl auch nicht kommen. Ansonsten: from foo import Bar as FooBar
#!/usr/bin/env python3
import time
from gpiozero import Button
class Counter:
def __init__(self):
self.value = 0
def increase(self):
self.value += 1
def main(btn_pin=16, delta=2):
try:
counter = Counter()
last_check = time.time()
with Button(btn_pin) as btn:
btn.when_pressed = counter.increase
while True:
if time.time() - last_check > delta:
print("Button was pressed for {0} times within the last {1} seconds".format(counter.value, delta))
counter.value = 0
last_check = time.time()
time.sleep(0.01)
except KeyboardInterrupt:
pass
if __name__ == '__main__':
main()
Alles anzeigen
Ob man das counter.value = 0 noch in eine Methode counter.reset() oder tatsächlich counter.set(0) packt ist wohl Geschmackssache. Aber es erfüllt wohl seinen Zweck.
Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!