← Alle MakerNEWS

ESP32

ESP32 und LED für Anfänger: Anschließen, blinken, dimmen und mit millis() steuern

Herr Brinke 13 Minuten Lesezeit Aktualisiert: 29/08/2026
salvino fidacaro ebuujxV S7M unsplash scaled

Eine LED ist wahrscheinlich das bekannteste Bauteil für den Einstieg in die Mikrocontroller-Welt.

Warum?

Weil man sofort sieht, ob das Programm funktioniert.

Der ESP32 kann eine LED:

  • einschalten
  • ausschalten
  • blinken lassen
  • unterschiedlich schnell blinken lassen
  • mehrere LEDs steuern
  • dimmen
  • abhängig von Sensoren oder Tastern schalten

Dabei lernen wir einige der wichtigsten Grundlagen der ESP32-Programmierung kennen.

In diesem Beitrag schauen wir uns deshalb die LED am ESP32 Schritt für Schritt an.

Ganz einfach erklärt.


Was ist eine LED?

LED bedeutet:

Light Emitting Diode

Auf Deutsch:

Leuchtdiode

Eine LED ist ein elektronisches Bauteil, das Licht erzeugt, wenn Strom in der richtigen Richtung hindurchfließt.

Das Wort Diode ist dabei wichtig.

Denn eine LED lässt den Strom nicht einfach in beide Richtungen fließen.

Deshalb muss sie richtig herum angeschlossen werden.


Plus und Minus bei einer LED

Eine normale bedrahtete LED besitzt zwei Anschlüsse:

Anode (+)

und

Kathode (-)

Bei vielen LEDs gilt:

langes Bein = Anode (+)

kurzes Bein = Kathode (-)

Zusätzlich besitzt das Kunststoffgehäuse häufig auf der Kathodenseite eine abgeflachte Stelle.

Newbiely beschreibt ebenfalls die Kathode als Minus-Anschluss und die Anode als den Anschluss, über den die LED gesteuert wird.


Was passiert, wenn die LED falsch herum angeschlossen wird?

Dann leuchtet sie normalerweise nicht.

Das ist ein häufiger Anfängerfehler.

Wenn eine LED trotz scheinbar richtigem Programm nicht leuchtet, sollte deshalb zuerst geprüft werden:

Ist die LED richtig herum eingebaut?


Warum braucht eine LED einen Widerstand?

Eine LED sollte normalerweise nicht einfach direkt zwischen einen GPIO und GND angeschlossen werden.

Der Grund:

Eine LED begrenzt ihren Strom nicht ausreichend selbst.

Ohne passenden Widerstand könnte zu viel Strom fließen.

Das kann die LED beschädigen und den Ausgang des ESP32 unnötig belasten.

Deshalb verwenden wir einen:

Vorwiderstand

Newbiely verwendet in seinem einfachen ESP32-LED-Aufbau beispielsweise einen 220-Ω-Widerstand und weist ebenfalls darauf hin, dass LEDs normalerweise einen Strombegrenzungswiderstand benötigen.


Wie wird der Widerstand angeschlossen?

Vereinfacht beispielsweise so:

ESP32 GPIO
    │
    │
 Widerstand
    │
    │
   LED
    │
    │
   GND

Der Widerstand kann grundsätzlich auf der Anoden- oder Kathodenseite in Reihe zur LED sitzen.

Wichtig ist:

Der Strom muss durch den Widerstand und die LED fließen.


Welche Widerstandsgröße sollte verwendet werden?

Für einfache Experimente mit einer Standard-LED werden häufig Werte wie:

220 Ω

oder

330 Ω

verwendet.

Welcher Wert genau geeignet ist, hängt unter anderem von der LED-Farbe, ihrer Durchlassspannung und dem gewünschten Strom ab.

Für einen ersten Breadboard-Versuch ist ein Widerstand im Bereich einiger hundert Ohm eine gute, vorsichtige Wahl.


LED an den ESP32 anschließen

Für unser Beispiel verwenden wir:

GPIO 18

Die Schaltung sieht vereinfacht so aus:

GPIO 18
   │
   │
 220 Ω
   │
   │
 LED
   │
   │
 GND

Damit können wir GPIO 18 verwenden, um die LED zu steuern.


GPIO als Ausgang einstellen

Bevor wir eine LED steuern können, müssen wir dem ESP32 sagen:

Dieser GPIO soll als Ausgang verwendet werden.

Dafür gibt es:

pinMode();

Zum Beispiel:

pinMode(18, OUTPUT);

