Taster

ESP | Taster im Griff Abfragen, Flankenerkennung, Entprellen


Ein Taster hat immer zwei Zustände: gedrückt oder nicht gedrückt. Dieser Wert kann abgefragt werden und je nach Zustand kann dann bspw. eine LED angeschaltet oder ausgeschaltet werden. In diesem Abschnitt lernst du die eltronische Beschaltung eines Tasters kennen und kannst den Zustand des Tasters auslesen. Des Weiteren lernst du wie man einen Taster entprellt und den Zustand speichert.

Der Zustand eines Tasters

Taster am Pin 17 und Poti am Pin 2
Abb. 1 Taster am Pin 17 und Poti am Pin 2.
Taster

Mit einem Taster (s. Abb. 1) kann man bspw. ein Licht anschalten. Je nach Tastendruck und elektronischer Schaltung liegt an dem angeschlossenen Pin entweder 0 V (pull-down) oder 3,3 V (pull-up). Dieser Zustand kann mit Hilfe einer Entscheidung ausgewertet werden.

from machine import Pin
import time

button = Pin(17, mode=Pin.IN, pull=Pin.PULL_DOWN)
led = Pin(27, Pin.OUT)

while True:
    if button.value() == 1:
        led.on()
    else:
        led.off()

Man beachte, dass der Wert des Tasters entweder eine logische 0 oder 1 ist. So kann ganz einfach der Zustand des Tasters bestimmt werden.

Die Schaltung
Beschaltung eines Tasters mit Pull-Up-Widerstand
Abb. 2 Beschaltung eines Tasters mit Pull-Up-Widerstand.

Für die logische Auswertung des Tasters in Abb. 2 ist es von Bedeutung, dass der Wert am Mikrocontrollerpin 17 entweder 0 V oder 3,3 V ist. Es darf keinen schwebenden Zustand, sprich der Wert liegt dazwischen oder ist unbestimmt, geben. Die Schaltung in Abb. 2 garantiert genau dies. Der sogenannte Pull-Down-Widerstand zieht die Spannung bei unbetätigtem Taster am Mikrocontrollerpin nach auf 0 V hoch. Wird der Taster gedrückt liegen 3,3 V am Pin an.

Man beachte, dass beim Tausch von Taster und Pull-Up-Widerstand die Spannung nach oben auf 3,3 V gezogen wird und wir dann von einem Pull-Up-Widerstand sprechen. In diesem Fall liegt beim Betätigen des Tasters, wie in unserem Fall, eine logische 0 am Controllerpin.

Der Schutzwiderstand sorgt dafür, das bei versehentlicher Programmierung des Pins als Ausgang kein Kurzschluss entsteht.

Arbeitsauftrag 1 detecting a button press

Taster

  1. Erstelle den Ordner 02-Button
  2. Erstelle die Datei button.py und gib den passenden Code ein, so dass bei Tastendruck die LED angeht.
  3. Lass den Zustand des Tasters am Monitor ausgeben.
  4. Lass bei Tastendruck einen Sound abspielen

Für Fortgeschrittene Zustand merken

  1. Nutze den Poti als digitalen Eingang und finde heraus, bei welcher Position der Schaltzustand sich ändert.
  2. Kannst Du den Taster auch so programmieren, dass das Licht angeht wenn du einmal den Taster drückst und beim nächsten Mal wieder aus?

Die Betätigung eines Tasters merken

Skispuren im Tiefschnee
Abb. 3 Skispuren im Tiefschnee.
Spuren im Schnee

Der Schnee merkt sich jeden Skifahrer. Nicht so ein Taster: Betätigen wir ihn, ändert er seinen Zustand. Doch lassen wir ihn wieder los, sieht es so aus, als wäre er nie betätigt worden.

Taster kommen sehr häufig in Steuerungen zum Einsatz. Gegenüber einem Schalter haben sie zwei Vorteile. Erstens haben sie immer die identische Endposition und sie vermitteln beim Betätigen ein angenehmes taktiles Gefühl.

Im nächsten Schritt wollen wir den Taster dazu bringen, dass er sich wie der Schnee etwas merkt. Dazu verwenden wir Flags und States verwenden.

Flags und States sind Variablen. Flags sind immer einfache Variablen vom Datentyp Bolean. States sind Variablen die auch mehr Werte speichern können.

from machine import Pin
import time

button = Pin(17, mode=Pin.IN, pull=Pin.PULL_DOWN)
led = Pin(27, mode=Pin.OUT)

# States
ledState = False
lastState = 0
currentState = 0

while True:
    currentState = button.value()
    
    # Zustand hat sich geändert
    if currentState != lastState:
        # Nur reagieren, bei betätigtem Taster
        if currentState == 1:
            # LED umschalten
            ledState = not ledState
            led.value(ledState)
        
        lastState = currentState

