# ============================================================
# Raspberry Pi Pico W - MicroPython
# HC-SR04 + LCD paralela 16x2 + 8 LEDs + pot. de contraste
# Muestra distancia en LCD y enciende patrones de LEDs
# segun rangos excluyentes de distancia.
# ============================================================
from machine import Pin, time_pulse_us
import utime
# ------------------ LEDs (GP2 a GP9) ------------------------
# led1..led8 -> indices 0..7
PINES_LEDS = [2, 3, 4, 5, 6, 7, 8, 9] # GP de cada LED
leds = [Pin(p, Pin.OUT) for p in PINES_LEDS] # objetos Pin de salida
def apagar_todos():
"""Apaga los 8 LEDs."""
for led in leds:
led.value(0)
def encender(lista):
"""Apaga todo y enciende solo los LEDs indicados (numeros 1..8)."""
apagar_todos()
for n in lista:
leds[n - 1].value(1) # n-1 porque la lista interna empieza en 0
# ------------------ Sensor HC-SR04 --------------------------
TRIG = Pin(16, Pin.OUT) # GP16 -> Trig
ECHO = Pin(17, Pin.IN) # GP17 -> Echo
def medir_distancia():
"""Devuelve la distancia en cm medida por el HC-SR04."""
TRIG.value(0)
utime.sleep_us(2)
TRIG.value(1) # pulso de disparo de 10 us
utime.sleep_us(10)
TRIG.value(0)
# mide la duracion del eco (timeout 30 ms)
duracion = time_pulse_us(ECHO, 1, 30000)
if duracion < 0:
return -1 # sin lectura valida
# distancia = tiempo * velocidad_sonido / 2 -> cm
return (duracion * 0.0343) / 2
# ------------------ LCD paralela 16x2 (HD44780, modo 4 bits) -
# Implementacion minima sin librerias externas.
RS = Pin(10, Pin.OUT) # GP10 -> RS
EN = Pin(11, Pin.OUT) # GP11 -> E (Enable)
D4 = Pin(12, Pin.OUT) # GP12 -> D4
D5 = Pin(13, Pin.OUT) # GP13 -> D5
D6 = Pin(14, Pin.OUT) # GP14 -> D6
D7 = Pin(15, Pin.OUT) # GP15 -> D7
DATA = [D4, D5, D6, D7]
def lcd_pulso():
"""Genera el pulso de Enable para validar el dato."""
EN.value(1)
utime.sleep_us(50)
EN.value(0)
utime.sleep_us(50)
def lcd_nibble(valor):
"""Coloca 4 bits en D4-D7 y los valida."""
for i in range(4):
DATA[i].value((valor >> i) & 1)
lcd_pulso()
def lcd_byte(valor, modo):
"""Envia un byte: modo=0 comando, modo=1 dato."""
RS.value(modo)
lcd_nibble(valor >> 4) # nibble alto
lcd_nibble(valor & 0x0F) # nibble bajo
def lcd_comando(c):
lcd_byte(c, 0)
def lcd_dato(d):
lcd_byte(d, 1)
def lcd_init():
"""Secuencia de arranque del HD44780 en modo 4 bits."""
utime.sleep_ms(50)
RS.value(0)
lcd_nibble(0x03); utime.sleep_ms(5)
lcd_nibble(0x03); utime.sleep_us(150)
lcd_nibble(0x03)
lcd_nibble(0x02) # fija modo 4 bits
lcd_comando(0x28) # 4 bits, 2 lineas, 5x8
lcd_comando(0x0C) # display ON, cursor OFF
lcd_comando(0x06) # incremento automatico
lcd_comando(0x01) # limpiar pantalla
utime.sleep_ms(2)
def lcd_cursor(col, fila):
"""Posiciona el cursor (col 0..15, fila 0..1)."""
dir_base = 0x80 + (0x40 * fila) + col
lcd_comando(dir_base)
def lcd_texto(texto):
"""Escribe una cadena en la posicion actual."""
for ch in texto:
lcd_dato(ord(ch))
# ------------------ Programa principal ----------------------
lcd_init()
lcd_cursor(0, 0)
lcd_texto("Distancia:")
while True:
d = medir_distancia()
# --- Mostrar distancia en la LCD (segunda linea) ---
lcd_cursor(0, 1)
if d < 0:
lcd_texto("--- cm ")
else:
lcd_texto("{:6.1f} cm ".format(d))
# --- Encendido de LEDs por rangos EXCLUYENTES ---
if d < 0:
apagar_todos() # sin lectura valida
elif d > 19.8:
encender([5]) # solo Led5
elif d > 16.4:
encender([6, 7]) # Led6 y Led7 (Led5 off)
elif d > 9.6:
encender([1, 7, 8]) # Led1, Led7, Led8 (Led6 off)
elif d > 8:
encender([1, 3, 4]) # Led1, Led3, Led4 (Led7, Led8 off)
else: # d < 8
encender([2]) # solo Led2
utime.sleep_ms(200)