Digitale Eingänge am Mikrocontroller: Taster, Logikpegel, Pull-up/Pull-down und Entprellen

https://bildung.social/@oerinformatik/

https://oer-informatik.de/mcu-digitale-eingaenge

Mikrocontroller, digitaler Eingang, digitalRead, Taster, Logikpegel, Pull-up-Widerstand, Pull-down-Widerstand, INPUT_PULLUP, Öffner, Drahtbruch, Prellen, Entprellen

tl/dr; (ca. 31 min Lesezeit): Ein Taster am Eingang braucht mehr als zwei Drähte: Hier erfährst Du, ab welcher Spannung ein Eingang HIGH liest, warum ein offener Eingang einen Pull-up- oder Pull-down-Widerstand braucht, wie Du Pegel und Ströme an Taster-Widerstands-Netzwerken berechnest, wann ein Öffner sicherer ist als ein Schließer, wie Du viele Taster an wenige Pins bringst und wie Du prellende Kontakte in Hardware und Software entprellst. Für ESP32-C6, ESP32, ESP8266 (NodeMCU) und Arduino Uno [AI-Assisted]. (Zuletzt geändert am 10.11.2026)

Dieser Artikel ist Teil einer Artikelreihe über Mikrocontroller-Grundlagen: Erste Schritte / Digitale Ausgänge / Digitale Eingänge / Variablen und Datentypen / Pinbelegung der Boards

Schon fit in diesem Thema? Nutze die Kann-Liste und die Leitfragen unter dem Artikel als Checkliste, ob Du die relevanten Kompetenzen bereits hast.

Als Grundlagen digitaler Eingänge kann ich nach Durchlesen des Artikels…

  • … Logikpegel und Schaltschwellen eines Eingangs aus dem Datenblatt bestimmen und die Aufgabe eines Schmitt-Triggers erklären.

  • … Pull-up- und Pull-down-Widerstände im Stromlaufplan erkennen, benennen und erklären, warum sie bei offenem Kontakt einen definierten Pegel sicherstellen – auch an den Busleitungen SDA und SCL.

  • … Taster so mit Pull-up- oder Pull-down-Widerständen beschalten, dass bei Betätigung ein 0- oder 1-Signal entsteht, den Pegel bei betätigtem und unbetätigtem Taster bestimmen und mit digitalRead() einlesen.

  • … Spannungen und Ströme an Taster-Spannungsteiler-Schaltungen und Widerstands-Taster-Netzwerken für den betätigten und unbetätigten Zustand berechnen.

  • … interne Pull-up-Widerstände mit INPUT_PULLUP (beim ESP32 auch Pull-down-Widerstände mit INPUT_PULLDOWN) nutzen.

  • … Öffner und Schließer unterscheiden und beurteilen, wie sich ein Drahtbruch auswirkt.

  • … die Anschlusstechnik mehrerer Taster an einer Platine mit Steckverbinder beschreiben und eine Tasterabfrage über eine Tastenmatrix oder einen Portexpander skizzieren.

  • … das Prellen mechanischer Kontakte erklären und Entprellschaltungen mit RC-Glied und Schmitt-Trigger oder RS-Flipflop sowie einen entprellten Reset beschreiben, beurteilen und auf Fehler prüfen.

  • … Tastendrücke in Software entprellen und Flanken erkennen.

Ein Mikrocontroller muss wissen, was um ihn herum passiert: Hat jemand einen Taster gedrückt? Ist die Tür zu? Hat der Endschalter angesprochen? Das erfährt er über digitale Eingänge. Sie kennen wie die Ausgänge nur zwei Zustände, HIGH und LOW. Damit ein Eingang aber verlässlich den richtigen Zustand liest, braucht er eine passende Beschaltung – sonst meldet er Tastendrücke, die es nie gab, oder zählt einen Druck zehnmal.

Am Ende steht diese Schaltung auf dem Steckbrett: ein Taster mit externem Pull-down-Widerstand, der eine LED schaltet.

Steckbrett: Taster 2 zwischen 3,3 V und GPIO2 mit 10-kOhm-Pull-down-Widerstand gegen GND, LED 1 mit 220 Ohm an GPIO4 eines ESP32-C6 DevKit (mit KI erstellt)

Zum Üben gibt es eigene Übungsaufgaben zu digitalen Eingängen.

Dieser Artikel baut auf der Kann-Liste der Artikel Erste Schritte mit dem Mikrocontroller und Digitale Ausgänge auf.

Schritt 1: Logikpegel und Schaltschwellen

Ein Pin wird nach dem Reset als Eingang betrieben; ausdrücklich legst Du das mit pinMode(pin, INPUT); fest. digitalRead(pin) liefert dann HIGH oder LOW. Welche Spannung als welcher Pegel gilt, steht im Datenblatt als Input Low Voltage U_\mathrm{IL,max} und Input High Voltage U_\mathrm{IH,min}:

  • Bis U_\mathrm{IL,max} erkennt der Eingang sicher Low (0).
  • Ab U_\mathrm{IH,min} erkennt er sicher High (1).
  • Dazwischen liegt der verbotene Bereich: Der Eingang kann 0 oder 1 lesen, und seine Eingangsstufe zieht erhöhten Querstrom.
