Externe Taster am MCU-Board einlesen
https://oer-informatik.de/taster_einlesen_nodemcu
tl/dr; (ca. 7 min Lesezeit): Zur Bedienung des MCU-Projekts sind Taster unerlässlich. Aber warum sind sie manchmal gegen GND, manchmal gegen VCC geschaltet? Warum haben manche Widerstände, andere nicht? Hier geht es um Eingabe-Basics für Microcontroller und die Besonderheiten von ESP32 und ESP8266.
Viele Pins eines Microcontrollers haben als GPIO (general purpose input output) die Möglichkeit, ein HIGH
-Signal oder ein LOW
-Signal an einem Eingang zu erkennen. Es können daher Taster angeschlossen werden, die diese Pins mit HIGH
oder LOW
belegen.
Taster gegen V_{CC} (HIGH
)
Eine einfache Schaltung wäre, einen Taster zwischen den digitalen Eingang und der positiven Versorgungsspannung zu setzen. Ist der Taster betätigt, so liegt ein positives Potenzial am Eingang an - was als HIGH
interpretiert würde. Die positive Versorgungsspannung wird auf ICs oft mit V_{CC} ausgewiesen, bei den ESPs-basierten Boards entspricht sie 3,3V, bei anderen wie z.B. dem Arduino Uno liegt sie bei 5V.
3,3V liegen am digitalen Eingan an, wenn ich den Taster betätige - das ist trivial. Aber was passiert, wenn ich den Taster loslasse?

(Ich wähle hier für den digitalen Eingang beispielhaft GPIO13
- das ist z.B. D7
beim ESP8266. Das gilt natürlich entsprechend an allen digitalen Eingängen).
Wir erwarten nach dem Loslassen einen LOW
-Pegel am Pin GPIO13
. Aber muss das so sein? Es gibt zwei Effekte, die dafür sorgen können, dass ein offener Taster zu keinem definierten LOW
-Pegel führt.
Eine offene Leitung wirkt wie eine Antenne, die bei entsprechenden elektromagnetischen Feldern in der Umgebung (z.B. aus weiteren Schaltungskomponenten) Störsignale empfangen kann. Diese könnten ggf. als
HIGH
interpretiert werden.Ladungen, die nach betätigen des Tasters zu GPIO13 geflossen sind, haben ggf. kapazitive Schaltungskomponenten geladen. Diese Ladung bleibt zunächst nach öffnen des Schalters bestehen und entlädt sich erst mit Verzögerung.
Taster gegen GND (LOW
)
Wie sieht es bei einem Taster aus, der gegen GND verschaltet ist? Bei geschlossenem Taster ist es wieder trivial: es liegt das GND-Potenzial an (LOW
, 0V). Bei geöffnetem Taster?

Auch hier gelten wieder die Überlegungen zur Antennenwirkung. Aber eigentlich sollte das Potenzial bei geöffnetem Taster doch HIGH
sein, damit wir den offenen und den geschlossenen Zustand unterscheiden können. Wir benötigen also weitere Bauteile.
Pull-Up-Widerstand
Wir bleiben beim letzten Beispiel: Wenn der Taster gegen GND geöffnet ist liegt kein definiertes Potenzial am digitalen Eingang an, obwohl es ein HIGH
-Pegel sein sollte. Wir müssen dort also ein HIGH
anlegen. Das offene Ende direkt mit HIGH
zu verdrahten verbietet sich, da wir sonst einen Kurzschluss erzeugen, sobald der Taster betätigt ist. Wir müssen also einen Widerstand dazwischen schalten, der das Potenzial hoch zieht (“pull up”) gegen V_{CC}: ein Pull-Up-Widerstand R_{PU}. Dieser sollte groß genug sein, um die Ströme, die zwischen GND und V_{CC} bei betätigtem Taster fließen, zu begrenzen. Üblich sind Werte im Kiloohm-Bereich, etwa R_{PU} = 22\ k\Omega (was den Strom auf etwa 0,17mA begrenzt).

