← Alle MakerNEWS

ESP32

ESP32 und Taster für Anfänger: Anschließen, auslesen und entprellen

Herr Brinke 13 Minuten Lesezeit Aktualisiert: 29/08/2026
sahand babali owjrvbyXYyc unsplash scaled

Ein Taster gehört zu den einfachsten Bauteilen, die an einen ESP32 angeschlossen werden können.

Und trotzdem kann man damit bereits eine Menge lernen.

Zum Beispiel:

  • digitale Eingänge
  • HIGH und LOW
  • digitalRead()
  • INPUT_PULLUP
  • Bedingungen mit if
  • Zustandsänderungen
  • Tasterprellen
  • kurzes und langes Drücken

In diesem Beitrag schauen wir uns den Taster am ESP32 Schritt für Schritt an.

Ganz einfach erklärt und ohne unnötige Fachbegriffe.


Was ist ein Taster?

Ein Taster ist zunächst nichts anderes als ein kleiner Schalter.

Allerdings gibt es einen wichtigen Unterschied.

Ein Schalter bleibt normalerweise in seiner Position.

Zum Beispiel:

Licht an → Schalter bleibt an

Ein Taster springt dagegen nach dem Loslassen wieder zurück.

Ein typisches Beispiel ist eine Türklingel:

drücken → Klingel

loslassen → Klingel aus

Genau dieses Prinzip können wir mit dem ESP32 erkennen.


Wie funktioniert ein Taster elektrisch?

Ein einfacher Taster besitzt zwei Zustände.

Nicht gedrückt

Die elektrische Verbindung ist unterbrochen.

──────    ──────

Gedrückt

Die Kontakte werden miteinander verbunden.

──────────────

Der ESP32 kann diese beiden Zustände erkennen.

Damit haben wir einen klassischen digitalen Eingang.


Warum besitzt mein Taster vier Beine?

Viele kleine Taster für Breadboards besitzen vier Anschlüsse.

Das wirkt zunächst merkwürdig.

Schließlich brauchen wir eigentlich nur zwei Kontakte.

Der Grund ist einfach:

Jeweils zwei Anschlüsse sind intern bereits miteinander verbunden.

Vereinfacht sieht das so aus:

1 ───── 2

    │
 TASTER
    │

3 ───── 4

Beim Drücken werden die beiden Seiten miteinander verbunden.

Die vier Beine sorgen außerdem dafür, dass der Taster stabil auf einer Platine oder einem Breadboard sitzt.


Taster auf dem Breadboard

Beim Einsetzen eines vierbeinigen Tasters sollte darauf geachtet werden, dass er richtig auf dem Breadboard sitzt.

Besonders praktisch ist es, ihn über die mittlere Trennung des Breadboards zu setzen.

Dadurch befinden sich die beiden Seiten des Tasters auf getrennten Kontaktreihen.


Wie schließen wir den Taster an?

Für unser erstes Beispiel benötigen wir:

  • ESP32
  • Breadboard
  • Taster
  • zwei Jumper-Kabel

Wir verwenden beispielsweise:

GPIO 21

Eine Seite des Tasters verbinden wir mit:

GPIO 21

Die andere Seite mit:

GND

Vereinfacht:

ESP32

GPIO 21
   │
   │
 TASTER
   │
   │
  GND

Das ist schon die komplette Schaltung.

Es fehlt kein Widerstand.

Warum?

Das schauen wir uns jetzt an.


Das Problem mit einem offenen Eingang

Stellen wir uns zunächst vor, wir würden einfach schreiben:

pinMode(21, INPUT);

Wenn der Taster gedrückt wird, ist GPIO 21 mit GND verbunden.

Der ESP32 erkennt einen eindeutigen Zustand.

Aber was passiert, wenn der Taster nicht gedrückt wird?

Dann ist der GPIO mit nichts verbunden.

Er hängt gewissermaßen:

in der Luft.

Ein solcher Eingang wird als:

Floating Input

bezeichnet.

Der ESP32 könnte dann zufällige Zustände erkennen.

Zum Beispiel:

HIGH
LOW
HIGH
HIGH
LOW
LOW
HIGH

obwohl niemand den Taster berührt.

Das ist natürlich nicht besonders hilfreich.


Pull-up-Widerstand einfach erklärt

Wir benötigen deshalb einen definierten Zustand.

Dafür gibt es einen sogenannten:

Pull-up-Widerstand

Dieser zieht den Eingang vereinfacht gesagt auf HIGH, solange nichts anderes passiert.

Das Praktische:

Der ESP32 besitzt solche Widerstände bereits eingebaut.

Wir müssen also keinen zusätzlichen Widerstand auf das Breadboard stecken.

Stattdessen schreiben wir:

pinMode(21, INPUT_PULLUP);

Damit aktivieren wir den internen Pull-up-Widerstand.


Was bedeutet INPUT_PULLUP?

Zerlegen wir den Begriff.

INPUT

bedeutet:

Eingang

und:

PULLUP

bedeutet vereinfacht:

Ziehe den Eingang auf HIGH.

Solange der Taster nicht gedrückt wird, erkennt der ESP32 deshalb:

HIGH

Warum ist gedrückt plötzlich LOW?

Jetzt kommt etwas, das am Anfang häufig verwirrt.

Unsere Schaltung sieht so aus:

GPIO 21
   │
 TASTER
   │
  GND

Der interne Pull-up-Widerstand sorgt normalerweise für:

HIGH

Drücken wir den Taster, verbinden wir GPIO 21 direkt mit:

GND

Dadurch erkennt der ESP32:

LOW

Deshalb gilt bei unserer Schaltung:

Taster nicht gedrückt = HIGH

Taster gedrückt = LOW

Das sollte man sich merken.

INPUT_PULLUP + Taster gegen GND

nicht gedrückt → HIGH

gedrückt → LOW

Diese Art der Beschaltung ist bei Mikrocontrollern sehr verbreitet.


Unser erstes Taster-Programm

Jetzt wollen wir herausfinden, ob der ESP32 den Taster erkennt.

#define BUTTON_PIN 21

void setup() {

  Serial.begin(115200);

  pinMode(BUTTON_PIN, INPUT_PULLUP);

}

void loop() {

  int buttonState = digitalRead(BUTTON_PIN);

  Serial.println(buttonState);

  delay(100);

}

Das Programm ist bereits ausreichend.


Was macht digitalRead()?

Diese Zeile ist besonders wichtig:

digitalRead(BUTTON_PIN);

digitalRead() bedeutet:

digitalen Zustand lesen

Der ESP32 schaut also nach:

Ist dieser Eingang HIGH oder LOW?

Das Ergebnis speichern wir:

int buttonState = digitalRead(BUTTON_PIN);

in der Variable:

buttonState

Das Ergebnis im Serial Monitor

Mit:

Serial.println(buttonState);

geben wir den Zustand aus.

Ohne gedrückten Taster sehen wir beispielsweise:

1
1
1
1
1
1

Jetzt drücken wir den Taster:

0
0
0
0
0
0

Wir lassen ihn los:

1
1
1
1
1

Dabei gilt:

HIGH = 1

LOW = 0

Also:

1 = nicht gedrückt

0 = gedrückt

Unser Taster funktioniert.


Statt 0 und 1 lieber verständlichen Text anzeigen

Die Zahlen funktionieren.

Aber wir können es besser machen.

Unser ESP32 soll direkt schreiben:

Taster gedrückt

oder:

Taster nicht gedrückt

Dafür benötigen wir eine Entscheidung.


if einfach erklärt

if bedeutet:

wenn

Wir schreiben:

if (buttonState == LOW) {

  Serial.println("Taster gedrueckt");

}

Das lässt sich fast wie ein normaler Satz lesen:

WENN der Zustand des Tasters LOW ist, DANN schreibe „Taster gedrückt“.


Was bedeutet ==?

Hier lauert ein klassischer Anfängerfehler.

Wir schreiben:

buttonState == LOW

mit zwei Gleichheitszeichen.

Das bedeutet:

vergleichen

Der ESP32 fragt:

Ist buttonState gleich LOW?

Ein einzelnes:

=

hat eine andere Bedeutung.

Damit wird ein Wert gespeichert.

Also:

=   Wert zuweisen

==  Werte vergleichen

else: Was passiert ansonsten?

Jetzt ergänzen wir:

else

else bedeutet:

ansonsten

Unser Programm:

#define BUTTON_PIN 21

void setup() {

  Serial.begin(115200);

  pinMode(BUTTON_PIN, INPUT_PULLUP);

}

void loop() {

  int buttonState = digitalRead(BUTTON_PIN);

  if (buttonState == LOW) {

    Serial.println("Taster gedrueckt");

  }
  else {

    Serial.println("Taster nicht gedrueckt");

  }

  delay(100);

}

Jetzt zeigt der Serial Monitor:

Taster nicht gedrueckt
Taster nicht gedrueckt
Taster nicht gedrueckt
Taster gedrueckt
Taster gedrueckt
Taster gedrueckt
Taster nicht gedrueckt