Noch übersichtlicher wird es, wenn wir dem Pin einen Namen geben:

#define LED_PIN 18

Dann können wir schreiben:

pinMode(LED_PIN, OUTPUT);

LED einschalten

Jetzt kommt:

digitalWrite(LED_PIN, HIGH);

Vereinfacht bedeutet das:

Ausgang HIGH

und bei unserer Schaltung:

LED an

Newbiely verwendet genau dieses Prinzip ebenfalls: GPIO als OUTPUT konfigurieren und anschließend mit digitalWrite() zwischen HIGH und LOW wechseln.


LED ausschalten

Zum Ausschalten verwenden wir:

digitalWrite(LED_PIN, LOW);

Damit erhalten wir:

HIGH → LED an

LOW → LED aus

Unser erstes LED-Programm

#define LED_PIN 18

void setup() {

  pinMode(LED_PIN, OUTPUT);

}

void loop() {

  digitalWrite(LED_PIN, HIGH);

}

Nach dem Start bleibt die LED eingeschaltet.

Möchten wir sie ausschalten:

digitalWrite(LED_PIN, LOW);

Jetzt lassen wir die LED blinken

Ein echter Klassiker der Mikrocontroller-Programmierung ist:

Blink

Die LED soll:

AN

↓

warten

↓

AUS

↓

warten

↓

wieder von vorne

Dafür verwenden wir delay().


Was bedeutet delay()?

delay() hält das Programm für eine bestimmte Anzahl von Millisekunden an.

Zum Beispiel:

delay(1000);

bedeutet:

1000 Millisekunden warten

Also:

1 Sekunde


Das Blink-Programm

#define LED_PIN 18

void setup() {

  pinMode(LED_PIN, OUTPUT);

}

void loop() {

  digitalWrite(LED_PIN, HIGH);

  delay(1000);

  digitalWrite(LED_PIN, LOW);

  delay(1000);

}

Der Ablauf:

LED an

↓

1 Sekunde

↓

LED aus

↓

1 Sekunde

↓

LED an

↓

...

Damit blinkt die LED dauerhaft.


Blinkgeschwindigkeit verändern

Die Geschwindigkeit können wir sehr einfach verändern.

Schneller:

delay(200);

Langsamer:

delay(2000);

Zum Beispiel:

digitalWrite(LED_PIN, HIGH);
delay(200);

digitalWrite(LED_PIN, LOW);
delay(200);

Jetzt blinkt die LED deutlich schneller.


Blinkzeit als Variable speichern

Noch schöner wird unser Programm, wenn wir die Zeit nicht überall direkt eintragen.

Zum Beispiel:

int blinkTime = 500;

Dann:

#define LED_PIN 18

int blinkTime = 500;

void setup() {

  pinMode(LED_PIN, OUTPUT);

}

void loop() {

  digitalWrite(LED_PIN, HIGH);

  delay(blinkTime);

  digitalWrite(LED_PIN, LOW);

  delay(blinkTime);

}

Jetzt müssen wir nur noch:

int blinkTime = 500;

ändern.

Zum Beispiel:

int blinkTime = 100;

oder:

int blinkTime = 2000;

Das Programm bleibt ansonsten gleich.


Mehrere LEDs steuern

Jetzt können wir mehrere Ausgänge verwenden.

Zum Beispiel:

  • rote LED
  • gelbe LED
  • grüne LED

Wir definieren:

#define RED_LED 18
#define YELLOW_LED 19
#define GREEN_LED 21

Im setup():

pinMode(RED_LED, OUTPUT);
pinMode(YELLOW_LED, OUTPUT);
pinMode(GREEN_LED, OUTPUT);

Damit kann jede LED einzeln gesteuert werden.


Eine einfache Ampel

Das Prinzip einer Ampel ist perfekt, um mehrere digitale Ausgänge kennenzulernen.

Wir benötigen:

  • rote LED
  • gelbe LED
  • grüne LED
  • je einen passenden Vorwiderstand

Newbiely behandelt eine ESP32-Ampel ebenfalls als Kombination mehrerer digitaler Ausgänge. Dort werden Rot, Gelb und Grün über getrennte GPIOs gesteuert.


Einfaches Ampelprogramm

#define RED_LED 18
#define YELLOW_LED 19
#define GREEN_LED 21

void setup() {

  pinMode(RED_LED, OUTPUT);
  pinMode(YELLOW_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);

}