Schaltschwellen der digitalen Eingänge laut Datenblatt
Board Betriebsspannung U_\mathrm{B} U_\mathrm{IL,max} U_\mathrm{IH,min} 5 V am Eingang erlaubt?
ESP32-C6 3,3 V 0{,}25 \cdot U_\mathrm{B} \approx 0{,}83\ \mathrm{V} 0{,}75 \cdot U_\mathrm{B} \approx 2{,}48\ \mathrm{V} nein
ESP32 (DevKit V4) 3,3 V 0{,}25 \cdot U_\mathrm{B} \approx 0{,}83\ \mathrm{V} 0{,}75 \cdot U_\mathrm{B} \approx 2{,}48\ \mathrm{V} nein
ESP8266 (NodeMCU) 3,3 V 0{,}25 \cdot U_\mathrm{B} \approx 0{,}83\ \mathrm{V} 0{,}75 \cdot U_\mathrm{B} \approx 2{,}48\ \mathrm{V} nein
Arduino Uno (ATmega328P) 5 V 0{,}3 \cdot U_\mathrm{B} = 1{,}5\ \mathrm{V} 0{,}6 \cdot U_\mathrm{B} = 3{,}0\ \mathrm{V} ja

Die ESP-Boards sind nicht 5-V-tolerant: Ein Taster oder Sensor, der 5 V an einen Eingang legt, kann den Chip zerstören. Pull-up-Widerstände und Taster gehören dort an 3,3 V. Umgekehrt erkennt ein Uno die 3,3 V eines Sensors gerade noch als High (über 3,0 V), aber ohne Reserve; dafür gibt es Pegelwandler (Artikel Logikfamilien und Pegel).

Schmitt-Trigger: Ein Signal, das langsam ansteigt oder verrauscht ist, bleibt lange im verbotenen Bereich. Ein Eingang mit nur einer Schaltschwelle würde dort mehrmals hin- und herkippen. Ein Schmitt-Trigger hat zwei Schwellen: Er schaltet beim Ansteigen erst bei der oberen Schwelle U_\mathrm{T+} auf High und beim Fallen erst bei der unteren Schwelle U_\mathrm{T-} zurück. Der Abstand der beiden Schwellen heißt Hysterese; kleine Schwankungen darunter ändern den Ausgang nicht. Die Port-Eingänge des ATmega328P haben einen solchen Schmitt-Trigger eingebaut, für die Entprellung in Schritt 7 nimmt man einen eigenen Baustein (z. B. 74HC14). Wie Schmitt-Trigger arbeiten, zeigt der Artikel Komparator und Schmitt-Trigger.

Ein CMOS-Eingang ist sehr hochohmig: Sein Eingangsleckstrom liegt im Bereich von höchstens etwa 1 µA. Daraus folgt das wichtigste Problem dieses Artikels: Ein offener Eingang – etwa ein Taster ohne weitere Beschaltung, der gerade nicht gedrückt ist – hat gar keinen festen Pegel. Er „floatet“: Die Leitung wirkt wie eine Antenne, schon das Feld einer Hand oder ein Netzkabel in der Nähe schaltet ihn zufällig zwischen 0 und 1, und eine Ladung, die beim letzten Tastendruck auf die Leitung kam, bleibt eine Weile stehen.

Schritt 2: Pull-up- und Pull-down-Widerstände

Damit der Eingang bei offenem Kontakt einen definierten Pegel hat, zieht ein Widerstand ihn auf ein festes Potenzial:

  • Ein Pull-up-Widerstand liegt zwischen Eingang und Versorgungsspannung. Der Taster schaltet den Eingang gegen Masse. Unbetätigt liest der Controller High, betätigt Low – das Signal ist low-aktiv.
  • Ein Pull-down-Widerstand liegt zwischen Eingang und Masse. Der Taster schaltet den Eingang gegen die Versorgungsspannung. Unbetätigt liest der Controller Low, betätigt High – das Signal ist high-aktiv.
Links: Pull-up-Widerstand R1 von U_B zum Eingang E, Taster S1 vom Eingang gegen Masse; rechts: Taster S2 von U_B zum Eingang E, Pull-down-Widerstand R2 vom Eingang gegen Masse; jeweils Eingangsspannung U_E (mit KI erstellt)
Pegel am Eingang bei Pull-up- und Pull-down-Beschaltung
Beschaltung Taster unbetätigt Taster betätigt aktiver Pegel
Pull-up, Taster gegen GND U_\mathrm{E} = U_\mathrm{B} → 1 U_\mathrm{E} = 0\ \mathrm{V} → 0 low-aktiv
Pull-down, Taster gegen U_\mathrm{B} U_\mathrm{E} = 0\ \mathrm{V} → 0 U_\mathrm{E} = U_\mathrm{B} → 1 high-aktiv

Den Eingang direkt mit U_\mathrm{B} zu verbinden, geht nicht: Beim Drücken des Tasters entstünde ein Kurzschluss. Der Widerstand begrenzt den Strom.

Warum liegt bei offenem Taster die volle Spannung am Eingang? In den hochohmigen Eingang fließt praktisch kein Strom, also fällt am Pull-up-Widerstand keine Spannung ab: U_{R1} = R_1 \cdot I \approx 0. Mit einem Leckstrom von 1 µA fallen an 10 kΩ nur 10 mV ab – vernachlässigbar.

Wie groß wählst Du den Widerstand? Bei betätigtem Taster fließt der Querstrom I = U_\mathrm{B} : R, solange der Taster gedrückt ist. Ein kleiner Widerstand macht den Eingang störfest, kostet aber Strom; ein großer spart Strom, macht den Eingang aber empfindlich für Störungen und zusammen mit der Leitungskapazität langsam. Übliche Werte liegen zwischen 4,7 kΩ und 47 kΩ. Bei 3,3 V und 10 kΩ fließen 0,33 mA, bei 5 V 0,5 mA.

