Seite 1 von 1

Reaktionszeit bei Button eingaben?

Verfasst: Samstag 29. April 2023, 13:31
von DoGro
Guten Tag ,

Ich verwende ein Raspberry Pi Pico von 2020. Und programmiere das erste mal auf einem Microcontroller.

Dort ich versuche den Button S2 zum hochzählen zu programmieren, solange der Button S1 gedrückt ist.
Leider zählt er nicht bei jedem drücken hoch.
Ich weiß nicht genau woran das liegt, ob an den sleep Zeiten oder ob der Speicher überlastet ist?

Für Hilfe wäre ich sehr dankbar.
Viele Grüße
DoGro

Code: Alles auswählen

from machine import Pin
from time import sleep_ms

#Pins
button_S1 = Pin(16, Pin.IN, Pin.PULL_DOWN)
button_S2 = Pin(18, Pin.IN, Pin.PULL_DOWN)


class ButtonEvent:
    def __init__(self, name):
        self.name = name
        self.last = False
        
    def is_pressed(self):
        pressed = self.name.value()
        sleep_ms(50)
        self.last = pressed
        return pressed
        
    
    def has_changed(self):
        pressed = self.is_pressed()
        changed = (self.name.value() != self.last)
        self.last = pressed
        sleep_ms(50)
        return changed
    

def count():
    counter = 0
    button1 = ButtonEvent(button_S1)
    button2 = ButtonEvent(button_S2)
    sleep_ms(500)
    if button1.is_pressed():
        print('ha')
        x = True
        while x:  
            if button1.has_changed():
                print('Ende')
                x = False
            elif button2.has_changed():
                print('counter: '+ str(counter))
                counter += 1
    return counter


#Hauptprogramm
zahl = 0

zahl = count()
print(zahl)

Re: Reaktionszeit bei Button eingaben?

Verfasst: Samstag 29. April 2023, 14:01
von __deets__
Da ist viel im Argen. Ein Argument name zu nenne, obwohl es ein Button ist. Die ganze Schlaferei, und Anlage von ungenutztem Zustand wie self.last.

Das problem ist einfach zu lösen, indem du

- die IRQ Funktion beim Pin zu benutzen, der gezählt werden soll.
- wenn der IRQ auslöst, einfach abtragen, ob gerade der andere Button gedrückt ist. Wenn ja, Counter hochzählen.

In der Hauptschleife einfach dauerhaft den Zählerstand ausgeben, ggf mit schlafen dazwischen.

Re: Reaktionszeit bei Button eingaben?

Verfasst: Samstag 29. April 2023, 17:29
von DoGro
Ah vielen Dank an die Interrupts habe ich gar nicht gedancht.

Code: Alles auswählen

from machine import Pin
import utime

# Button-Pins definieren
button_S1 = Pin(16, Pin.IN, Pin.PULL_DOWN)
button_S2 = Pin(18, Pin.IN, Pin.PULL_DOWN)


# Interrupt für Button 2 definieren
def button2_interrupt(pin):
    utime.sleep_ms(100)  #Entrpellen
    global counter
    if button_S1.value():
        counter += 1

# Interrupt an Pins binden
button_S2.irq(trigger=Pin.IRQ_FALLING, handler=button2_interrupt)

# Hauptprogramms
counter = 0
while True:
    print(counter)
    utime.sleep(1)
Vielen Dank für deine Hilfe

Das einzige Problem jetzt ist noch, dass der doch ab und zu bei einem Knopfdruck den Counter um 2 hochsetzt.
Liegt das an der sleep-Zeit?

Ich habe da an das Entprellen gedacht. Was das Phänomen verringert, allerdings nicht verhindert.

Re: Reaktionszeit bei Button eingaben?

Verfasst: Samstag 29. April 2023, 23:52
von __deets__
Niemals im IRQ schlafen. Wenn du prellen Verhindern willst, nimm einen Zeitstempel & ignorier neue Ereignisse 100ms lang.

Wenn du pulldowns aktivierst, warum reagierst du dann auf die fallende Flanke? Das zählt dann doch loslassen.

Außer prellen fällt mir zur Ursache erstmal auch nichts ein. Ich würde da mit einem logic analyzer draufschauen.

Re: Reaktionszeit bei Button eingaben?

Verfasst: Sonntag 30. April 2023, 18:31
von DoGro
Hallo deets,

vielen Dank für deine Hilfe.
Das verwenden des Zeitstempel hat das Problem so gut wie komplett gelöst.
Die Feinabstimmung kann ich dann hoffentlich bei weiteren Projekten und mehr Erfahrung vornehmen.

Wie das mit dem Logic Analyzer funktioniert weiß ich noch nicht. In die Thematik muss ich mich erst einarbeiten.

Der Grund für die Abfallende Flanke liegt in meinem Code begründet.
Es soll über die beiden Buttons ein Code eingegeben werden.

Solange S1 gedrückt ist kann über den S2 eine Zahl eingegeben werden. Beim Loslassen von S1 wird der Wert dann gespeichert. :)

Hier nun mein aktuell verwendeter Code:

Code: Alles auswählen