void loop() {

  // Rot
  digitalWrite(RED_LED, HIGH);
  digitalWrite(YELLOW_LED, LOW);
  digitalWrite(GREEN_LED, LOW);

  delay(3000);


  // Rot-Gelb
  digitalWrite(RED_LED, HIGH);
  digitalWrite(YELLOW_LED, HIGH);
  digitalWrite(GREEN_LED, LOW);

  delay(1000);


  // Grün
  digitalWrite(RED_LED, LOW);
  digitalWrite(YELLOW_LED, LOW);
  digitalWrite(GREEN_LED, HIGH);

  delay(3000);


  // Gelb
  digitalWrite(RED_LED, LOW);
  digitalWrite(YELLOW_LED, HIGH);
  digitalWrite(GREEN_LED, LOW);

  delay(1000);

}

Damit haben wir schon einen kleinen automatischen Ablauf programmiert.


Aber delay() hat einen Haken

Für erste Übungen ist:

delay();

sehr praktisch.

Es gibt aber ein Problem.

Während:

delay(3000);

läuft, wartet das Programm.

Der ESP32 arbeitet während dieser Zeit unseren normalen Programmablauf nicht weiter ab.

Newbiely weist beim Blink-Beispiel ausdrücklich darauf hin, dass delay() andere Aufgaben blockiert und zeigt deshalb zusätzlich eine Variante mit millis().


Warum kann das problematisch sein?

Stellen wir uns vor, unsere Ampel soll gleichzeitig einen Taster erkennen.

Das Programm steht gerade hier:

delay(3000);

Jetzt wird der Taster gedrückt.

Unser Programm wartet aber noch.

Es schaut momentan gar nicht nach dem Taster.

Das ist ungefähr so, als würde jemand sagen:

Ich mache jetzt drei Sekunden lang gar nichts. Danach schaue ich wieder, was passiert ist.

Für einfache Blinkübungen ist das egal.

Für größere Programme wird es problematisch.


Die bessere Idee: Auf die Uhr schauen

Statt zu sagen:

Warte 1000 Millisekunden.

können wir sagen:

Schau auf die Uhr und prüfe, ob bereits 1000 Millisekunden vergangen sind.

Dafür gibt es beim ESP32:

millis();

Newbiely verwendet genau dieses Prinzip für „Blinken ohne Verzögerung“.


millis() einfach erklärt

millis() liefert die Zeit, die seit dem Start des Programms vergangen ist.

Vereinfacht beispielsweise:

Start

0 ms

↓

500 ms

↓

1000 ms

↓

1500 ms

↓

2000 ms

Das Programm kann also fragen:

Ist seit der letzten Aktion genug Zeit vergangen?

Wenn ja:

LED umschalten

Wenn nein:

einfach weiterarbeiten


Warum ist millis() besser?

Mit delay():

LED an

↓

WARTEN

↓

WARTEN

↓

WARTEN

↓

LED aus

Mit millis():

LED an

↓

Zeit prüfen

↓

Taster prüfen

↓

Sensor prüfen

↓

Zeit prüfen

↓

andere Aufgabe

↓

Zeit prüfen

Der ESP32 kann also zwischenzeitlich andere Aufgaben erledigen.


LED blinken ohne delay()

Ein vereinfachtes Beispiel:

#define LED_PIN 18

unsigned long previousMillis = 0;

const long interval = 1000;

bool ledState = false;

void setup() {

  pinMode(LED_PIN, OUTPUT);

}

void loop() {

  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {

    previousMillis = currentMillis;

    ledState = !ledState;

    digitalWrite(LED_PIN, ledState);

  }

}

Das sieht zunächst komplizierter aus.

Das Prinzip ist aber einfach.


Was passiert hier?

Wir speichern:

previousMillis

also:

Wann wurde die LED zuletzt umgeschaltet?

Dann schauen wir:

currentMillis = millis();

Wie spät ist es jetzt?

Anschließend vergleichen wir:

currentMillis - previousMillis >= interval

Vereinfacht:

Ist seit der letzten Umschaltung mindestens eine Sekunde vergangen?

Wenn ja:

LED umschalten

Wenn nein:

nichts tun und loop() weiterlaufen lassen


Warum lohnt es sich, millis() zu lernen?

Weil fast jedes größere Mikrocontrollerprojekt mehrere Dinge gleichzeitig machen soll.

Zum Beispiel:

LED blinken

+

Taster prüfen

+

Temperatur messen

+

Display aktualisieren

+

WLAN bedienen

Mit vielen langen delay()-Befehlen wird das schwierig.

Mit zeitgesteuerten Abläufen über millis() bleibt das Programm wesentlich reaktionsfähiger.