Wir verwenden drei States: ledState zum Umschalten der LED, currentState zum Speichern des aktuellen Tasterzustandes und lastState zum Speichern des letzten Tasterzustandes. Nur so können wir das Betätigen des Tasters eindeutig festhalten. Dies ist in diesem Fall die steigende Flanke von 0 auf 1.

Zuerst erfassen wir die Flanke, sprich wenn der Taster betätigt oder losgelassen wird: if currentState != lastState. Im zweiten Schritt erfassen wir, ob der Taster gedrückt wurde: if currentState == 1. Dann toggeln wir den Zustand der LED: ledState = not ledState und weisen der LED den neuen Wert zu: led.value(ledState).

Am Ende darf man nicht vergessen den lastState = currentState zu setzen, da sonst die Flanken beim Betätigen oder Loslassen des Tasters nicht mehr erkannt werden.

Das Prellen eines Tasters

Das landende Flugzeug

Ein Flugzeug landet unsanft auf der Landebahn. Der Pilot setzt mehrfach auf. Es ist als ob das Flugzeug hin- und herschwingt.

Die Kontaktfedern eines Taster können sowohl beim Betätigen als auch beim Loslassen nachschwingen, so dass es ungewollt zu mehrfachen Kontakten des Tasters kommt. Diese Eigenschaft nennt man das Prellen eines Tasters.

Um das unerwünschte Prellverhalten loszuwerden, da hierdurch bei einer Betätgigung des Tasters womöglich mehrere Kontakte gezählt werden, entprellt man den Taster. Dies ist entweder durch eine elektronische Schaltung möglich oder wie in unserem Fall durch eine softwaretechnische Lösung.

Abb. 4 Bounce-Landeanflug.

Das Prellverhalten

Zeitablaufdiagramm bei nicht entprelltem Taster
Abb. 5 Zeitablaufdiagramm bei nicht entprelltem Taster.

Abb. 5 zeigt das Zeitablaufdiagramm eines prellenden Tasters. Das Prellen tritt sowohl beim Drücken als auch beim Loslassen des Tasters auf. Darüber hinaus ist es auch möglich, dass durch Störungen der Zustand geändert wird.

Hardwaretechnisch Entprellen kann man, in dem man einen Kondensator parallel zum Pull-Down- oder Pull-Up-Widerstand schaltet. Dadurch werden kurzzeitige Signalschwankungen heraus­ge­fil­tert. Eine Zustandsänderung tritt erst dann ein, wenn der Kondensator auf die Schaltschwelle des Mikrocontrollers ge- oder entladen ist.

Softwaretechnisch lässt sich das Entprellen durch eine Zeitverzögerung erreichen. Durch Auspro­bieren kann man herausfinden, wie lang die Zeit nach dem Drücken und Loslassen jeweils sein muss. Dann packt man noch eine Reserve obendrauf und man erhält eine einfache Lösung.

from machine import Pin
import time

button = Pin(17, mode=Pin.IN, pull=Pin.PULL_DOWN)
led = Pin(27, Pin.OUT)

while True:
    if button.value() == 1:        
        time.sleep_ms(20)  # Entprellen
		ledStatus = True

Arbeitsauftrag 2 reading and remembering the button state

Flankenerkennung

  1. Erstelle die Datei button-flag.py und binde Taster und LED ein.
  2. Programmiere den Taster so, dass er die steigende Flanke erkennt und den Zustand der LED mit jedem Tastendruck ändert.
  3. Entprelle zusätzlich den Taster
  4. Programmiere den Taster so, dass er bei fallender Flanke die LED umschaltet.
  5. Zähle wie oft der Taster prellt

Mehrfachbelegung eines Tasters für Fortgeschrittene

  1. Erstelle die Datei button-multiple-action.py und binde Taster und LED ein.
  2. Bei kurzzeitigem Betätigen soll die LED an und aus gehen.
  3. Bei längerem Betätigen (> 1 s) soll die LED anfangen zu blinken
  4. Bewerte welchen Nachteil längere Zeitverzögerungen in einem solchen Programm haben.

🎯 Arbeitsauftrag 3 Taster Smart Garden

Situationsbeschreibung

Du arbeitest daran deine Garten-LEDs mit einem Taster anzusteuern. Ziel ist, die Funktion des Tasters zu verstehen — Zustand abfragen, entprellen, Flankenerkennung — und daraus eine Schaltung/Programm zu bauen, bei der eine LED beim Tastendruck reagiert.

Pin-Belegung der Status-LED und des Buzzers
Abb. 5 Pin-Belegung der Status-LED und des Buzzers.

Folgender Beispiel-Code ist bereits vorhanden:

from machine import Pin
import time

button = Pin(99, mode=Pin.IN, pull=Pin.PULL_DOWN)
led = Pin(27, mode=Pin.OUT)

# States
ledState = False
currentState = False
lastState = False

while True:			
				
Auftragsbearbeitung

3.1 Du möchtest zuerst die Grundlagen überprüfen

3.1.1 Wähle aus, wie der Pin des Tasters konfiguriert werden muss, damit man seinen Zustand zuverlässig abfragen kann.
Wähle eine Antwort.

  1. Pin(99, mode=Pin.IN, pull=Pin.PULL_DOWN)
  2. Pin(99, mode=Pin.IN, pull=Pin.PULL_UP)
  3. Pin(17, mode=Pin.IN, pull=Pin.PULL_DOWN)
  4. Pin(17, mode=Pin.IN, pull=Pin.PULL_UP)


3.1.2 Nenne, was dafür sorgt, dass der Eingangspin keinen „undefinierten“ Zustand annimmt, wenn der Taster nicht gedrückt ist. Wähle eine Antwort aus.

  1. Ein Kondensator in Reihe zum Taster
  2. Ein Kondensator parallel zum Taster
  3. Ein Open-Drain-Pin
  4. Ein Pull-Down- bzw. Pull-Up-Widerstand



3.1.3 Wähle die korrekte Begründung wieso bei einem Pull-Up-Widerstand die Pin-Spannung beim offenen Taster 3,3 V beträgt. Wähle eine Antwort.

  1. Der Widerstand an 3,3 V zieht die Spannung hoch.
  2. Der Widerstand an 3,3 V zieht die Spannung runter.
  3. Der Widerstand an 0 V zieht die Spannung hoch.
  4. Der Widerstand an 0 V zieht die Spannung runter.


3.1.4 Wähle die korrekte Begründung wieso bei einem Pull-Down-Widerstand die Pin-Spannung beim betätigten Taster 3,3 V beträgt. Wähle eine Antwort.

  1. Der Taster an 3,3 V zieht die Spannung hoch.
  2. Der Taster an 3,3 V zieht die Spannung runter.
  3. Der Taster an 0 V zieht die Spannung hoch.
  4. Der Taster an 0 V zieht die Spannung runter.


3.2 Bevor du mit der eigentlichen Lösung des Problems beginnst, möchtest Du nochmal das Thema Flankenerkennung trainieren. Dein Kollege stellt dir hierzu zwei Fragen.

3.2.1 Was versteht man unter „Flankenerkennung“ bei einem Taster? Wähle eine Antwort.

  1. Ein Pull-Up-Widerstand wird automatisch erkannt
  2. Das Erkennen der Tasterbetätigung (Zustandwechsel)
  3. Das Erkennen, ob der Taster gerade betätigt oder unbetätigt ist
  4. Das Entprellen eines Taster mit mehr als 20 ms


3.2.2 Wieso benötigt man hierzu 2 State-Variablen state1 und state2? Wähle eine Antwort.

  1. zum Speichern des aktuellen und vorletzen Tasterzustandes
  2. zum Speichern des letzten und vorletzen Tasterzustandes
  3. zum Speichern des aktuellen und letzen Tasterzustandes
  4. es würde auch eine Variable ausreichen

3.3 Erstelle ein MicroPython-Programm für den ESP32, das folgendes tut:

  • Taster an Pin 17, LED an Pin 27 (oder passenden GPIO)
  • Der Taster soll entprellt werden (mindestens 15 ms Verzögerung nach Erkennung eines Tastendrucks)
  • Jedes Mal, wenn der Taster gedrückt wird (auf steigende Flanke), soll die LED ihren Zustand umschalten (an → aus, aus → an). Verwende dafür die Idee mit lastState und currentState (state change detection).

Optional (für Fortgeschrittene):

  • Ergänze das Programm mit einer Funktion, dass bei einem langen Tastendruck (> 1s) statt Umschalten der LED ein Summer/Buzzer ausgelöst wird.
  • Dokumentiere im Kommentar, warum Entprellen und Flankenerkennung wichtig sind.

Die Lösung sollte folgendermaßen aussehen:


while True:
    oled.fill(0)
    oled.text(f"Temperatur: {temperatur:.2f}", 0, 0) 
    oled.show()

	if temperatur >= 23:
		led.on()
		buzzer.toggle()
	else:
		led.off()
    
    sleep(0.0025)

Wichtige Begriffe zum Auswerten von Tastern



die Flanken­erkennung der Mikrocontroller wurde so programmiert, dass er eine fallende oder steigende Flanke beim Betätigen des Tasters erkennt
der State der Zustand oder Variable auf der ein Zustand gespeichert wird
das Flag eine Variable vom Datentyp boolean
ledState = not ledState toggeln eines Zustands, sprich der gespeicherte Wert wird invertiert RPulldown
if button.value() == 1 Abfrage zum Erkennen des Tastendrucks