Pull-ups an SDA und SCL: Beim I²C-Bus treiben alle Teilnehmer die beiden Leitungen nur aktiv auf Low (Ausgänge mit offenem Drain bzw. Kollektor). Den High-Pegel stellen allein zwei Pull-up-Widerstände her, typisch 4,7 kΩ bei 100 kHz, kleiner bei höherer Taktrate oder vielen Teilnehmern. So entsteht kein Kurzschluss, wenn zwei Teilnehmer gleichzeitig senden, und jeder Teilnehmer kann die Leitung auf Low halten. Fehlen die Pull-ups, bleibt der Bus stumm. Viele Sensor-Breakouts bringen die Widerstände schon mit. Mehr dazu im Artikel I²C-Bus.

Praktischer Aufbau mit Pull-down: Taster 2 liegt zwischen 3,3 V (Uno: 5 V) und dem Eingang BUTTON2_PIN, ein 10-kΩ-Widerstand zieht den Eingang auf GND. LED 1 zeigt an, ob der Taster gedrückt ist. Taster 2 ist hier bewusst anders beschaltet als in der Standard-Pinbelegung der Reihe (dort sind alle Taster low-aktiv); deshalb steht im Programm pinMode(BUTTON2_PIN, INPUT); ohne internen Widerstand.

Steckbrett: Taster 2 zwischen 3,3 V und GPIO2 mit 10-kOhm-Pull-down-Widerstand gegen GND, LED 1 mit 220 Ohm an GPIO4 eines ESP32-C6 DevKit (mit KI erstellt)

Die Fritzing-Datei zum Nachbauen: mcu-digitale-eingaenge-pulldown-steckbrett-esp32c6.fzz

Das Programm fragt den Eingang in jedem Durchlauf von loop() ab (Polling) und schaltet LED 1 entsprechend:

Taster 2 liegt zwischen 3,3 V (Pin „3V3“) und GPIO2, der Pull-down-Widerstand (10 kΩ) zwischen GPIO2 und GND. LED 1 hängt mit 220 Ω an GPIO4. Unbetätigt liest GPIO2 0 V (LOW), betätigt 3,3 V (HIGH).

//-------------------------------------------------------------------------------------
// Liste der Ein- und Ausgabeelemente
// Board: ESP32-C6 Dev Kit N8-M
//-------------------------------------------------------------------------------------
// Datentyp | Name der Variable   | Anschlusspin      | Name, Verhalten
const int     BUTTON2_PIN         = 2;                // Button 2, active LOW, INPUT_PULLUP
const int     LED1_PIN            = 4;                // LED 1, active HIGH (strapping pin, ok as output)

// Taster 2 ist in diesem Beispiel bewusst anders beschaltet als in der Liste:
// Taster gegen 3,3 V (Uno: 5 V), externer Pull-down 10 kOhm gegen GND -> active HIGH

void setup() {
  pinMode(BUTTON2_PIN, INPUT);        // ohne internen Widerstand, der Pull-down ist extern
  pinMode(LED1_PIN, OUTPUT);
}

void loop() {
  if (digitalRead(BUTTON2_PIN) == HIGH) {   // betätigt: HIGH (high-aktiv)
    digitalWrite(LED1_PIN, HIGH);           // LED 1 an
  } else {
    digitalWrite(LED1_PIN, LOW);            // LED 1 aus
  }
}

Die Listen der Ein- und Ausgabeelemente für weitere Boards (ESP32 Dev Kit V1/V2, WeMos-Board mit OLED) stehen im Artikel Pinbelegung der Mikrocontroller-Boards.

Schritt 3: Interne Pull-up- und Pull-down-Widerstände

Die meisten Controller haben zuschaltbare Widerstände eingebaut. Du aktivierst sie mit pinMode():

pinMode(pin, INPUT);           // kein interner Widerstand: externer Pull-up oder Pull-down nötig
pinMode(pin, INPUT_PULLUP);    // interner Pull-up (alle vier Boards)
pinMode(pin, INPUT_PULLDOWN);  // interner Pull-down (nur ESP32-C6 und ESP32)
Interne Widerstände der Boards
Board interner Pull-up interner Pull-down Hinweise
ESP32-C6 an allen GPIO an allen GPIO Richtwert einige 10 kΩ
ESP32 (DevKit V4) ja, außer GPIO34–39 ja, außer GPIO34–39 GPIO34–39 sind reine Eingänge ohne interne Widerstände
ESP8266 (NodeMCU) ja, außer D0 (GPIO16) nur D0 mit INPUT_PULLDOWN_16 INPUT_PULLDOWN gibt es nicht (Übersetzungsfehler); D3, D4, D8 sind Boot-Pins
Arduino Uno an allen Pins, 20–50 kΩ keiner INPUT_PULLDOWN gibt es nicht (Übersetzungsfehler)

Weil alle Boards einen internen Pull-up haben, schließt die Reihe alle Taster gegen GND an und nutzt INPUT_PULLUP – so läuft dasselbe Programm überall. Gedrückt heißt dann LOW. Den Aufbau mit Taster 1 und LED 1 kennst Du aus dem Artikel Erste Schritte; außer dem Taster brauchst Du kein Bauteil.

Taster 1 liegt zwischen GPIO1 und GND, ein Widerstand ist nicht nötig. LED 1 hängt mit 220 Ω an GPIO4. Der ESP32-C6 hat an jedem GPIO einen zuschaltbaren Pull-up und Pull-down.

//-------------------------------------------------------------------------------------
// Liste der Ein- und Ausgabeelemente
// Board: ESP32-C6 Dev Kit N8-M
//-------------------------------------------------------------------------------------
// Datentyp | Name der Variable   | Anschlusspin      | Name, Verhalten
const int     BUTTON1_PIN         = 1;                // Button 1, active LOW, INPUT_PULLUP
const int     LED1_PIN            = 4;                // LED 1, active HIGH (strapping pin, ok as output)

