Arduino Ampel selber bauen: LED-Verkehrsampel mit Fußgängerampel & Taster
Die LED-Ampel ist der Klassiker unter den Arduino-Einsteigerprojekten – und aus gutem Grund: Mit ein paar LEDs, Widerständen und einem Arduino UNO lernst du die wichtigsten Grundlagen – digitale Ausgänge, Timing und Programm-Zustände. In diesem Tutorial bleibt es aber nicht beim simplen Blinken: Wir bauen eine echte Verkehrsampel mit korrekter Rot-Gelb-Grün-Phasenfolge, erweitern sie um eine Fußgängerampel mit Anforderungstaster und machen alles am Ende mit millis() fließend – ohne dass der Taster je „hängt“.
Warum die Ampel das perfekte erste Projekt ist
Eine Ampel ist ein Zustandsautomat in seiner reinsten Form: Sie kennt eine feste Abfolge von Phasen (Rot → Rot-Gelb → Grün → Gelb → Rot), jede mit eigener Dauer. Genau dieses Denken in Zuständen brauchst du später in fast jedem größeren Projekt – vom Automaten über Menue-Steuerungen bis zur Maschinensteuerung. Die Ampel bringt es dir spielerisch bei, weil du das Ergebnis sofort blinken siehst. Und weil nur LEDs, Widerstände und ein Taster nötig sind, ist sie in einer halben Stunde aufgebaut.
ℹ️ Rot-Gelb-Grün – die deutsche Reihenfolge: Anders als in vielen Ländern gibt es in Deutschland vor Grün eine kurze Rot-Gelb-Phase („Gleich geht’s los“). Genau diese Phase bauen wir mit ein – so wird deine Ampel richtig authentisch.
Das brauchst du
Für den Anforderungstaster reicht ein einfacher Taster – wir nutzen den internen Pull-up-Widerstand des Arduino, sodass kein zusätzliches Bauteil nötig ist.
1Verkabelung der Auto-Ampel
Jede LED bekommt einen eigenen Digitalpin und einen Vorwiderstand in der Plus-Leitung. Das lange Beinchen (Anode) zeigt zum Widerstand/Pin, das kurze (Kathode) an GND.
| LED / Bauteil | Arduino UNO | Hinweis |
|---|---|---|
| Auto Rot | D2 (über 220 Ω) | Halt |
| Auto Gelb | D3 (über 220 Ω) | Übergang |
| Auto Grün | D4 (über 220 Ω) | Fahrt frei |
| Fuß Rot | D5 (über 220 Ω) | Warten |
| Fuß Grün | D6 (über 220 Ω) | Gehen |
| Taster | D7 ↔ GND | interner Pull-up |
| alle Kathoden | GND-Schiene | gemeinsame Masse |
ℹ️ Welcher Widerstand passt? Für 3mm-LEDs an 5 V sind 220–330 Ω ideal. Die genaue Rechnung mit dem Ohmschen Gesetz zeigt der Guide LED-Vorwiderstand berechnen.
2Die einfache Auto-Ampel
Fangen wir mit dem Kern an: die reine Autoampel mit korrekter Phasenfolge. Dieser erste Sketch nutzt bewusst noch delay(), weil er so am leichtesten zu verstehen ist:
const int AUTO_ROT = 2, AUTO_GELB = 3, AUTO_GRUEN = 4;
void setup() {
pinMode(AUTO_ROT, OUTPUT);
pinMode(AUTO_GELB, OUTPUT);
pinMode(AUTO_GRUEN, OUTPUT);
}
void loop() {
// Rot
digitalWrite(AUTO_ROT, HIGH);
delay(4000);
// Rot-Gelb (gleich geht es los)
digitalWrite(AUTO_GELB, HIGH);
delay(1500);
// Gruen
digitalWrite(AUTO_ROT, LOW);
digitalWrite(AUTO_GELB, LOW);
digitalWrite(AUTO_GRUEN, HIGH);
delay(4000);
// Gelb
digitalWrite(AUTO_GRUEN, LOW);
digitalWrite(AUTO_GELB, HIGH);
delay(1500);
digitalWrite(AUTO_GELB, LOW);
}
Lädst du das hoch, läuft die Ampel schon komplett durch. Schön – aber solange delay() läuft, ist der Arduino „taub“ für Tastendrücke. Genau das lösen wir gleich.
3Fußgängerampel mit Anforderungstaster
Jetzt kommt der spannende Teil: eine Fußgängerampel, die erst auf Knopfdruck reagiert. Damit der Taster jederzeit erkannt wird, ersetzen wir die delay()-Blöcke durch einen Zustandsautomaten mit millis(). Jede Phase merkt sich, wann sie begonnen hat, und wechselt erst, wenn ihre Dauer um ist:
const int AUTO_ROT = 2, AUTO_GELB = 3, AUTO_GRUEN = 4;
const int FUSS_ROT = 5, FUSS_GRUEN = 6;
const int TASTER = 7;
enum Phase { AUTO_FREI, AUTO_GELBPHASE, FUSS_FREI, FUSS_RAEUMEN };
Phase phase = AUTO_FREI;
unsigned long phasenStart = 0;
bool anforderung = false;
void setzePhase(Phase p) {
phase = p;
phasenStart = millis();
}
void setup() {
for (int p = 2; p <= 6; p++) pinMode(p, OUTPUT);
pinMode(TASTER, INPUT_PULLUP);
setzePhase(AUTO_FREI);
}
void loop() {
unsigned long jetzt = millis();
// Taster jederzeit abfragen (LOW = gedrueckt)
if (digitalRead(TASTER) == LOW) anforderung = true;
switch (phase) {
case AUTO_FREI:
digitalWrite(AUTO_GRUEN, HIGH); digitalWrite(AUTO_GELB, LOW);
digitalWrite(AUTO_ROT, LOW);
digitalWrite(FUSS_ROT, HIGH); digitalWrite(FUSS_GRUEN, LOW);
// Nach Anforderung mindestens 3 s Auto-Gruen lassen
if (anforderung && jetzt - phasenStart > 3000) setzePhase(AUTO_GELBPHASE);
break;
case AUTO_GELBPHASE:
digitalWrite(AUTO_GRUEN, LOW); digitalWrite(AUTO_GELB, HIGH);
if (jetzt - phasenStart > 1500) setzePhase(FUSS_FREI);
break;
case FUSS_FREI:
digitalWrite(AUTO_GELB, LOW); digitalWrite(AUTO_ROT, HIGH);
digitalWrite(FUSS_ROT, LOW); digitalWrite(FUSS_GRUEN, HIGH);
if (jetzt - phasenStart > 5000) setzePhase(FUSS_RAEUMEN);
break;
case FUSS_RAEUMEN: // Fuss-Gruen blinkt, dann zurueck
digitalWrite(FUSS_GRUEN, (jetzt / 300) % 2); // blinken
if (jetzt - phasenStart > 3000) {
digitalWrite(FUSS_GRUEN, LOW); digitalWrite(FUSS_ROT, HIGH);
digitalWrite(AUTO_ROT, LOW);
anforderung = false;
setzePhase(AUTO_FREI);
}
break;
}
}
💡 Das ist ein Zustandsautomat: Statt eines starren Ablaufs fragt der Arduino in jeder Runde „in welcher Phase bin ich, und ist ihre Zeit um?“. Weil loop() nie blockiert, wird der Taster in jeder Millisekunde geprüft. Das gleiche Muster steckt hinter unzähligen Projekten – mehr dazu im Guide millis() statt delay().
4Taster sauber entprellen
Mechanische Taster „prellen“: Beim Drücken schließt der Kontakt nicht sauber, sondern flackert millisekundenlang. In unserem Ampel-Code ist das egal, weil wir nur ein Flag setzen. Willst du aber zählen, wie oft gedrückt wurde, brauchst du Entprellung. So sieht sie kompakt aus:
const int TASTER = 7;
bool letzterStand = HIGH;
unsigned long letzteAenderung = 0;
int zaehler = 0;
void setup() {
pinMode(TASTER, INPUT_PULLUP);
Serial.begin(115200);
}
void loop() {
bool stand = digitalRead(TASTER);
if (stand != letzterStand && millis() - letzteAenderung > 50) {
letzteAenderung = millis();
letzterStand = stand;
if (stand == LOW) { // sauberer Druck erkannt
zaehler++;
Serial.print("Anforderung Nr. ");
Serial.println(zaehler);
}
}
}
Die 50 Millisekunden sind das übliche Entprell-Fenster. Warum das so funktioniert und wie du Taster per Interrupt abfragst, vertieft der Guide Arduino Interrupts & Entprellen.
5Kreuzung aus zwei Ampeln
Eine echte Kreuzung hat zwei Autoampeln, die gegenläufig schalten: Ist die eine grün, ist die andere rot. Mit einem zweiten LED-Satz und einer kleinen Erweiterung wird daraus eine komplette Kreuzung. Der Trick: eine gemeinsame Sicherheitsphase, in der beide Richtungen rot sind, bevor die andere Seite grün wird:
// Richtung A: D2/D3/D4 | Richtung B: D8/D9/D10
void alleRot() {
digitalWrite(2, HIGH); digitalWrite(3, LOW); digitalWrite(4, LOW);
digitalWrite(8, HIGH); digitalWrite(9, LOW); digitalWrite(10, LOW);
}
void richtungFrei(int rot, int gelb, int gruen) {
digitalWrite(rot, LOW); digitalWrite(gelb, LOW); digitalWrite(gruen, HIGH);
}
void loop() {
alleRot(); delay(2000); // Sicherheitsphase
richtungFrei(2,3,4); delay(5000); // A faehrt
digitalWrite(4, LOW); digitalWrite(3, HIGH); delay(1500);
alleRot(); delay(2000); // Sicherheitsphase
richtungFrei(8,9,10); delay(5000); // B faehrt
digitalWrite(10, LOW); digitalWrite(9, HIGH); delay(1500);
}
ℹ️ Warum die Sicherheitsphase? In echt sorgt die kurze Allrot-Phase dafür, dass die Kreuzung leer ist, bevor Querverkehr Grün bekommt. Baust du das nach, ist deine Kreuzung nicht nur hübsch, sondern auch „verkehrssicher“.
Praxistipps & Erweiterungen
- Nachtmodus: Lässt du nur die gelbe LED im Sekundentakt blinken, hast du den typischen „Ampel-aus“-Zustand nachgebaut.
- Countdown: Kombiniere die Fußgängerampel mit einem LCD1602, das die Restsekunden bis Grün anzeigt.
- Summer für Barrierefreiheit: Ein Piepton bei Fuß-Grün macht die Ampel wie im Original für Sehbehinderte nutzbar.
- Wenig Pins? Multiplexen: Mit einem Schieberegister steuerst du viele LEDs über nur drei Pins.
- Dauerhaft aufbauen: Läuft alles, löte die Ampel auf eine Lochrasterplatine.
Troubleshooting
⚠️ Eine LED bleibt dunkel: Meist ist sie verpolt. Das lange Beinchen (Anode) muss zum Widerstand/Pin, das kurze an GND. Dreh die LED einfach um.
⚠️ Taster wird nicht erkannt: Ohne INPUT_PULLUP „schwebt“ der Pin. Entweder den internen Pull-up nutzen (Taster gegen GND) oder einen 10-kΩ-Widerstand nach 5 V setzen.
⚠️ Ampel hängt in einer Phase: Wahrscheinlich eine Zeitbedingung mit falschem Vergleich (> vs. <) oder phasenStart wird nicht neu gesetzt. Prüfe, dass jeder Phasenwechsel über setzePhase() läuft.
⚠️ LEDs leuchten alle schwach: Fehlende gemeinsame Masse zwischen Breadboard und Arduino. Eine durchgehende GND-Leitung löst das.
⚠️ Fuß-Grün blinkt nicht: Der Ausdruck (jetzt / 300) % 2 braucht einen unsigned long – stelle sicher, dass jetzt aus millis() stammt.
🚀 Dein Ampel-Starterpaket
Alle Bauteile für dieses Projekt im Shop:
- UNO R3 Entwicklungsboard – die Steuerzentrale
- 3mm LED Sortiment – rot, gelb, grün
- Widerstands-Set – die Vorwiderstände
- Breadboard 400 Kontakte und Dupont-Jumperkabel
- Alternativ als kompaktes Board: Nano V3
Fazit
Aus fünf LEDs, ein paar Widerständen und einem Taster ist eine echte Ampelanlage geworden – mit deutscher Rot-Gelb-Grün-Phasenfolge, Fußgängerampel auf Anforderung und einer verkehrssicheren Kreuzung. Vor allem aber hast du das wichtigste Konzept der Mikrocontroller-Programmierung gelernt: den Zustandsautomaten mit millis(), der mehrere Dinge scheinbar gleichzeitig erledigt, ohne je zu blockieren.
Von hier ist der Weg zu größeren Projekten kurz: Der gleiche Aufbau steckt hinter Automaten, Waschmaschinen-Steuerungen und Menue-Systemen. Bau die Ampel um einen Countdown, einen Summer oder eine zweite Kreuzung herum – und du hast das Denken in Zuständen für immer verinnerlicht. Viel Spaß beim Blinken!