Damit können wir bereits auf den Taster reagieren.


Eine LED mit dem Taster steuern

Jetzt kombinieren wir Eingang und Ausgang.

Wir verwenden:

GPIO 21 → Taster

und beispielsweise:

GPIO 18 → LED

Unser Ziel:

Taster gedrückt

↓

LED an

Taster losgelassen:

Taster losgelassen

↓

LED aus

Das Programm

#define BUTTON_PIN 21
#define LED_PIN 18

void setup() {

  pinMode(BUTTON_PIN, INPUT_PULLUP);

  pinMode(LED_PIN, OUTPUT);

}

void loop() {

  int buttonState = digitalRead(BUTTON_PIN);

  if (buttonState == LOW) {

    digitalWrite(LED_PIN, HIGH);

  }
  else {

    digitalWrite(LED_PIN, LOW);

  }

}

Jetzt haben wir eine vollständige kleine Steuerung:

TASTER
   ↓
digitalRead()
   ↓
ESP32
   ↓
if()
   ↓
digitalWrite()
   ↓
 LED

Das ist bereits das Grundprinzip sehr vieler Mikrocontroller-Projekte.


Aber jetzt kommt ein neues Problem

Bisher fragen wir ständig:

Ist der Taster gerade gedrückt?

Manchmal möchten wir aber etwas anderes wissen:

Wurde der Taster gerade eben gedrückt?

Das klingt ähnlich.

Für ein Programm ist es aber ein großer Unterschied.


Zustand oder Ereignis?

Angenommen, wir möchten bei jedem Tastendruck einen Zähler erhöhen.

Wir schreiben:

if (buttonState == LOW) {

  zaehler++;

}

Jetzt drücken wir den Taster für eine halbe Sekunde.

Was passiert?

Vielleicht erwarten wir:

1

Tatsächlich könnte der ESP32 aber zählen:

1
2
3
4
5
6
7
8
9
...

Warum?

Der ESP32 arbeitet loop() extrem schnell ab.

Solange der Taster gedrückt bleibt, lautet die Antwort immer wieder:

LOW

Unser Programm zählt deshalb immer weiter.


Wir müssen den Tastendruck erkennen

Wir möchten nicht wissen:

Ist der Taster gedrückt?

Sondern:

Hat sich der Zustand gerade von nicht gedrückt auf gedrückt verändert?

Wir müssen uns deshalb den vorherigen Zustand merken.

Zum Beispiel:

int lastButtonState = HIGH;

Jetzt können wir vergleichen:

vorher HIGH

und:

jetzt LOW

Das bedeutet:

Der Taster wurde gerade gedrückt.


Einen einzelnen Tastendruck erkennen

#define BUTTON_PIN 21

int lastButtonState = HIGH;

void setup() {

  Serial.begin(115200);

  pinMode(BUTTON_PIN, INPUT_PULLUP);

}

void loop() {

  int buttonState = digitalRead(BUTTON_PIN);

  if (lastButtonState == HIGH && buttonState == LOW) {

    Serial.println("Taster wurde gedrueckt!");

  }

  lastButtonState = buttonState;

}

Jetzt interessiert uns nicht mehr nur der aktuelle Zustand.

Wir vergleichen:

VORHER

mit

JETZT

Was bedeutet &&?

Im Programm steht:

lastButtonState == HIGH && buttonState == LOW

Die beiden Zeichen:

&&

bedeuten:

UND

Unser Programm fragt:

War der Taster vorher HIGH UND ist er jetzt LOW?

Wenn beide Bedingungen stimmen, wurde der Taster gerade gedrückt.


Was ist eine Flanke?

Für diese Zustandsänderung gibt es einen Fachbegriff:

Flanke

Keine Sorge, das Prinzip ist einfach.

Wir betrachten eine Veränderung:

HIGH → LOW

oder:

LOW → HIGH

Bei unserer INPUT_PULLUP-Schaltung bedeutet:

HIGH → LOW

Taster wurde gedrückt

und:

LOW → HIGH

Taster wurde losgelassen

Damit können wir zwischen:

Taster halten

und:

Taster neu drücken

unterscheiden.


LED mit jedem Tastendruck umschalten

Jetzt können wir etwas Interessanteres bauen.

Unser Ziel:

einmal drücken → LED an

noch einmal drücken → LED aus

noch einmal drücken → LED an

Der Taster funktioniert also ähnlich wie ein Lichtschalter.

Dafür müssen wir uns zusätzlich merken, ob die LED gerade an oder aus ist.


