#158Intermediário

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…

5.0(1)
15 concluído
Raspberry Pi Pico: semáforo com 4 modos selecionados por botão (máquina de estados)
Semáforos reais piscam em amarelo à noite e às vezes permanecem no vermelho; neste projeto, você escolhe cada opção com um único botão. Cada acionamento passa para o próximo modo: ciclo normal com vermelho, amarelo e verde em sequência, só vermelho, amarelo piscante e totalmente desligado. O Raspberry Pi Pico controla as luzes enquanto continua monitorando o botão, sem perder nenhum acionamento.

Vídeo

Esquema do circuito

Raspberry Pi Pico: semáforo com 4 modos selecionados por botão (máquina de estados) - Circuit

Código-fonte

MicroPython
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)
84

Perguntas 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.