#158Intermedio

Semaforo Raspberry Pi Pico con selettore a 4 posizioni (macchina a stati, GP11-13 + GP4)

4 diverse modalità del semaforo con un solo pulsante! Ad ogni pressione del pulsante, la modalità cambia: **Ciclo normale** (rosso → giallo → verde in sequenza), **Solo rosso** (segnale di stop), **Giallo lampeggiante** (attenzione/modalità notturna), **Spento** (manutenzione). Concetti: **state machine** (macchina a stati — la variabile `mode` determina quale comportamento verrà eseguito), **modulo mod cycling** (`(mode + 1) % 4` → 0→1→2→3→0 ciclo infinito), **temporizzazione non bloccante** (l

5.0(1)
15 completato
Semaforo Raspberry Pi Pico con selettore a 4 posizioni (macchina a stati, GP11-13 + GP4)
I semafori veri lampeggiano gialli di notte e a volte restano sul rosso; in questo progetto scegli tutto questo con un solo pulsante. Ogni pressione passa alla modalità successiva: il ciclo normale con rosso, giallo e verde a turno, solo rosso, giallo lampeggiante e tutto spento. Il Raspberry Pi Pico gestisce le luci continuando ad ascoltare il pulsante, così nessuna pressione va persa.

Video

Schema circuito

Semaforo Raspberry Pi Pico con selettore a 4 posizioni (macchina a stati, GP11-13 + GP4) - Circuit

Codice sorgente

MicroPython
1# ─────────────────────────────────────────
2#   BlueGrays · bluegrays.com
3#   Semaforo Raspberry Pi Pico con selettore a 4 posizioni (macchina a stati, GP11-13 + GP4)
4# ─────────────────────────────────────────
5# Un pulsante scorre 4 modalità: ciclo normale (rosso -> giallo -> verde),
6# solo rosso, giallo lampeggiante e spento. Usa una macchina a stati e
7# temporizzazione non bloccante con time.ticks_ms(), così il pulsante
8# risponde sempre.
9#
10# Pin:
11#   GP11 -> LED verde
12#   GP12 -> LED giallo
13#   GP13 -> LED rosso (ogni LED con 220 ohm)
14#   GP4  -> Pulsante (altro piedino a GND)
15
16from machine import Pin
17import time
18
19# ============ LED ============
20green  = Pin(11, Pin.OUT)   # Verde
21yellow = Pin(12, Pin.OUT)   # Giallo
22red    = Pin(13, Pin.OUT)   # Rosso
23
24# ============ PULSANTE ============
25button = Pin(4, Pin.IN, Pin.PULL_UP)   # Legge 0 quando è premuto
26
27# ============ STATO ============
28# Modalità: 0 ciclo normale, 1 solo rosso, 2 giallo lampeggiante, 3 spento
29mode = 0
30last_btn = 1                 # Valore precedente del pulsante
31blink_state = False          # Stato del lampeggio giallo
32last_tick = time.ticks_ms()  # Ultima commutazione del lampeggio
33
34# ============ CICLO NORMALE ============
35normal_step = 0                     # 0: rosso, 1: giallo, 2: verde
36normal_last = time.ticks_ms()       # Ora di inizio del passo
37NORMAL_TIMES = [3000, 1000, 3000]   # Rosso, giallo, verde (ms)
38LEDS = [red, yellow, green]
39
40def all_off():
41    # Spegnere tutti i LED
42    red.off(); yellow.off(); green.off()
43
44# ============ CICLO PRINCIPALE ============
45while True:
46    btn = button.value()
47
48    # ---- Pulsante premuto (1 -> 0): cambio modalità ----
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)   # Antirimbalzo
55    last_btn = btn
56
57    now = time.ticks_ms()
58
59    # ---- Ciclo normale del semaforo ----
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    # ---- Solo rosso (stop) ----
68    elif mode == 1:
69        all_off(); red.on()
70
71    # ---- Lampeggio giallo, 0.4 s (attenzione/notte) ----
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    # ---- Spento ----
80    else:
81        all_off()
82
83    time.sleep_ms(10)
84

FAQ

Che cos'è una macchina a stati?▾

Una sola variabile (mode) decide cosa fa il programma in quel momento. Ogni pressione cambia la modalità e il ciclo esegue solo il codice della modalità attuale. È il modo standard per tenere in ordine comportamenti complessi.

A cosa serve (mode + 1) % 4?▾

Aumenta la modalità di uno e torna a 0 quando arriva a 4, così cambia all'infinito: 0, 1, 2, 3, 0, 1...

Perché usare ticks_ms() invece di time.sleep()?▾

Durante sleep() il Pico non può leggere il pulsante e i cambi di modalità arrivano in ritardo. ticks_ms() e ticks_diff() evitano lunghe attese durante le fasi dei LED. Tuttavia, questa versione attende 200 ms per il debounce al cambio di modalità e 10 ms alla fine di ogni iterazione del ciclo; durante questi intervalli il pulsante non viene riletto.

Posso aggiungere una nuova modalità?▾

Sì, porta il numero di modalità a 5 e scrivi un blocco di comportamento per la nuova, per esempio un lampeggio verde o tutte le luci che si accendono in sequenza.

Semaforo Raspberry Pi Pico con selettore a 4 modalità (macchina a stati, GP11-13 | BlueGrays