Kann eine LED nur AN und AUS?

Nein.

Bis jetzt kennen wir:

0 %

oder

100 %

Aber eine LED kann auch gedimmt werden.

Zum Beispiel:

0 %

25 %

50 %

75 %

100 %

Dafür verwenden Mikrocontroller häufig:

PWM


Was ist PWM?

PWM bedeutet:

Pulse Width Modulation

Auf Deutsch:

Pulsweitenmodulation

Das klingt kompliziert.

Das Prinzip ist aber erstaunlich einfach.

Der ESP32 schaltet die LED sehr schnell:

AN

und:

AUS

So schnell, dass unser Auge die einzelnen Schaltvorgänge nicht mehr wahrnimmt.


Ein einfaches Beispiel

Die LED ist immer eingeschaltet:

AN AN AN AN AN AN AN AN

Sie wirkt sehr hell.

Jetzt:

AN AUS AN AUS AN AUS AN AUS

Sie ist nur ungefähr die Hälfte der Zeit eingeschaltet.

Für unser Auge wirkt sie:

dunkler

Noch weniger:

AN AUS AUS AUS AN AUS AUS AUS

Die LED wirkt noch dunkler.


Was ist das Tastverhältnis?

Das Verhältnis zwischen:

EIN-Zeit

und:

AUS-Zeit

wird häufig als:

Duty Cycle

oder:

Tastverhältnis

bezeichnet.

Zum Beispiel:

0 %   → LED aus

25 %  → eher dunkel

50 %  → mittlere Helligkeit

75 %  → hell

100 % → volle Helligkeit

Newbiely erklärt das Dimmen ebenfalls über ein PWM-Signal: Je größer das Tastverhältnis, desto heller erscheint die LED.


Warum wird die Spannung nicht einfach kleiner gemacht?

Der ESP32 erzeugt an einem normalen digitalen Ausgang grundsätzlich digitale Zustände.

Also vereinfacht:

LOW

oder

HIGH

PWM erzeugt die scheinbare Zwischenstufe durch sehr schnelles Umschalten.

Damit lassen sich nicht nur LEDs dimmen.

PWM wird beispielsweise auch für andere Steueraufgaben verwendet.


LED langsam heller und dunkler werden lassen

Ein schöner Effekt ist:

dunkel

↓

heller

↓

noch heller

↓

maximal hell

↓

dunkler

↓

noch dunkler

↓

aus

Dieser Effekt wird häufig als:

Fade

bezeichnet.

Newbiely hat dafür ein eigenes ESP32-Tutorial und zeigt dort sowohl Varianten mit delay() als auch mit millis().

Für den Einstieg reicht zunächst das Verständnis:

Die Helligkeit wird nicht nur mit HIGH und LOW gesteuert, sondern über ein PWM-Signal.


Kann jeder GPIO für LEDs verwendet werden?

Nicht automatisch.

Je nach verwendetem ESP32-Chip und Development Board können einzelne GPIOs besondere Funktionen oder Einschränkungen besitzen.

Deshalb gilt:

Vor dem Aufbau immer die Pinbelegung des konkret verwendeten ESP32-Boards prüfen.

Das gilt besonders dann, wenn später:

  • PWM
  • ADC
  • I²C
  • SPI
  • UART

oder andere Spezialfunktionen verwendet werden.


Eingebaute LED oder externe LED?

Manche ESP32-Boards besitzen bereits eine LED auf der Platine.

Das ist praktisch für erste Tests.

Allerdings gilt:

Nicht jedes ESP32-Board besitzt dieselbe LED am selben GPIO.

Deshalb sollte die Dokumentation des konkreten Boards geprüft werden.

Für Lernprojekte ist eine externe LED oft sogar besser.

Warum?

Weil dabei gleichzeitig gelernt wird:

  • Breadboard verwenden
  • Polarität beachten
  • Widerstand verwenden
  • GPIO verbinden
  • GND verbinden

LED und Taster kombinieren

Aus dem letzten Beitrag kennen wir bereits den Taster.

Jetzt können wir beide Bauteile kombinieren.

TASTER
   ↓
ESP32
   ↓
 LED

Zum Beispiel:

#define BUTTON_PIN 21
#define LED_PIN 18

void setup() {

  pinMode(BUTTON_PIN, INPUT_PULLUP);

  pinMode(LED_PIN, OUTPUT);

}

void loop() {

  if (digitalRead(BUTTON_PIN) == LOW) {

    digitalWrite(LED_PIN, HIGH);

  }
  else {

    digitalWrite(LED_PIN, LOW);

  }

}