void setup() {
  pinMode(BUTTON1_PIN, INPUT_PULLUP); // interner Pull-up: unbetätigt HIGH
  pinMode(LED1_PIN, OUTPUT);
}

void loop() {
  bool pressed = (digitalRead(BUTTON1_PIN) == LOW);   // betätigt: LOW (low-aktiv)
  digitalWrite(LED1_PIN, pressed ? HIGH : LOW);       // LED 1 leuchtet, solange Taster 1 gedrückt ist
}

Die Listen der Ein- und Ausgabeelemente für weitere Boards (ESP32 Dev Kit V1/V2, WeMos-Board mit OLED) stehen im Artikel Pinbelegung der Mikrocontroller-Boards.

Die internen Widerstände sind recht hochohmig. Für lange Leitungen zu einem Bedienfeld oder in störender Umgebung (Motoren, Relais) ist ein externer, niederohmigerer Widerstand besser, z. B. 4,7 kΩ.

Schritt 4: Spannungen an Taster-Widerstands-Netzwerken berechnen

In echten Schaltungen liegt oft noch ein Widerstand in Reihe zum Taster: als Schutzwiderstand, der den Strom begrenzt, falls der Pin versehentlich als Ausgang auf High steht, oder als Teil eines RC-Glieds (Schritt 7). Dann ist der Eingang bei betätigtem Taster nicht mehr genau 0 V, sondern Pull-up und Schutzwiderstand bilden einen Spannungsteiler.

Beispiel (Uno): Pull-up R_1 = 4{,}7\ \mathrm{k\Omega} an U_\mathrm{B} = 5\ \mathrm{V}, Taster mit Schutzwiderstand R_\mathrm{S} = 330\ \mathrm{\Omega} gegen Masse.

\def\arraystretch{2.3} \begin{array}{rcl|l} U_\mathrm{E} & = & U_\mathrm{B} \cdot \frac{R_\mathrm{S}}{R_1 + R_\mathrm{S}} & \\ U_\mathrm{E} & = & 5\ \mathrm{V} \cdot \frac{330\ \mathrm{\Omega}}{4\,700\ \mathrm{\Omega} + 330\ \mathrm{\Omega}} & \\ U_\mathrm{E} & \approx & 0{,}328\ \mathrm{V} & \end{array}

0{,}328\ \mathrm{V} liegt deutlich unter U_\mathrm{IL,max} = 1{,}5\ \mathrm{V}: Der Controller liest sicher Low. Der Schutzwiderstand darf also nicht zu groß werden – sonst landet U_\mathrm{E} im verbotenen Bereich. Bei 3,3 V ist die Grenze enger (U_\mathrm{IL,max} \approx 0{,}83\ \mathrm{V}), rechne deshalb mit der Schwelle Deines Boards. Wie Spannungsteiler berechnet werden, zeigt der Artikel Spannungsteiler.

Mehrere Taster an einem Analogeingang: Mit verschiedenen Widerständen in Reihe zu den Tastern lassen sich mehrere Taster über eine Leitung abfragen. Jeder Taster erzeugt mit dem gemeinsamen Pull-up eine eigene Spannung U_\mathrm{ADC} = U_\mathrm{B} \cdot \frac{R_n}{R_\mathrm{PU} + R_n}:

Widerstands-Taster-Netzwerk an einem Analogeingang: Pull-up 10 kOhm von 5 V zum Eingang ADC; Taster S1 direkt gegen Masse, Taster S2 über 2,2 kOhm, Taster S3 über 4,7 kOhm gegen Masse (mit KI erstellt)
Spannungen am Analogeingang je betätigtem Taster (R_\mathrm{PU} = 10\ \mathrm{k\Omega}, U_\mathrm{B} = 5\ \mathrm{V})
betätigt Widerstand gegen Masse R_n U_\mathrm{ADC}
kein Taster unendlich 5,00 V
S1 0 Ω 0 V
S2 2,2 kΩ 0,902 V
S3 4,7 kΩ 1,60 V

Werden zwei Taster gleichzeitig gedrückt, liegen ihre Widerstände parallel; die Spannung wird kleiner als die des Tasters mit dem kleineren Widerstand, und meist erkennt das Programm nur diesen Taster. Wie das Programm die gemessene Spannung mit analogRead() einem Taster zuordnet, zeigt der Artikel Analoge Eingänge.

Schritt 5: Öffner, Schließer und der Drahtbruch

Taster und Schalter gibt es mit zwei Arten von Kontakten:

  • Der Schließer (normally open, NO) ist in Ruhe offen und schließt beim Betätigen. Die meisten Taster in Mikrocontroller-Projekten sind Schließer.
  • Der Öffner (normally closed, NC) ist in Ruhe geschlossen und öffnet beim Betätigen.
Taster, ausgeführt als Schließer (normally open)
Taster, ausgeführt als Öffner (normally closed)

Mit Pull-up und Kontakt gegen GND liest der Controller beim Schließer unbetätigt HIGH und betätigt LOW; beim Öffner ist es genau umgekehrt. Im Programm musst Du die Abfrage deshalb an die Kontaktart anpassen.

Spannend wird der Unterschied, wenn die Leitung zum Taster bricht oder ein Stecker abfällt. Mit Pull-up liest der Eingang dann dauerhaft HIGH:

Verhalten von Schließer und Öffner bei Drahtbruch
Kontakt (Pull-up, gegen GND) unbetätigt betätigt bei Drahtbruch Wirkung des Drahtbruchs
Schließer HIGH LOW HIGH sieht aus wie „nicht betätigt“ – der Fehler bleibt unbemerkt
Öffner LOW HIGH HIGH sieht aus wie „betätigt“ – das Gerät geht in den sicheren Zustand