Zustand der LED speichern

Dafür verwenden wir:

bool ledState = false;

bool kann zwei Zustände speichern:

true

oder

false

Wir verwenden:

false = LED aus

true = LED an

Das Programm

#define BUTTON_PIN 21
#define LED_PIN 18

int lastButtonState = HIGH;

bool ledState = false;

void setup() {

  pinMode(BUTTON_PIN, INPUT_PULLUP);

  pinMode(LED_PIN, OUTPUT);

}

void loop() {

  int buttonState = digitalRead(BUTTON_PIN);

  if (lastButtonState == HIGH && buttonState == LOW) {

    ledState = !ledState;

    digitalWrite(LED_PIN, ledState);

  }

  lastButtonState = buttonState;

}

Jetzt schaltet jeder Tastendruck die LED um.


Was bedeutet !ledState?

Diese Zeile sieht zunächst merkwürdig aus:

ledState = !ledState;

Das Ausrufezeichen bedeutet hier vereinfacht:

Gegenteil

Ist:

ledState = false

wird daraus:

true

Ist:

ledState = true

wird daraus:

false

Also:

AUS → AN

AN → AUS

AUS → AN

Perfekt für unseren Taster.


Und trotzdem kann etwas Merkwürdiges passieren

Man drückt den Taster einmal.

Eigentlich sollte die LED:

einmal umschalten

Aber manchmal passiert:

AN

AUS

AN

obwohl der Taster nur einmal gedrückt wurde.

Ist der ESP32 kaputt?

Nein.

Der Taster macht tatsächlich etwas, das wir nicht sehen können.


Was ist Tasterprellen?

Ein echter mechanischer Taster schließt seinen Kontakt nicht immer sofort sauber.

Beim Drücken können die Metallkontakte für wenige Millisekunden hin und her springen.

Vereinfacht erwarten wir:

HIGH
HIGH
HIGH
LOW
LOW
LOW
LOW

In Wirklichkeit könnte das Signal kurz so aussehen:

HIGH
HIGH
LOW
HIGH
LOW
HIGH
LOW
LOW
LOW

Der Taster „prellt“.

Für uns Menschen passiert das extrem schnell.

Der ESP32 ist aber ebenfalls extrem schnell.

Er kann diese kurzen Zustandsänderungen erkennen.

Dadurch denkt unser Programm möglicherweise:

Taster gedrückt!

Taster gedrückt!

Taster gedrückt!

obwohl wir nur einmal gedrückt haben.


Taster entprellen

Dieses Problem nennt man:

Tasterprellen

Die Lösung heißt:

Entprellen

oder auf Englisch:

Debouncing

Auch Newbiely behandelt das Entprellen als eigenes Thema, weil es besonders bei der Erkennung einzelner Tastendrücke wichtig wird.


Die einfache Lösung: kurz warten

Für erste Experimente findet man häufig diese Lösung:

delay(50);

Nach einem erkannten Tastendruck wartet das Programm beispielsweise 50 Millisekunden.

Das kann bei einfachen Versuchen funktionieren.

Allerdings hat delay() einen Nachteil:

Während dieser Zeit macht der ESP32 nichts anderes.

Bei einer kleinen Übung ist das oft egal.

Bei größeren Projekten kann das problematisch werden.


Warum delay() später stören kann

Stellen wir uns vor, der ESP32 soll gleichzeitig:

  • einen Taster prüfen
  • Temperatur messen
  • ein Display aktualisieren
  • WLAN-Daten empfangen
  • einen Motor steuern

Wenn das Programm ständig mit delay() wartet, werden auch die anderen Aufgaben ausgebremst.

Deshalb wird bei größeren Projekten häufig mit Zeitmessungen gearbeitet, ohne das gesamte Programm anzuhalten.

Dafür gibt es beispielsweise:

millis()

Das ist aber bereits ein Thema für einen späteren Beitrag.

Für den Einstieg reicht zunächst:

Taster können prellen und müssen bei Anwendungen mit einzelnen Tastendrücken gegebenenfalls entprellt werden.


Kurzes und langes Drücken erkennen

Jetzt kennen wir bereits:

Taster nicht gedrückt

Taster gedrückt

Taster wurde gerade gedrückt

Taster wurde losgelassen

Damit können wir noch einen Schritt weitergehen.

Wir können messen:

Wie lange wurde der Taster gedrückt?

Zum Beispiel:

kurz drücken

→ LED einschalten

und:

lange drücken

→ LED ausschalten

Dafür merken wir uns beim Drücken die aktuelle Zeit.

Beim Loslassen prüfen wir:

