# 3 LCD + 3 Sensores (Pico / MicroPython) + Control por rangos
# -------------------------
from machine import Pin, I2C, SoftI2C, time_pulse_us
from time import sleep, sleep_us
from pico_i2c_lcd import I2cLcd
# -------------------------
# I2C LCD 1 (Hardware I2C0) -> GP0/GP1
# -------------------------
i2c0 = I2C(0, sda=Pin(0), scl=Pin(1), freq=100000)
addrs0 = i2c0.scan()
if not addrs0:
raise RuntimeError("No se detecta LCD en I2C0 (SDA=GP0, SCL=GP1).")
I2C_ADDR0 = addrs0[0]
lcd1 = I2cLcd(i2c0, I2C_ADDR0, 2, 16)
# -------------------------
# I2C LCD 2 (Hardware I2C1) -> GP18/GP19
# -------------------------
i2c1 = I2C(1, sda=Pin(18), scl=Pin(19), freq=100000)
addrs1 = i2c1.scan()
if not addrs1:
raise RuntimeError("No se detecta LCD en I2C1 (SDA=GP18, SCL=GP19).")
I2C_ADDR1 = addrs1[0]
lcd2 = I2cLcd(i2c1, I2C_ADDR1, 2, 16)
# -------------------------
# I2C LCD 3 (SoftI2C) -> GP20/GP21
# -------------------------
i2c2 = SoftI2C(sda=Pin(20), scl=Pin(21), freq=100000)
addrs2 = i2c2.scan()
if not addrs2:
raise RuntimeError("No se detecta LCD en SoftI2C (SDA=GP20, SCL=GP21).")
I2C_ADDR2 = addrs2[0]
lcd3 = I2cLcd(i2c2, I2C_ADDR2, 2, 16)
# -------------------------
# Sensores ultrasónicos
# -------------------------
TRIG1 = Pin(7, Pin.OUT)
ECHO1 = Pin(6, Pin.IN)
TRIG2 = Pin(11, Pin.OUT)
ECHO2 = Pin(10, Pin.IN)
TRIG3 = Pin(9, Pin.OUT)
ECHO3 = Pin(8, Pin.IN)
# -------------------------
# Rangos de control (según tu requerimiento)
# -------------------------
R1_MIN, R1_MAX = 25, 50 # d1 -> LED rojo
R2_MIN, R2_MAX = 51, 75 # d2 -> LED amarillo
R3_MIN, R3_MAX = 76, 100 # d3 -> LED verde
# ------------------- LEDs -------------------
ledr = Pin(15, Pin.OUT) # Led rojo - BAJO
leda = Pin(14, Pin.OUT) # Led amarillo - MEDIO
ledv = Pin(13, Pin.OUT) # Led verde - ALTO
# Recomendado: apagar LEDs al inicio
ledr.value(0)
leda.value(0)
ledv.value(0)
def medir_distancia(trig: Pin, echo: Pin, timeout_us=30000):
# Pulso de disparo (TRIG)
trig.low()
sleep_us(2)
trig.high()
sleep_us(10)
trig.low()
# Medir pulso en ECHO (en microsegundos)
dur = time_pulse_us(echo, 1, timeout_us)
# dur < 0 = timeout (sin eco)
if dur < 0:
return None
# Distancia en cm (velocidad sonido ≈ 0.0343 cm/us)
dist_cm = (dur * 0.0343) / 2
return dist_cm
def en_rango(valor, minimo, maximo):
"""True si valor está dentro de [minimo, maximo] y no es None."""
if valor is None:
return False
return minimo <= valor <= maximo
def mostrar(lcd, titulo, dist, ok, rmin, rmax):
lcd.clear()
lcd.putstr(titulo + "\n")
if dist is None:
lcd.putstr("Sin eco")
else:
estado = "OK" if ok else "FUERA"
lcd.putstr("{:0.1f}cm {}".format(dist, estado))
# Títulos por pantalla
tit1 = "Nivel S1:"
tit2 = "Nivel S2:"
tit3 = "Nivel S3:"
# -------------------------
# Loop principal
# -------------------------
while True:
# Medimos de a uno para evitar interferencia (cross-talk)
d1 = medir_distancia(TRIG1, ECHO1)
sleep(0.07)
d2 = medir_distancia(TRIG2, ECHO2)
sleep(0.07)
d3 = medir_distancia(TRIG3, ECHO3)
sleep(0.07)
# Control por rangos
ok1 = en_rango(d1, R1_MIN, R1_MAX)
ok2 = en_rango(d2, R2_MIN, R2_MAX)
ok3 = en_rango(d3, R3_MIN, R3_MAX)
# -------------------------
# LEDs INDEPENDIENTES (cada sensor enciende su LED si está en rango)
# -------------------------
ledr.value(1 if ok1 else 0) # Rojo según d1
leda.value(1 if ok2 else 0) # Amarillo según d2
ledv.value(1 if ok3 else 0) # Verde según d3
# Mostrar en LCDs
mostrar(lcd1, tit1, d1, ok1, R1_MIN, R1_MAX)
mostrar(lcd2, tit2, d2, ok2, R2_MIN, R2_MAX)
mostrar(lcd3, tit3, d3, ok3, R3_MIN, R3_MAX)
# Consola (debug)
print("S1:", d1 if d1 is not None else "Sin eco", "->", "OK" if ok1 else "FUERA",
"| S2:", d2 if d2 is not None else "Sin eco", "->", "OK" if ok2 else "FUERA",
"| S3:", d3 if d3 is not None else "Sin eco", "->", "OK" if ok3 else "FUERA")
sleep(0.2)