Ein Beispiel aus der Werkstatt der CSB-Rad GmbH: Beim Lastenrad meldet ein Bremsschalter der Motorsteuerung, dass gebremst wird; dann muss der Motor sofort abschalten. Wäre der Bremsschalter ein Schließer, bliebe ein abgerissenes Kabel unbemerkt – der Motor würde beim Bremsen weiterschieben. Als Öffner meldet der Kabelbruch „Bremse betätigt“, der Motor bleibt aus, und der Fehler fällt sofort auf. Deshalb nimmt man für alles, was ausschalten oder stoppen soll (Not-Halt, Endschalter, Bremse), einen Öffner: Er ist drahtbruchsicher. Für Funktionen, die nur etwas einschalten, genügt der Schließer.

Eine Abfrage für einen Öffner an BUTTON1_PIN mit internem Pull-up sieht so aus:

// Öffner gegen GND: unbetätigt LOW, betätigt oder Drahtbruch HIGH
if (digitalRead(BUTTON1_PIN) == HIGH) {
  motorAus();                        // sicherer Zustand
}

Es gibt auch Taster mit beiden Kontakten (Wechsler). Steht an einem Taster mit mehr als zwei Anschlüssen nicht NO oder NC, findest Du mit dem Durchgangsprüfer heraus, welche Anschlüsse in Ruhe verbunden sind.

Wechselschalter mit NO- und NC-Kontakt

Schritt 6: Mehrere Taster anschließen

Bedienelemente sitzen oft auf einer eigenen Platine (Frontplatte, Tastenfeld), die über einen Steckverbinder mit der Controllerplatine verbunden ist. Je nach Zahl der Taster und der freien Pins gibt es vier Lösungen:

Anschlusstechniken für mehrere Taster
Anschlusstechnik Leitungen für n Taster Vorteile Nachteile
je Taster ein Eingang, gemeinsame Masse n + 1 einfach, gleichzeitiges Drücken erkennbar viele Pins und Adern
Tastenmatrix (Zeilen × Spalten) z + s (z. B. 4 × 4 = 16 Taster an 8 Leitungen) wenige Leitungen für viele Taster Programm muss Zeilen nacheinander abfragen; Entkoppeldioden bei Mehrfachbetätigung
Widerstandsnetzwerk am Analogeingang 3 (Signal, U_\mathrm{B}, GND) sehr wenige Leitungen Toleranzen, Mehrfachbetätigung kaum erkennbar
Portexpander oder Schieberegister 4 bis 5 (z. B. U_\mathrm{B}, GND, SDA, SCL) viele Taster an wenigen Pins, erweiterbar zusätzlicher Baustein, Abfrage über Bus

Am Steckverbinder fasst Du gleichartige Anschlüsse zusammen: Alle Taster bekommen eine gemeinsame Masseleitung, die Pull-up-Widerstände sitzen auf der Controllerplatine (dort, wo der Eingang ist) oder sind intern zugeschaltet. Bei langen Leitungen helfen kleine Kondensatoren gegen Störungen (Schritt 7). Reicht die Polzahl des Steckverbinders nicht, weichst Du auf eine Matrix oder einen Portexpander aus.

Tastenmatrix: Die Taster sitzen an den Kreuzungen von Zeilen- und Spaltenleitungen. Das Programm schaltet nacheinander je eine Zeile als Ausgang auf LOW, alle anderen bleiben hochohmig; die Spalten sind Eingänge mit Pull-up. Liest eine Spalte LOW, ist der Taster an der Kreuzung von aktiver Zeile und dieser Spalte gedrückt. Drückt jemand drei Taster in einem Rechteck, entstehen Geisterkontakte; Dioden in Reihe zu jedem Taster verhindern das.

Tasterabfrage über einen Portexpander: Ein I²C-Portexpander (z. B. PCF8574 mit acht Anschlüssen P0 … P7) hat schwache interne Pull-ups. Die Taster schalten seine Anschlüsse gegen Masse; der Controller liest über den Bus ein Byte, in dem jedes Bit für einen Taster steht. Liest er z. B. 1111\,1011_2, ist der Taster an P2 betätigt (low-aktiv). Viele Expander melden eine Änderung über einen Interrupt-Ausgang (INT), sodass der Controller nicht ständig abfragen muss. Ein zweiter Expander am selben Bus braucht eine andere Adresse: Seine Adresseingänge (A0 … A2) werden anders auf U_\mathrm{B} oder Masse gelegt. Alternativ schiebt ein Parallel-Seriell-Schieberegister (z. B. 74HC165) die Tasterzustände in den Controller. Wie Du einzelne Bits aus dem gelesenen Byte herausfilterst, zeigt der Artikel Register und Bitoperationen.

Willst Du eine Schaltung um einen weiteren Taster erweitern, gehst Du immer gleich vor: freien Pin (oder Expander-Anschluss) suchen, Sonderfunktionen des Pins prüfen (Boot-Pins, reine Eingänge), Beschaltung (Pull-up) ergänzen, Stromlaufplan und Liste der Ein- und Ausgabeelemente nachführen und die Software anpassen.

Schritt 7: Prellen und Entprellen in Hardware

Ein mechanischer Kontakt schließt nicht sauber. Beim Betätigen federn die Kontaktflächen zurück, öffnen und schließen mehrmals, bis sie nach etwa 1 … 10 ms (bei schlechten Kontakten auch länger) ruhig aufliegen. Dieses Prellen sieht der Controller als Folge kurzer Impulse. Ein Programm, das Tastendrücke zählt, zählt dann statt einem Druck mehrere.

