Raspberry Pi Pico: semáforo com 4 modos selecionados por botão (máquina de estados)
4 modos de semáforo com apenas 1 botão! O modo muda a cada acionamento: Ciclo normal (vermelho → amarelo → verde em sequência), Só vermelho (sinal de parada), Amarelo piscante (atenção/modo noturno), Desligado (manutenção). Conceitos: máquina de estados (a variável mode determina qual comportamento executar), alternância cíclica de modos com módulo ((mode + 1) % 4 → ciclo infinito 0→1→2→3→0), temporização sem bloqueio (as fases dos LEDs são temporizadas…

Vídeo
Esquema do circuito

Código-fonte
1# ─────────────────────────────────────────
2# BlueGrays · bluegrays.com
3# Raspberry Pi Pico: semáforo com 4 modos selecionados por botão (máquina de estados)
4# ─────────────────────────────────────────
5# Um botão percorre 4 modos: ciclo normal (vermelho -> amarelo -> verde),
6# só vermelho, amarelo piscando e desligado. Usa uma máquina de estados e
7# temporização sem bloqueio com time.ticks_ms(), então o botão sempre
8# responde.
9#
10# Pinos:
11# GP11 -> LED verde
12# GP12 -> LED amarelo
13# GP13 -> LED vermelho (cada LED com 220 ohm)
14# GP4 -> Botão (outra perna no GND)
15
16from machine import Pin
17import time
18
19# ============ LEDS ============
20green = Pin(11, Pin.OUT) # Verde
21yellow = Pin(12, Pin.OUT) # Amarelo
22red = Pin(13, Pin.OUT) # Vermelho
23
24# ============ BOTÃO ============
25button = Pin(4, Pin.IN, Pin.PULL_UP) # Lê 0 quando pressionado
26
27# ============ ESTADO ============
28# Modo: 0 ciclo normal, 1 só vermelho, 2 amarelo piscando, 3 desligado
29mode = 0
30last_btn = 1 # Valor anterior do botão
31blink_state = False # Estado do amarelo piscando
32last_tick = time.ticks_ms() # Última troca da piscada
33
34# ============ CICLO NORMAL ============
35normal_step = 0 # 0: vermelho, 1: amarelo, 2: verde
36normal_last = time.ticks_ms() # Hora de início do passo
37NORMAL_TIMES = [3000, 1000, 3000] # Vermelho, amarelo, verde (ms)
38LEDS = [red, yellow, green]
39
40def all_off():
41 # Apaga todos os LEDs
42 red.off(); yellow.off(); green.off()
43
44# ============ LOOP PRINCIPAL ============
45while True:
46 btn = button.value()
47
48 # ---- Botão pressionado (1 -> 0): troca de modo ----
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) # Debounce
55 last_btn = btn
56
57 now = time.ticks_ms()
58
59 # ---- Ciclo normal do semáforo ----
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 # ---- Só vermelho (pare) ----
68 elif mode == 1:
69 all_off(); red.on()
70
71 # ---- Amarelo piscando, 0.4 s (atenção/noite) ----
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 # ---- Desligado ----
80 else:
81 all_off()
82
83 time.sleep_ms(10)
84Perguntas frequentes
O que é uma máquina de estados?
Uma única variável (mode) determina o que o programa faz no momento. Cada acionamento do botão muda o modo, e o laço executa apenas o código do modo atual. É a forma padrão de manter comportamentos complexos organizados.
O que faz (mode + 1) % 4?
Incrementa o modo em um e volta a 0 quando chega a 4. Assim, o modo percorre a sequência 0, 1, 2, 3, 0, 1... sem parar.
Por que usar ticks_ms() em vez de time.sleep()?
Durante sleep(), o Pico não consegue ler o botão, o que atrasa as mudanças de modo. ticks_ms() e ticks_diff() evitam esperas longas durante as fases dos LEDs. Porém, esta versão espera 200 ms para debounce nas mudanças de modo e 10 ms ao final de cada laço; o botão não é lido novamente nesses intervalos.
Posso adicionar um novo modo?
Sim, aumente o número de modos para 5 e escreva um bloco de comportamento separado para o novo modo, como verde piscante ou todas as luzes acendendo em sequência.