Wie viel Zeit ist vergangen?

Auch hierfür eignet sich:

millis()

Damit lassen sich später unterschiedliche Bedienfunktionen mit nur einem einzigen Taster realisieren.


Was kann man mit einem Taster alles machen?

Ein einzelner Taster kann erstaunlich viele Funktionen übernehmen.

Zum Beispiel:

Aktion auslösen

Taster drücken
→ Summer ertönt

Zustand umschalten

Taster drücken
→ LED an

erneut drücken
→ LED aus

Zähler erhöhen

Taster drücken
→ +1

Programm starten

Taster drücken
→ Ablauf beginnt

Zwischen Betriebsarten wechseln

Taster drücken
→ Modus 1

erneut drücken
→ Modus 2

Kurzes und langes Drücken

kurz
→ Funktion A

lang
→ Funktion B

Damit ist der einfache Taster eines der vielseitigsten Eingabebauteile überhaupt.


Typische Fehler beim Taster

Wenn der Taster nicht funktioniert, lohnt sich ein Blick auf einige typische Fehler.

Taster falsch auf dem Breadboard

Bei vierbeinigen Tastern sind jeweils zwei Pins bereits miteinander verbunden.

Ist der Taster falsch eingesetzt, kann die Schaltung dauerhaft verbunden sein.


GND fehlt

Bei unserer INPUT_PULLUP-Schaltung muss der Taster den Eingang beim Drücken mit GND verbinden.


INPUT statt INPUT_PULLUP

Bei:

pinMode(BUTTON_PIN, INPUT);

fehlt bei unserer einfachen Schaltung der definierte Zustand.

Wir verwenden deshalb:

pinMode(BUTTON_PIN, INPUT_PULLUP);

HIGH und LOW verwechselt

Bei unserer Schaltung gilt:

nicht gedrückt = HIGH

gedrückt = LOW

Taster löst mehrfach aus

Mögliche Ursache:

Tasterprellen

Dann muss der Tastendruck entprellt werden.


Programm reagiert ständig

Wird nur geprüft:

if (buttonState == LOW)

läuft die Aktion ständig weiter, solange der Taster gehalten wird.

Soll eine Aktion nur einmal pro Tastendruck ausgeführt werden, muss die Zustandsänderung erkannt werden.


Die wichtigsten Taster-Befehle

Für einfache Tasterprojekte reichen bereits wenige Befehle.

Taster vorbereiten:

pinMode(BUTTON_PIN, INPUT_PULLUP);

Taster lesen:

digitalRead(BUTTON_PIN);

Zustand prüfen:

if (buttonState == LOW)

Zustandsänderung erkennen:

if (lastButtonState == HIGH && buttonState == LOW)

Damit können bereits viele Taster-Projekte umgesetzt werden.


Das Wichtigste in 60 Sekunden

Ein Taster ist ein digitaler Eingang.

Eine einfache ESP32-Schaltung besteht aus:

GPIO
 │
Taster
 │
GND

Mit:

pinMode(BUTTON_PIN, INPUT_PULLUP);

verwenden wir den internen Pull-up-Widerstand des ESP32.

Deshalb gilt:

nicht gedrückt = HIGH

gedrückt = LOW

Mit:

digitalRead(BUTTON_PIN);

lesen wir den Zustand.

Mit:

if (buttonState == LOW)

können wir darauf reagieren.

Soll eine Aktion nur einmal pro Tastendruck ausgeführt werden, müssen wir die Zustandsänderung erkennen:

HIGH → LOW

Und wenn ein Tastendruck scheinbar mehrfach erkannt wird, kann das am:

Tasterprellen

liegen.

Dann benötigen wir eine Entprellung.

Damit sind bereits die wichtigsten Grundlagen für Taster am ESP32 verstanden.


Wie geht es weiter?

Nachdem wir einen digitalen Eingang ausführlich kennengelernt haben, schauen wir uns als Nächstes die andere Seite genauer an:

ESP32 und LEDs

Dabei geht es unter anderem um:

  • LED richtig anschließen
  • Anode und Kathode
  • Vorwiderstand berechnen
  • LED ein- und ausschalten
  • mehrere LEDs steuern
  • Ampelschaltung
  • LED blinken lassen
  • unterschiedliche Blinkgeschwindigkeiten
  • warum delay() irgendwann problematisch wird
  • millis() statt delay()
  • LED dimmen
  • PWM einfach erklärt

Damit lernen wir digitale Ausgänge deutlich genauer kennen.


Alle Beiträge dieser Serie

Add your first comment to this post