Signalverläufe beim Betätigen eines Tasters mit Pull-up: oben das prellende Signal am Taster mit mehreren kurzen Impulsen in den ersten Millisekunden, Mitte die Spannung am Kondensator eines RC-Glieds mit oberer und unterer Schaltschwelle, unten der saubere Ausgang des Schmitt-Triggers mit einer einzigen Flanke (mit KI erstellt)

Es gibt drei Wege zum Entprellen, zwei davon in Hardware:

1. RC-Glied mit Schmitt-Trigger: Ein Kondensator am Eingang glättet die Impulse. Beim Betätigen entlädt der Taster den Kondensator über einen kleinen Widerstand R_2 schnell; die kurzen Unterbrechungen reichen nicht, um ihn über R_1 wieder nennenswert zu laden. Beim Loslassen lädt sich der Kondensator über R_1 + R_2 langsam auf. Ein Schmitt-Trigger (z. B. Inverter 74HC14) wandelt die langsam steigende Kondensatorspannung in eine steile Flanke um. Ein normales Gatter ohne Hysterese würde im Übergangsbereich mehrfach schalten oder sogar schwingen.

Die Zeitkonstante muss größer als die Prellzeit sein. Beispiel: R_1 = 47\ \mathrm{k\Omega}, R_2 = 1\ \mathrm{k\Omega}, C = 220\ \mathrm{nF}, U_\mathrm{B} = 5\ \mathrm{V} und obere Schaltschwelle U_\mathrm{T+} = 2{,}9\ \mathrm{V}. Nach dem Loslassen dauert es

\def\arraystretch{2.3} \begin{array}{rcl|l} t & = & (R_1 + R_2) \cdot C \cdot \ln\frac{U_\mathrm{B}}{U_\mathrm{B} - U_\mathrm{T+}} & \\ t & = & 48\ \mathrm{k\Omega} \cdot 220\ \mathrm{nF} \cdot \ln\frac{5\ \mathrm{V}}{2{,}1\ \mathrm{V}} & \\ t & \approx & 10{,}56\ \mathrm{ms} \cdot 0{,}8675 \approx 9{,}16\ \mathrm{ms} & \end{array}

bis der Schmitt-Trigger umschaltet – lang genug für einen Taster mit wenigen Millisekunden Prellzeit, kurz genug, dass niemand die Verzögerung merkt. Das Laden eines Kondensators erklärt der Artikel Kondensator und Spule: Schaltvorgänge.

2. RS-Flipflop mit Wechsler: Ein Taster mit Umschaltkontakt (Wechsler) setzt ein RS-Flipflop aus zwei NAND-Gattern über den einen Kontakt und setzt es über den anderen zurück; beide Eingänge haben Pull-up-Widerstände. Beim ersten Berühren des einen Kontakts kippt das Flipflop. Die folgenden Prellimpulse öffnen den Kontakt nur kurz – der Eingang geht dann auf High, und das ist bei NAND-Flipflops der Zustand „Speichern“. Der Wechsler prellt nie zurück bis zum anderen Kontakt, deshalb bleibt der Ausgang stabil. Diese Lösung entprellt ohne Verzögerung, braucht aber einen Wechsler und zwei Leitungen; mit einem einfachen Schließer funktioniert sie nicht. Mehr zu Flipflops im Artikel Flipflops.

Links: Entprellung mit RC-Glied, Pull-up R1, Taster S1 gegen Masse, Entladewiderstand R2, Kondensator C1 und Schmitt-Trigger-Inverter K1; rechts: Wechsler S2 an zwei NAND-Gattern K2 und K3, die als RS-Flipflop geschaltet sind, mit Pull-up-Widerständen R3 und R4 (mit KI erstellt)

Entprellter Reset: Ein Reset-Taster muss in Hardware entprellt werden, denn während des Resets läuft kein Programm. Die Reset-Beschaltung mit Pull-up-Widerstand (z. B. 10 kΩ) und Kondensator (z. B. 100 nF) gegen Masse ist selbst ein RC-Glied: Der Taster entlädt den Kondensator über einen kleinen Schutzwiderstand, nach dem Loslassen lädt er sich langsam auf und hält den Reset-Eingang einige Millisekunden auf Low. Der Reset-Eingang vieler Controller hat einen Schmitt-Trigger. Für einen sauberen Impuls fester Mindestlänge gibt es Reset-Bausteine (supervisor). Mehr zur Reset-Beschaltung zeigt der Artikel Aufbau eines Mikrocontrollers.

Typische Fehler in Entprellschaltungen: Gatter ohne Schmitt-Trigger-Eingang hinter dem RC-Glied; Zeitkonstante kleiner als die Prellzeit; fehlender Widerstand R_2, sodass der Kontakt den Kondensator schlagartig entlädt (hoher Spitzenstrom, Kontaktabbrand); RS-Flipflop mit Schließer statt Wechsler oder ohne Pull-up-Widerstände; Kondensator so groß, dass kurze Tastendrücke verloren gehen.

Schritt 8: Entprellen in Software und Flanken erkennen

Heute ist der dritte Weg der Normalfall: Das Programm entprellt selbst. Es kostet kein Bauteil. Hardware-Entprellung brauchst Du nur, wenn das Signal direkt einen Interrupt- oder Zählereingang ansteuert oder wenn (wie beim Reset) kein Programm läuft.

