Raspberry Pi Pico-Ampel mit 4-Modus-Tastenwahlschalter (Zustandsmaschine, GP11-13 + GP4)
4 verschiedene Modi für die Ampel mit nur einer Taste! Mit jedem Tastendruck wechselt der Modus: **Normaler Zyklus** (nacheinander rot → gelb → grün), **Nur Rot** (Haltebefehl), **Gelb blinkend** (Achtung/Nachtmodus), **Aus** (Wartung). Lerninhalte: **Zustandsmaschine** (die Variable `mode` bestimmt, welches Verhalten ausgeführt wird), **Modulo-Modus-Zyklus** (`(mode + 1) % 4` → 0→1→2→3→0 – endloser Zyklus), **non-blocking timing** (die LED-Phasen werden mit `time.ticks_ms()` + `time.ticks_diff(

Video
Schaltplan

Quellcode
1# ─────────────────────────────────────────
2# BlueGrays · bluegrays.com
3# Raspberry Pi Pico-Ampel mit 4-Modus-Tastenwahlschalter (Zustandsmaschine, GP11-13 + GP4)
4# ─────────────────────────────────────────
5# Eine Taste schaltet durch 4 Modi: normaler Zyklus (Rot -> Gelb -> Grün),
6# nur Rot, gelbes Blinken und aus. Nutzt einen Zustandsautomaten und nicht
7# blockierendes Timing mit time.ticks_ms(), sodass die Taste immer
8# reagiert.
9#
10# Pins:
11# GP11 -> Grüne LED
12# GP12 -> Gelbe LED
13# GP13 -> Rote LED (jede LED mit 220 Ohm)
14# GP4 -> Taste (anderes Beinchen an GND)
15
16from machine import Pin
17import time
18
19# ============ LEDS ============
20green = Pin(11, Pin.OUT) # Grün
21yellow = Pin(12, Pin.OUT) # Gelb
22red = Pin(13, Pin.OUT) # Rot
23
24# ============ TASTE ============
25button = Pin(4, Pin.IN, Pin.PULL_UP) # Liest 0 bei Druck
26
27# ============ ZUSTAND ============
28# Modus: 0 normaler Zyklus, 1 nur Rot, 2 Gelb blinkend, 3 aus
29mode = 0
30last_btn = 1 # Vorheriger Tastenwert
31blink_state = False # Zustand des gelben Blinkens
32last_tick = time.ticks_ms() # Letztes Umschalten des Blitzes
33
34# ============ NORMALER ZYKLUS ============
35normal_step = 0 # 0: Rot, 1: Gelb, 2: Grün
36normal_last = time.ticks_ms() # Startzeit des Schritts
37NORMAL_TIMES = [3000, 1000, 3000] # Rot, Gelb, Grün (ms)
38LEDS = [red, yellow, green]
39
40def all_off():
41 # Alle LEDs ausschalten
42 red.off(); yellow.off(); green.off()
43
44# ============ HAUPTSCHLEIFE ============
45while True:
46 btn = button.value()
47
48 # ---- Taste gedrückt (1 -> 0): Moduswechsel ----
49 if last_btn == 1 and btn == 0:
50 mode = (mode + 1) % 4
51 all_off()
52 normal_step = 0
53 normal_last = time.ticks_ms()
54 time.sleep_ms(200) # Entprellung
55 last_btn = btn
56
57 now = time.ticks_ms()
58
59 # ---- Normaler Ampelzyklus ----
60 if mode == 0:
61 if time.ticks_diff(now, normal_last) > NORMAL_TIMES[normal_step]:
62 normal_step = (normal_step + 1) % 3
63 normal_last = now
64 all_off()
65 LEDS[normal_step].on()
66
67 # ---- Nur Rot (Stopp) ----
68 elif mode == 1:
69 all_off(); red.on()
70
71 # ---- Gelbes Blinken, 0.4 s (Vorsicht/Nacht) ----
72 elif mode == 2:
73 if time.ticks_diff(now, last_tick) > 400:
74 blink_state = not blink_state
75 yellow.value(blink_state)
76 last_tick = now
77 red.off(); green.off()
78
79 # ---- Aus ----
80 else:
81 all_off()
82
83 time.sleep_ms(10)
84FAQ
Was ist ein Zustandsautomat (State Machine)?▾
Eine einzige Variable (mode) bestimmt, was das Programm gerade tut. Jeder Tastendruck ändert den Modus, und die Schleife führt nur den Code des aktuellen Modus aus. Das ist der übliche Weg, komplexes Verhalten übersichtlich zu halten.
Was macht (mode + 1) % 4?▾
Es erhöht den Modus um eins und springt bei 4 wieder auf 0. So wechselt der Modus endlos 0, 1, 2, 3, 0, 1 …
Warum ticks_ms() statt time.sleep()?▾
Während sleep() kann der Pico den Taster nicht lesen, Moduswechsel kommen verzögert an. ticks_ms() und ticks_diff() vermeiden lange Wartezeiten während der LED-Phasen. Diese Version wartet jedoch beim Moduswechsel 200 ms zur Entprellung und am Ende jedes Schleifendurchlaufs 10 ms; in diesen Zeiträumen wird der Taster nicht erneut gelesen.
Kann ich einen neuen Modus hinzufügen?▾
Ja, erhöhe die Anzahl der Modi auf 5 und schreibe für den neuen Modus einen eigenen Verhaltensblock, zum Beispiel ein grünes Blinken oder alle Lichter nacheinander.