# Variablen
counter = 0
saved_counters = []
code = [2, 2, 2, 2]
last_press_S1 = 0 # Zum Entprellen
last_press_S2 = 0
threshold = 100  

# Interrupt fürs loslassen Button S1
def button1_interrupt(pin):
    global last_press_S1
    current_time = ticks_ms()
    if current_time - last_press_S1 > threshold:
        saved_counters.append(save_and_reset_counter())
        led.value(1)
        sleep_ms(50)
        led.value(0)
        print('Button 1 losgelassen')
        last_press_S1 = current_time

# Interrupt fürs drücken Button S2 
def button2_interrupt(pin):
    global counter, last_press_S2
    current_time = ticks_ms()
    if current_time - last_press_S2 > threshold:
        print('Button 2 gedrückt')
        if button_S1.value():
            counter += 1
        last_press_S2 = current_time

# Interrupt an Pins binden
button_S1.irq(trigger=Pin.IRQ_FALLING, handler=button1_interrupt)
button_S2.irq(trigger=Pin.IRQ_RISING, handler=button2_interrupt)

Re: Reaktionszeit bei Button eingaben?

Verfasst: Sonntag 30. April 2023, 19:05
von DoGro
Ach ich habe natürlich das Blinken der LED auch noch aus dem Interrupt rausgeholt, sonst hätte ich ja wieder eine sleep_ms in der Funktion.
So funktioniert der Code und das Drücken der Taster fast immer Tadellos. :P

Danke Danke.

Code: Alles auswählen

# Button-Pins definieren
button_S1 = Pin(16, Pin.IN, Pin.PULL_DOWN)
button_S2 = Pin(18, Pin.IN, Pin.PULL_DOWN)
led = Pin(17, Pin.OUT)

# Variablen
counter = 0
saved_counters = []
code = [2, 2, 2, 2]
last_press_S1 = 0 # Zum Entprellen verwende ich einen Reaktionsstopp, damit nicht in den Interrupts mit sleep_ms gearbeitet werden muss.
last_press_S2 = 0
threshold = 100  # Schwellenwert in Millisekunden der gewartet wird

# Interrupt fürs loslassen Button S1
def button1_interrupt(pin):
    global last_press_S1
    current_time = ticks_ms()  
    if current_time - last_press_S1 > threshold:
        reaktion_S1()
        last_press_S1 = current_time

        
# Button S1 Reaktionen
def reaktion_S1():
    print('Button 1 losgelassen')
    saved_counters.append(save_and_reset_counter())  # Ruft die Funktion zum Speichern der Button S2 Anzahl in der Liste saved_counters auf.
    led.value(1)
    sleep_ms(50)
    led.value(0)    
    

# Interrupt fürs drücken Button S2 
def button2_interrupt(pin):
    global counter, last_press_S2
    current_time = ticks_ms()
    if current_time - last_press_S2 > threshold:
        print('Button 2 gedrückt')
        if button_S1.value():
            counter += 1
        last_press_S2 = current_time

# Interrupt an Pins binden
button_S1.irq(trigger=Pin.IRQ_FALLING, handler=button1_interrupt)
button_S2.irq(trigger=Pin.IRQ_RISING, handler=button2_interrupt)

Re: Reaktionszeit bei Button eingaben?

Verfasst: Montag 1. Mai 2023, 21:02
von Dennis89
Hallo,

was heißt denn fast immer?

Ich weis ja nicht wie der Rest deine Codes aus sieht, aber man will eigentlich keine globalen Variablen in einem Programm haben. Wenn da noch mehr Code kommt, wird das alles sehr unübersichtlich.
Wenn man sich etwas merken will, dann nutzt man eine Klasse.

Das könnte dann so aussehen:

Code: Alles auswählen

from machine import Pin
from time import ticks_ms, ticks_diff, sleep


PIN_S1 = 16
PIN_S2 = 18


class ButtonCounter:
    def __init__(self, button_s1_pin, button_s2_pin, debounce_time=0.05):
        self.debounce_time = debounce_time
        self.button_s1 = Pin(button_s1_pin, Pin.IN, Pin.PULL_DOWN)
        button_s2 = Pin(button_s2_pin, Pin.IN, Pin.PULL_DOWN)
        button_s2.irq(handler=self.counting, trigger=Pin.IRQ_RAISING)
        self.timestamp = ticks_ms()
        self.counter = 0

    def counting(self, pin):
        if (
            ticks_diff(ticks_ms(), self.timestamp) >= self.debounce_time
            and self.button_s1.value()
        ):
            self.counter += 1
            self.timestamp = ticks_ms()


def main():
    button_counter = ButtonCounter(PIN_S1, PIN_S2)
    while True:
        print(button_counter.counter)
        sleep(0.5)


if __name__ == "__main__":
    main()
Grüße
Dennis

Re: Reaktionszeit bei Button eingaben?

Verfasst: Mittwoch 3. Mai 2023, 18:12
von DoGro
Ahh,
ok das mit der Klasse war meine erste Idee.

Damit tue ich mich noch etwas schwer. Ich danke dir, für deine Anregung.
Werde das erstmal verarbeiten müssen.

Viele Grüße