Somit wären beide Probleme gelöst: das undefinierte Potenzial bei offenem Taster wird auf V_{CC} gezogen, die Störungen durch Antennenwirkung sind damit auch eliminiert. Bei betätigtem Taster liegt trotzdem das Potenzial 0V (LOW
) an.
Beispielhaft mit einem NodeMCU auf ESP8266 auf dem Breadboard realisiert sähe eine solche Schaltung etwa so aus:

Wenn wir den Programmcode dafür schreiben müssen wir bedenken, dass das Potenzial des Pins LOW
ist, wenn der Taster betätigt wird. Der Code bei dem die interne LED leuchtet, wenn ein externer Taster mit Pullup an einen ESP8266 betätigt wird, sieht etwa so aus:
/* Liste der Ein- und Ausgabeelemente
Datentyp |Name | Anschlusspin | Name, Verhalten*/
const int ONBOARD_LED = D0; // GPIO016 LOW-Active
const int BUTTON = D7; // GPIO013, external pullup
void setup() {
pinMode(ONBOARD_LED, OUTPUT);
pinMode(BUTTON, INPUT);
}
void loop() {
bool buttonstate =digitalRead(BUTTON);
if (buttonstate==LOW){
digitalWrite(ONBOARD_LED, LOW); // switch LED on (LOW-active)
}else{
digitalWrite(ONBOARD_LED, HIGH); // switch LED off (LOW-active)
}
delay(100);
}
Lass Dich nicht in die Irre führen: die LED leuchtet wirklich, wenn der LED-Pin auf LOW
gesetzt wird. Das liegt an der internen Verschaltung auf dem Board.
Pull-Down-Widerstand
Die gleiche Überlegung können wir auch für den ersten Fall anwendenden: ein Taster gegen V_{CC}. Falls dieser Taster nicht betätigt ist, soll das Potenzial gesichert auf GND herunter gezogen werden (“pull down”). Hierzu dient ein Pull-Down-Widerstand R_{PD}, für den die gleichen Überlegungen gelten, wie für den Pull-Up-Widerstand. Auch hier begrenzt ein Widerstand im Kiloohmbereich (z.B. R_{PD} = 22\ k\Omega) den Strom.

Der Aufbau einer solchen Schaltung ist fast identisch - Der Widerstand wird jetzt gegen LOW
verdrahtet, der Taster gegen HIGH
.

Auch der Code gleicht dem vorigen fast - es wird lediglich das gegensätzliche Potenzial überprüft (if (buttonstate==HIGH)
):
/* Liste der Ein- und Ausgabeelemente
Datentyp |Name | Anschlusspin | Name, Verhalten*/
const int ONBOARD_LED = D0; // GPIO016 LOW-Active
const int BUTTON = D7; // GPIO013, external pulldown
void setup() {
pinMode(ONBOARD_LED, OUTPUT);
pinMode(BUTTON, INPUT);
}
void loop() {
bool buttonstate =digitalRead(BUTTON);
if (buttonstate==HIGH){
digitalWrite(ONBOARD_LED, LOW); // switch LED on (LOW-active)
}else{
digitalWrite(ONBOARD_LED, HIGH); // switch LED off (LOW-active)
}
delay(100);
}
Interne Pull-Up / Pull-Down-Widerstände
In der Praxis werden diese externen Pull-Up bzw. Pull-Down-Widerstände selten benötigt. Die meisten Microcontroller bieten intern die Möglichkeit, Widerstände per Software zuzuschalten. Für den Arduino Uno und den ESP8266 können Pull-Up-Widerstände zugeschaltet werden, der ESP32 bietet sowohl Pull-Up als auch Pull-Down-Widerstände:
Arduino Uno ATMega 328P |
ESP8266 | ESP32 | |
---|---|---|---|
Pull-Up-Widerstand an Pin | A0-A5 D1-D13 20-50k\Omega |
D1-D8 D9-D10 (USB) |
GPIO 0,2,4,5, GPIO 12-23, 25-27, GPIO 32,33 45 k\Omega |
Pull-Down-Widerstand an Pin | - | D0 | GPIO 2,4,5 GPIO 12-39 45 k\Omega |
Aktiviert werden die Widerstände in der Arduino-IDE jeweils mit dem pinMode()
-Befehl - je nach verwendetem Board sind diese verfügbar:
pinMode(pinTasterExternR, INPUT); // Taster mit externem Pullup/Pulldown (immer vorhanden)
pinMode(pinTasterInternPU, INPUT_PULLUP); // Taster mit internem Pulldown (Uno, ESP8266, ESP32)
pinMode(pinTasterInternPD, INPUT_PULLDOWN); // Taster mit internem Pulldown (nur ESP32)
Das übrige Programm kann unverändert bleiben, lediglich die Pullup/Pulldown-Widerstände der Schaltung sollten dann entfernt werden.
Da sich die Microcontroller in der Regel auf Boards mit weiteren Komponenten befinden (NodeMCU, Adafruit Feather usw.) kann es sein, dass nicht alle Eingänge in vollem Umfang nutzbar sind. Hier hilft ein Blick ins Datenblatt der Boards und Microcontroller. Im Fall eines ESP32 ist ein erster Ansatzpunkt auch dieses Programm, das an allen Pins jeweils den PullUp und den PullDown aktiviert, und dann prüft, welcher Pegel anliegt.
Öffner, Schließer und die Sache mit dem Kabelbruch
Schließer, normally opened (NO)
In kleineren Arduino-Projekten werden meist Taster verwendet, die im nicht betätigtem Zustand offen sind. Bei Betätigung schließen sie den Stromkreis, daher werden sie im deutschen Sprachgebrauch “Schließer” genannt. In Datenblättern findet man sie häufig mit der Bezeichnung “normally opened” oder kurz: NO.