Zwei Ideen stecken in der Software-Lösung:

  • Flankenerkennung: Meist interessiert nicht, ob der Taster gedrückt ist, sondern dass er gerade gedrückt wurde. Das Programm merkt sich den letzten Pegel und reagiert nur, wenn sich der Pegel ändert. Mit Pull-up ist der Wechsel von HIGH nach LOW die fallende Flanke (Taster gedrückt), der Wechsel von LOW nach HIGH die steigende Flanke (Taster losgelassen).
  • Wartezeit: Nach einer erkannten Änderung wartet das Programm, bis das Prellen vorbei ist (z. B. 20 ms), und liest dann erneut. Erst wenn der neue Pegel noch anliegt, gilt die Änderung.

Das folgende Programm schaltet LED 1 bei jedem Druck auf Taster 1 um und zählt die Drücke im seriellen Monitor mit:

Taster 1 an GPIO1 gegen GND, LED 1 an GPIO4 – derselbe Aufbau wie im vorigen Schritt. Für die Ausgabe im seriellen Monitor muss beim C6 unter „Werkzeuge“ die Option „USB CDC On Boot“ zur benutzten USB-Buchse passen.

//-------------------------------------------------------------------------------------
// Liste der Ein- und Ausgabeelemente
// Board: ESP32-C6 Dev Kit N8-M
//-------------------------------------------------------------------------------------
// Datentyp | Name der Variable   | Anschlusspin      | Name, Verhalten
const int     BUTTON1_PIN         = 1;                // Button 1, active LOW, INPUT_PULLUP
const int     LED1_PIN            = 4;                // LED 1, active HIGH (strapping pin, ok as output)

const unsigned long DEBOUNCE_MS = 20;   // Wartezeit zum Entprellen in ms

int lastState = HIGH;                   // letzter gültiger Pegel (unbetätigt: HIGH)
bool ledOn = false;                     // Zustand von LED 1
int pressCount = 0;                     // Zahl der Tastendrücke

void setup() {
  Serial.begin(115200);
  pinMode(BUTTON1_PIN, INPUT_PULLUP);
  pinMode(LED1_PIN, OUTPUT);
}

void loop() {
  int state = digitalRead(BUTTON1_PIN);
  if (state != lastState) {             // Pegel hat sich geändert: Flanke
    delay(DEBOUNCE_MS);                 // Prellen abwarten ...
    state = digitalRead(BUTTON1_PIN);   // ... und erneut lesen
    if (state != lastState) {           // Änderung ist stabil
      lastState = state;
      if (state == LOW) {               // fallende Flanke: Taster wurde gedrückt
        pressCount++;
        ledOn = !ledOn;                 // LED 1 umschalten
        digitalWrite(LED1_PIN, ledOn ? HIGH : LOW);
        Serial.print("Tastendruck Nr. ");
        Serial.println(pressCount);
      }
    }
  }
}

Die Listen der Ein- und Ausgabeelemente für weitere Boards (ESP32 Dev Kit V1/V2, WeMos-Board mit OLED) stehen im Artikel Pinbelegung der Mikrocontroller-Boards.

Ohne Flankenerkennung würde die LED bei gedrücktem Taster tausendfach pro Sekunde umschalten; ohne Wartezeit würde sie beim Prellen mehrmals umschalten und je nach Zahl der Prellimpulse an oder aus bleiben. Probiere es aus: Setze DEBOUNCE_MS auf 0 und drücke mehrmals – bei vielen Tastern zählt der serielle Monitor dann mehr Drücke, als Du gemacht hast.

delay() hat einen Nachteil: Während der 20 ms tut der Controller nichts anderes. Bei vielen Tastern oder zeitkritischen Aufgaben merkt sich das Programm deshalb nur den Zeitpunkt der letzten Änderung und vergleicht ihn mit der aktuellen Zeit von millis(). Wie das geht, zeigt der Artikel Zeit ohne delay(): millis(). Soll der Controller auf einen Tastendruck sofort reagieren, ohne ständig abzufragen, hilft ein Interrupt: Interrupts.

Unterschiede der Boards

Digitale Eingänge auf den vier Boards
Thema ESP32-C6 ESP32 (DevKit V4) ESP8266 (NodeMCU) Arduino Uno
Pegel am Eingang 3,3 V, nicht 5-V-tolerant 3,3 V, nicht 5-V-tolerant 3,3 V, nicht 5-V-tolerant 5 V
Schwellen Low / High 0,83 V / 2,48 V 0,83 V / 2,48 V 0,83 V / 2,48 V 1,5 V / 3,0 V
INPUT_PULLUP alle GPIO alle außer GPIO34–39 alle außer D0 alle Pins
INPUT_PULLDOWN alle GPIO alle außer GPIO34–39 nur D0 (INPUT_PULLDOWN_16) –
Taster 1 / Taster 2 GPIO1 / GPIO2 GPIO32 / GPIO33 D3 (FLASH-Taster) / D5 2 / 3
Vorsicht bei Strapping-Pins GPIO4/5/8/9/15 Strapping-Pins GPIO0/2/5/12/15 Boot-Pins D3, D4, D8 Pins 0/1 (serieller Monitor)

Boot- und Strapping-Pins liest der Controller beim Start ein. Ein Taster oder Pull-down daran kann verhindern, dass das Board normal startet. Die Pinbelegung der Reihe meidet sie für Taster; Details stehen im Artikel Pinbelegung der Mikrocontroller-Boards.

Unter der Haube: Was macht digitalRead()?

digitalRead() liest am Ende nur ein Bit aus einem Eingangsregister: Beim Uno ist es das Bit eines Ports im Register PINB, PINC oder PIND. pinMode(pin, INPUT_PULLUP) löscht das Richtungsbit im Register DDRx und setzt das Bit im Register PORTx – bei einem Eingang schaltet dieses Bit den internen Pull-up zu. Die ESP-Controller haben für jeden Pin eigene Konfigurationsbits für Pull-up und Pull-down. Wie Du Eingänge direkt über Register liest und einzelne Bits maskierst, zeigt der Vertiefungsartikel Register und Bitoperationen.