Jetzt gilt:

Taster drücken

↓

LED an

Taster loslassen:

LED aus

Damit verbinden wir einen digitalen Eingang mit einem digitalen Ausgang.


Sensor und LED kombinieren

Dasselbe Prinzip funktioniert später auch mit Sensoren.

Zum Beispiel:

Lichtsensor
    ↓
  ESP32
    ↓
zu dunkel?
    ↓
   JA
    ↓
 LED an

Oder:

Bewegungsmelder
      ↓
    ESP32
      ↓
Bewegung erkannt?
      ↓
     JA
      ↓
    LED an

Die LED ist deshalb nicht nur eine Lernübung.

Sie ist auch eine einfache Möglichkeit, Zustände sichtbar zu machen.


LEDs als Statusanzeige

In echten Projekten können LEDs beispielsweise anzeigen:

Grün

→ System läuft
Gelb

→ Verbindung wird aufgebaut
Rot

→ Fehler

Oder:

Blinken

→ WLAN-Verbindung wird gesucht

Damit kann eine einzelne LED bereits viele Informationen vermitteln.


Typische Anfängerfehler mit LEDs

Wenn eine LED nicht funktioniert, liegt es häufig an einem kleinen Fehler.

LED falsch herum

Anode und Kathode prüfen.


GND fehlt

Die Schaltung benötigt einen vollständigen Stromkreis.


Falscher GPIO

Im Programm:

#define LED_PIN 18

Die LED steckt aber an GPIO 21.

Programm und Hardware müssen zusammenpassen.


GPIO nicht als OUTPUT eingestellt

Es fehlt:

pinMode(LED_PIN, OUTPUT);

Vorwiderstand vergessen

Eine normale externe LED sollte mit einem geeigneten Strombegrenzungswiderstand verwendet werden.


HIGH und LOW verwechselt

Bei unserer Standardschaltung:

HIGH = LED an

LOW = LED aus

Bei anders aufgebauten Schaltungen kann sich diese Logik jedoch auch umkehren.


delay() blockiert das Programm

Bei einer einzelnen blinkenden LED ist das kein Problem.

Sobald mehrere Dinge gleichzeitig passieren sollen, sollte über Alternativen wie millis() nachgedacht werden.


Die wichtigsten LED-Befehle

GPIO als Ausgang:

pinMode(LED_PIN, OUTPUT);

LED einschalten:

digitalWrite(LED_PIN, HIGH);

LED ausschalten:

digitalWrite(LED_PIN, LOW);

Warten:

delay(1000);

Zeit seit Programmstart abfragen:

millis();

Mit diesen wenigen Grundlagen lassen sich bereits viele LED-Projekte umsetzen.


Das Wichtigste in 60 Sekunden

Eine LED besitzt:

Anode (+)

und:

Kathode (-)

Bei einer normalen LED wird ein geeigneter Vorwiderstand verwendet.

Eine einfache Schaltung:

GPIO
 │
Widerstand
 │
 LED
 │
 GND

Den GPIO stellen wir auf Ausgang:

pinMode(LED_PIN, OUTPUT);

LED einschalten:

digitalWrite(LED_PIN, HIGH);

LED ausschalten:

digitalWrite(LED_PIN, LOW);

Mit:

delay();

können wir eine einfache Blinkschaltung programmieren.

Für größere Programme ist:

millis();

häufig besser geeignet, weil das Programm während der Wartezeit weiterarbeiten kann.

Und mit:

PWM

kann die wahrgenommene Helligkeit einer LED verändert werden.

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


Wie geht es weiter?

Wir kennen jetzt:

  • digitale Eingänge
  • digitale Ausgänge
  • Taster
  • LEDs
  • HIGH und LOW
  • digitalRead()
  • digitalWrite()
  • delay()
  • millis()

Der nächste wichtige Schritt sind Werte, die nicht nur:

0 oder 1

kennen.

Im nächsten Beitrag geht es deshalb um:

ESP32 und analoge Werte

Dabei schauen wir uns an:

  • was analog bedeutet
  • Unterschied zwischen digital und analog
  • was ein ADC ist
  • analogRead()
  • Potentiometer anschließen
  • Messwerte im Serial Monitor anzeigen
  • Werte verändern und vergleichen
  • Grenzwerte verwenden
  • LED abhängig vom Potentiometer steuern
  • analoge Sensoren verstehen

Damit kommen wir von einfachen EIN/AUS-Signalen zu echten Messwerten.


Alle Beiträge dieser Serie

Add your first comment to this post