Schließer werden zum Einschalten von Komponenten verwendet. Sollte es zu einem Kabelbruch irgendwo im Stromkreis kommen, kann der der digitale Eingang keinen Schaltvorgang registrieren - ein Einschalten der Komponente wäre nicht möglich.
Öffner, normally closed (NC)
Würden wir über einen Schließer eine Komponente ausschalten und hätten einen Kabelbruch im Stromkreis, so wäre das Ausschalten nicht möglich. Daher werden im Bereich der Steuerungstechnik (und in sicherheitstechnisch relevanten Projekten) zum Ausschalten immer Öffner verwendet:

Hier ist der Stromkreis immer geschlossen, lediglich im Fall der Betätigung des Schalters wird der Stromkreis unterbrochen (geöffnet: daher Öffner). Im Englischen werden diese Art Taster als normally closed (NC) bezeichnet.
Wichtig: In der Programmierung müssen wir berücksichtigen, dass das Potenzial (HIGH
/LOW
) bei Verwendung eines Schließers genau umgekehrt ist zu dem Potenzial bei Verwendung eines Öffners!
In den meisten Microcontrollerprojekten kommen Schließer zum Einsatz. Gerade bei längeren Leitungsstrecken bis zum Taster und bei kritischen Anwendungen sollte aber erwogen werden, ob die Lösung mit einem Öffner sachgerechter ist.
Neben reinen Öffnern und Schließern gibt es auch Taster, die über beide Kontakte verfügen. Gerade bei Tastern mit mehr als zwei Pins lohnt es, mit dem Messgerät herauszufinden, wie der interne Aufbau ist (sofern keine Beschriftung mit NO oder NC erkennbar ist).

Weitere Literatur und Quellen
Primärquelle ist immer das Datenblatt des ESP32
Primärquelle ist immer das Datenblatt des ESP8266
Quellen und offene Ressourcen (OER)
Die Ursprungstexte (als Markdown), Grafiken und zugrunde liegende Diagrammquelltexte finden sich (soweit möglich in weiterbearbeitbarer Form) in folgendem git-Repository:
https://gitlab.com/oer-informatik/mcu/arduino-esp.
Sofern nicht explizit anderweitig angegeben sind sie zur Nutzung als Open Education Resource (OER) unter Namensnennung (H. Stein, oer-informatik.de) freigegeben gemäß der Creative Commons Namensnennung 4.0 International Lizenz (CC BY 4.0).