# Feu tricolore + PIR + HC-SR04 + bouton + 7 segments (1 afficheur cathode commune)
# MicroPython - Raspberry Pi Pico
from machine import Pin, time_pulse_us
import time
# --- Pin config ---
LED_RED_PIN = 2
LED_YELLOW_PIN = 3
LED_GREEN_PIN = 4
BUTTON_PIN = 10 # pull-up interne
PIR_PIN = 11
TRIG_PIN = 12
ECHO_PIN = 13
SEG_PINS = {
'a': 14,
'b': 15,
'c': 16,
'd': 17,
'e': 18,
'f': 19,
'g': 20
}
# --- Init hardware ---
led_red = Pin(LED_RED_PIN, Pin.OUT)
led_yellow = Pin(LED_YELLOW_PIN, Pin.OUT)
led_green = Pin(LED_GREEN_PIN, Pin.OUT)
button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)
pir = Pin(PIR_PIN, Pin.IN)
trig = Pin(TRIG_PIN, Pin.OUT)
echo = Pin(ECHO_PIN, Pin.IN)
segments = {k: Pin(v, Pin.OUT) for k, v in SEG_PINS.items()}
# --- Params ---
DUR_RED = 3
DUR_YELLOW = 1
DUR_GREEN = 3
DISTANCE_SEUIL_CM = 50
ECHO_TIMEOUT_US = 30000
# --- 7-seg digit map (cathode commune: HIGH=allumé) ---
digit_map = {
0: {'a':1,'b':1,'c':1,'d':1,'e':1,'f':1,'g':0},
1: {'a':0,'b':1,'c':1,'d':0,'e':0,'f':0,'g':0},
2: {'a':1,'b':1,'c':0,'d':1,'e':1,'f':0,'g':1},
3: {'a':1,'b':1,'c':1,'d':1,'e':0,'f':0,'g':1},
4: {'a':0,'b':1,'c':1,'d':0,'e':0,'f':1,'g':1},
5: {'a':1,'b':0,'c':1,'d':1,'e':0,'f':1,'g':1},
6: {'a':1,'b':0,'c':1,'d':1,'e':1,'f':1,'g':1},
7: {'a':1,'b':1,'c':1,'d':0,'e':0,'f':0,'g':0},
8: {'a':1,'b':1,'c':1,'d':1,'e':1,'f':1,'g':1},
9: {'a':1,'b':1,'c':1,'d':1,'e':0,'f':1,'g':1}
}
def display_digit(n):
if n not in digit_map:
clear_display()
return
pat = digit_map[n]
for seg, pin in segments.items():
pin.value(1 if pat[seg] else 0)
def clear_display():
for p in segments.values():
p.value(0)
# --- feux ---
def feu_rouge():
led_red.value(1); led_yellow.value(0); led_green.value(0)
def feu_jaune():
led_red.value(0); led_yellow.value(1); led_green.value(0)
def feu_vert():
led_red.value(0); led_yellow.value(0); led_green.value(1)
# --- distance HC-SR04 ---
def mesure_distance_cm():
trig.value(0)
time.sleep_us(2)
trig.value(1)
time.sleep_us(10)
trig.value(0)
try:
duree = time_pulse_us(echo, 1, ECHO_TIMEOUT_US)
except OSError:
return 9999
if duree <= 0:
return 9999
dist = (duree / 2) / 29.1
return dist
# --- countdown with checks ---
def countdown_with_checks(seconds):
for sec in range(seconds, 0, -1):
display_digit(sec)
for _ in range(10):
# bouton (active low)
if button.value() == 0:
while button.value() == 0:
time.sleep_ms(50)
return False
presence = pir.value()
distance = mesure_distance_cm()
if presence == 0 and distance <= DISTANCE_SEUIL_CM:
clear_display()
return True
time.sleep_ms(100)
display_digit(0)
time.sleep_ms(300)
clear_display()
return False
# --- main loop ---
print("Démarrage feu tricolore avec 7-seg (1 afficheur)")
while True:
# bouton -> reset cycle (simple gestion)
if button.value() == 0:
while button.value() == 0:
time.sleep_ms(50)
print("Bouton appuyé : retour cycle normal")
presence = pir.value()
distance = mesure_distance_cm()
# mode automatique : pas de personne + véhicule proche
if presence == 0 and distance <= DISTANCE_SEUIL_CM:
print("Mode AUTO: pas de personne + véhicule détecté → VERT")
feu_vert()
display_digit(0)
# rester vert tant que condition vraie ou bouton appuyé
while True:
if button.value() == 0:
while button.value() == 0:
time.sleep_ms(50)
break
presence = pir.value()
distance = mesure_distance_cm()
if presence == 1 or distance > DISTANCE_SEUIL_CM:
break
time.sleep_ms(200)
clear_display()
continue
# cycle normal
print("Cycle normal: ROUGE")
feu_rouge()
if countdown_with_checks(DUR_RED):
continue
print("Cycle normal: JAUNE")
feu_jaune()
if countdown_with_checks(DUR_YELLOW):
continue
print("Cycle normal: VERT")
feu_vert()
if countdown_with_checks(DUR_GREEN):
continue