Wie geht es weiter?

Taster sind digital, viele Sensoren liefern aber eine Spannung: Weiter geht es mit Variablen und Datentypen und analogen Eingängen. Nicht blockierendes Entprellen lernst Du bei millis(). Zum Üben gibt es die Übungsaufgaben zu digitalen Eingängen.

Leitfragen

  1. Ab welcher Spannung liest ein Eingang sicher High, und was passiert dazwischen?

Das Datenblatt nennt U_\mathrm{IH,min} (ab hier sicher High) und U_\mathrm{IL,max} (bis hier sicher Low), bei den ESP-Boards 0,75 bzw. 0,25 der Betriebsspannung, beim Uno 0,6 bzw. 0,3. Dazwischen liegt der verbotene Bereich: Der gelesene Wert ist zufällig, und die Eingangsstufe zieht Querstrom. siehe Abschnitt „Schritt 1“

  1. Wozu dient ein Schmitt-Trigger?

Er hat zwei Schaltschwellen (Hysterese) und macht aus einem langsam ansteigenden oder verrauschten Signal eine einzige steile Flanke. Ein Gatter mit nur einer Schwelle würde im Übergangsbereich mehrfach kippen. siehe Abschnitt „Schritt 1“

  1. Warum braucht ein Taster am Eingang einen Pull-up- oder Pull-down-Widerstand?

Ein CMOS-Eingang ist sehr hochohmig. Bei offenem Kontakt hätte er keinen festen Pegel und würde durch Störungen zufällig zwischen 0 und 1 wechseln. Der Widerstand zieht ihn auf ein festes Potenzial; weil kaum Strom fließt, fällt an ihm keine nennenswerte Spannung ab. Beim Drücken begrenzt er den Strom. siehe Abschnitt „Schritt 2“

  1. Welchen Pegel liest der Controller bei Pull-up- und bei Pull-down-Beschaltung?

Pull-up mit Taster gegen Masse: unbetätigt High, betätigt Low (low-aktiv). Pull-down mit Taster gegen U_\mathrm{B}: unbetätigt Low, betätigt High (high-aktiv). siehe Abschnitt „Schritt 2“

  1. Wozu dienen die Pull-up-Widerstände an SDA und SCL?

Die I²C-Teilnehmer ziehen die Leitungen nur aktiv auf Low (offener Drain bzw. Kollektor). Den High-Pegel erzeugen allein die Pull-up-Widerstände. So gibt es keinen Kurzschluss, wenn mehrere Teilnehmer gleichzeitig treiben. siehe Abschnitt „Schritt 2“

  1. Welche internen Widerstände bieten die Boards, und wie schaltest Du sie ein?

Mit pinMode(pin, INPUT_PULLUP) den internen Pull-up (alle vier Boards, beim ESP32 nicht an GPIO34–39, beim NodeMCU nicht an D0), mit INPUT_PULLDOWN den internen Pull-down (nur ESP32-C6 und ESP32). Der Uno hat keinen Pull-down. siehe Abschnitt „Schritt 3“

  1. Wie berechnest Du die Eingangsspannung, wenn ein Widerstand in Reihe zum Taster liegt?

Pull-up und Reihenwiderstand bilden bei betätigtem Taster einen Spannungsteiler: U_\mathrm{E} = U_\mathrm{B} \cdot R_\mathrm{S} : (R_1 + R_\mathrm{S}). Das Ergebnis vergleichst Du mit U_\mathrm{IL,max} bzw. U_\mathrm{IH,min} des Boards. siehe Abschnitt „Schritt 4“

  1. Warum nimmt man für Not-Halt, Endschalter und Bremse einen Öffner?

Bei einem Drahtbruch liest der Eingang mit Pull-up dauerhaft High. Beim Öffner bedeutet das „betätigt“: Das Gerät geht in den sicheren Zustand, und der Fehler fällt auf. Beim Schließer sähe der Drahtbruch wie „nicht betätigt“ aus und bliebe unbemerkt. siehe Abschnitt „Schritt 5“

  1. Welche Möglichkeiten gibt es, viele Taster mit wenigen Leitungen anzuschließen?

Tastenmatrix (Zeilen und Spalten), Widerstandsnetzwerk an einem Analogeingang, Portexpander am I²C-Bus oder Schieberegister. Am Steckverbinder werden gleichartige Anschlüsse wie die Masse zusammengefasst. siehe Abschnitt „Schritt 6“

  1. Was ist Prellen, und wie entprellst Du in Hardware und in Software?

Mechanische Kontakte öffnen und schließen beim Betätigen mehrmals, bevor sie ruhig aufliegen. In Hardware glättet ein RC-Glied die Impulse und ein Schmitt-Trigger macht daraus eine Flanke (Zeitkonstante größer als die Prellzeit), oder ein RS-Flipflop mit Wechsler speichert den ersten Kontakt. In Software erkennt das Programm die Flanke, wartet die Prellzeit ab und liest erneut. siehe Abschnitt „Schritt 7“ und Abschnitt „Schritt 8“


Hinweis zur Nachnutzung als Open Educational Resource (OER)

Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “Digitale Eingänge am Mikrocontroller: Taster, Logikpegel, Pull-up/Pull-down und Entprellen” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/mcu-digitale-eingaenge veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/mcu/arduino-esp. Erstellt mit KI-Assistenz; von mir umfassend redaktionell überarbeitet, geprüft und freigegeben. Stand: 10.11.2026.

[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]

Kommentare gerne per Mastodon, Verbesserungsvorschläge per gitlab issue (siehe oben). Beitrag teilen: