# main.py
import uasyncio as asyncio
from machine import Pin, SoftI2C
from i2c_lcd import I2cLcd
from lcd_api import LcdApi
import time
# =========================
# CONFIGURACIÓN LCD
# =========================
filas = 2
columnas = 16
I2C_direccion = 0x27
freq1 = 10000
i2c = SoftI2C(scl=Pin(22), sda=Pin(21), freq=freq1)
LCD = I2cLcd(i2c, I2C_direccion, filas, columnas)
#Creacion de caracteres
llave = [
0b01110,
0b01010,
0b01110,
0b00100,
0b00100,
0b00111,
0b00100,
0b00111,
]
editando = [
0b01110,
0b10001,
0b10000,
0b10000,
0b11111,
0b11011,
0b11011,
0b11111,
]
bloqueado = [
0b00000,
0b01110,
0b10001,
0b10001,
0b11111,
0b11011,
0b11011,
0b11111,
]
ojo = [
0b10001,
0b00000,
0b01110,
0b10101,
0b01110,
0b00000,
0b00000,
0b10001,
]
parlante = [
0b00000,
0b00010,
0b00110,
0b11110,
0b11110,
0b11110,
0b00110,
0b00010,
]
LCD.custom_char(1, llave)
LCD.custom_char(2, editando)
LCD.custom_char(3, bloqueado)
LCD.custom_char(4, ojo)
LCD.custom_char(5, parlante)
# =========================
# VARIABLES GLOBALES
# =========================
solicitud=False
ultima_tecla = None
num_pantalla=0
inicio=0
num=0
editar=0
desbloqueo=0
parpadeo=0
editand=0
avanzar=0
cursor_positions = [2, 3, 7, 8, 11, 12]
cursor_index = 0 # posición actual
retrocede=0
# =========================
# PINES DEl TECLADO MATRICIAL
# =========================
filas = [
Pin(23, Pin.OUT),
Pin(19, Pin.OUT),
Pin(18, Pin.OUT),
Pin(5, Pin.OUT)
]
# Pines de columnas (entradas con pull-up)
columnas = [
Pin(17, Pin.IN, Pin.PULL_UP),
Pin(16, Pin.IN, Pin.PULL_UP),
Pin(36, Pin.IN, Pin.PULL_UP),
Pin(15, Pin.IN, Pin.PULL_UP)
]
# Mapa del teclado
teclas = [
["1","2","3","subir"],
["4","5","6","izquierda"],
["7","8","9","derecha"],
["regresar","0","enter","bajar"]
]
# =========================
# PINES Y TIEMPOS DE LOS SEMAFOROS
# =========================
#-------------------------------------------------------------------
#--------------------------------------------------------------------
# SEMAFORO 1
semaforo1 = {
"verde": (Pin(13, Pin.OUT), 30),
"amarillo": (Pin(12, Pin.OUT), 2),
"rojo": (Pin(14, Pin.OUT), 40)
}
#Declara Variables de NOMBRE Y TIEMPO
led_rojo, tiempo_rojo = semaforo1["rojo"]
led_amarillo, tiempo_amarillo = semaforo1["amarillo"]
led_verde, tiempo_verde = semaforo1["verde"]
#Almacena los tiempos restantes
tiempos_restantes = {"rojo": 0,"verde": 0,"amarillo": 0}
#-------------------------------------------------------------------
#--------------------------------------------------------------------
# SEMAFORO 2
semaforo2 = {
"verde": (Pin(33, Pin.OUT), 30),
"amarillo": (Pin(32, Pin.OUT), 2),
"rojo": (Pin(2, Pin.OUT), 40)
}
#Declara Variables de NOMBRE Y TIEMPO
led_rojo2, tiempo_rojo2 = semaforo2["rojo"]
led_amarillo2, tiempo_amarillo2 = semaforo2["amarillo"]
led_verde2, tiempo_verde2 = semaforo2["verde"]
#Almacena los tiempos restantes
tiempos_restantes2 = {"rojo": 0,"verde": 0,"amarillo": 0}
#-------------------------------------------------------------------
#--------------------------------------------------------------------
#Declara variables de tiempo y nombre para semaforo auxiliar 1
semaforo_auxiliar1={
"verde": (Pin(27, Pin.OUT), 34),
"rojo": (Pin(26, Pin.OUT), 10),
"buzzer": (Pin(25, Pin.OUT),30)
}
led_verde1, tiempo_verde1 = semaforo_auxiliar1["verde"]
led_rojo1, tiempo_rojo1 = semaforo_auxiliar1["rojo"]
buzzer1,tiempo_buzzer1= semaforo_auxiliar1["buzzer"]
#Declara variables de tiempo y nombre para semaforo auxiliar 2
semaforo_auxiliar3={
"verde": (Pin(3, Pin.OUT), 34),
"rojo": (Pin(1, Pin.OUT), 10),
"buzzer": (Pin(4, Pin.OUT),30)
}
led_verde3, tiempo_verde3 = semaforo_auxiliar3["verde"]
led_rojo3, tiempo_rojo3 = semaforo_auxiliar3["rojo"]
buzzer3,tiempo_buzzer3= semaforo_auxiliar3["buzzer"]
# =========================
# PINES DEL PULSADOR
# =========================
pulsador1 = Pin(35, Pin.IN, Pin.PULL_DOWN)
pulsador2 = Pin(34, Pin.IN, Pin.PULL_DOWN)
# =========================
#FUNCIONES
# =========================
def lcd_clear_zone(x, y, n):
LCD.move_to(x, y)
LCD.putstr(" " * n)
LCD.move_to(x, y)
async def leer_teclado():
global ultima_tecla
for i, fila in enumerate(filas):
fila.value(0) # Activar la fila
for j, col in enumerate(columnas):
if col.value() == 0: # Tecla presionada
tecla_actual = teclas[i][j]
# Si es la misma tecla mantenida → NO la repito
if ultima_tecla == tecla_actual:
fila.value(1)
return None
# Nueva tecla → devuelvo y marco anti-rebote
ultima_tecla = tecla_actual
fila.value(1)
await asyncio.sleep_ms(150) # anti-rebote real
return tecla_actual
fila.value(1)
# Si NO hay teclas presionadas → limpio estado
ultima_tecla = None
return None
async def semaforo_principal():
while True:
# ============================
# ROJO
# ============================
led_rojo, tiempo_rojo = semaforo1["rojo"]
led_amarillo, tiempo_amarillo = semaforo1["amarillo"]
led_rojo.on()
for t in range(tiempo_rojo, -1, -1):
tiempos_restantes["rojo"] = t
await asyncio.sleep(1)
print(str(tiempos_restantes["rojo"]))
if num_pantalla==4:
LCD.move_to(2,1)
LCD.putstr(f"{tiempos_restantes['rojo']:02d}")
led_rojo.off()
led_amarillo.off()
# ============================
# VERDE
# ============================
led_verde, tiempo_verde = semaforo1["verde"]
led_verde.on()
for t in range(tiempo_verde, -1, -1):
tiempos_restantes["verde"] = t # ✅ guardamos el tiempo restante
await asyncio.sleep(1)
print(str(tiempos_restantes["verde"]))
if num_pantalla==4:
LCD.move_to(12,1)
LCD.putstr(f"{tiempos_restantes['verde']:02d}")
led_verde.off()
# ============================
# AMARILLO
# ============================
led_amarillo, tiempo_amarillo = semaforo1["amarillo"]
led_amarillo.on()
for t in range(tiempo_amarillo, -1, -1):
tiempos_restantes["amarillo"] = t # ✅ guardamos el tiempo restante
await asyncio.sleep(1)
print(str(tiempos_restantes["amarillo"]))
if num_pantalla==4:
LCD.move_to(7,1)
LCD.putstr(f"{tiempos_restantes['amarillo']:02d}")
led_amarillo.off()
#-----------------------------------------------------------------------
#----------------------------------------------------------------------
async def semaforo_principal2():
while True:
# ============================
# VERDE
# ============================
led_verde2, tiempo_verde2 = semaforo2["verde"]
led_verde2.on()
for t in range(tiempo_verde2, -1, -1):
tiempos_restantes2["verde"] = t # ✅ guardamos el tiempo restante
await asyncio.sleep(1)
print(str(tiempos_restantes2["verde"]))
if num_pantalla==5:
LCD.move_to(12,1)
LCD.putstr(f"{tiempos_restantes2['verde']:02d}")
led_verde2.off()
# ============================
# AMARILLO
# ============================
led_amarillo2, tiempo_amarillo2 = semaforo2["amarillo"]
led_amarillo2.on()
for t in range(tiempo_amarillo2, -1, -1):
tiempos_restantes2["amarillo"] = t # ✅ guardamos el tiempo restante
await asyncio.sleep(1)
print(str(tiempos_restantes2["amarillo"]))
if num_pantalla==5:
LCD.move_to(7,1)
LCD.putstr(f"{tiempos_restantes2['amarillo']:02d}")
led_amarillo2.off()
# ============================
# ROJO
# ============================
led_rojo2, tiempo_rojo2 = semaforo2["rojo"]
led_amarillo2, tiempo_amarillo2 = semaforo2["amarillo"]
led_rojo2.on()
for t in range(tiempo_rojo2, -1, -1):
tiempos_restantes2["rojo"] = t
await asyncio.sleep(1)
print(str(tiempos_restantes2["rojo"]))
if num_pantalla==5:
LCD.move_to(2,1)
LCD.putstr(f"{tiempos_restantes2['rojo']:02d}")
led_rojo2.off()
led_amarillo2.off()
#-------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------
async def color_amarillo():
while True:
t = tiempos_restantes["rojo"]
if t == 2: # faltan 3 segundos
led_amarillo.on()
# elif t == 0: # ciclo terminado
# led_amarillo.off()
await asyncio.sleep(0.1)
#-------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------
async def color_amarillo2():
while True:
t = tiempos_restantes2["rojo"]
if t == 2: # faltan 3 segundos
led_amarillo2.on()
# elif t == 0: # ciclo terminado
# led_amarillo.off()
await asyncio.sleep(0.1)
async def semaforo_aux_auto1():
led_verde1.off()
led_rojo1.on()
while True:
if tiempos_restantes["rojo"] <= 0:
# Principal no está en rojo → Auxiliar debe estar en rojo
led_verde1.off()
led_rojo1.on()
await asyncio.sleep(0.1)
continue
if tiempos_restantes["rojo"] == tiempo_rojo:
# Inicia ciclo de rojo del principal
await asyncio.sleep(2)
# Si sigue en rojo
if tiempos_restantes["rojo"] > 0:
# Enciende verde auxiliar
led_rojo1.off()
led_verde1.on()
# Mantener 30 segundos
for _ in range(tiempo_verde1):
# Si el principal se sale del rojo → cancelar
if tiempos_restantes["rojo"] <= 0:
break
await asyncio.sleep(1)
# Apagar verde y volver a rojo
led_verde1.off()
led_rojo1.on()
await asyncio.sleep(0.1)
##----------------------------------------------------------------------
async def semaforo_aux_auto2():
led_verde3.off()
led_rojo3.on()
while True:
if tiempos_restantes2["rojo"] <= 0:
# Principal no está en rojo → Auxiliar debe estar en rojo
led_verde3.off()
led_rojo3.on()
await asyncio.sleep(0.1)
continue
if tiempos_restantes2["rojo"] == tiempo_rojo2:
# Inicia ciclo de rojo del principal
await asyncio.sleep(2)
# Si sigue en rojo
if tiempos_restantes2["rojo"] > 0:
# Enciende verde auxiliar
led_rojo3.off()
led_verde3.on()
# Mantener 30 segundos
for _ in range(tiempo_verde3):
# Si el principal se sale del rojo → cancelar
if tiempos_restantes2["rojo"] <= 0:
break
await asyncio.sleep(1)
# Apagar verde y volver a rojo
led_verde3.off()
led_rojo3.on()
await asyncio.sleep(0.1)
##----------------------------------------------------------------------
async def teclado_posicion():
while True:
tecla = await leer_teclado()
if tecla:
print("Tecla presionada:", tecla)
#async def semaforo_auxiliar_solicitado():
async def activar_buzzer():
while True:
if pulsador1.value() == 1:
# Esperar a que AUX1 esté en verde
while not led_verde1.value():
await asyncio.sleep(0.1)
# ================================
# Medir tiempo real disponible en AUX1
# ================================
# El verde dura lo que reste del rojo principal - 2 seg de espera
tiempo_real_disponible = tiempos_restantes["rojo"] - 2
# Si NO alcanza el tiempo para sonar el buzzer → esperar siguiente ciclo
if tiempo_real_disponible < tiempo_buzzer1:
# esperar a que termine el verde actual
while led_verde1.value():
await asyncio.sleep(0.1)
continue
# ================================
# Sí alcanza el tiempo → continuar
# ================================
await asyncio.sleep(2) # espera después de ponerse verde
buzzer1.on()
for _ in range(tiempo_buzzer1):
await asyncio.sleep(1)
buzzer1.off()
await asyncio.sleep(0.05)
async def activar_buzzer2():
while True:
if pulsador2.value() == 1:
# Esperar a que AUX2 esté en verde
while not led_verde3.value():
await asyncio.sleep(0.1)
# Calcular tiempo real disponible
tiempo_real_disponible1 = tiempos_restantes2["rojo"] - 2
# Comparar correctamente con tiempo_buzzer3
if tiempo_real_disponible1 < tiempo_buzzer3:
# Esperar a que termine el verde actual
while led_verde3.value():
await asyncio.sleep(0.1)
continue
# Esperar 2 segundos después de entrar en verde
await asyncio.sleep(2)
# Activar buzzer 2 (buzzer3 en tu código)
buzzer3.on()
for _ in range(tiempo_buzzer3):
await asyncio.sleep(1)
buzzer3.off()
await asyncio.sleep(0.05)
async def pantallas():
global num_pantalla
global inicio
global num
global editar
global desbloqueo
global editand
global avanzar
global cursor_index
global cursor_positions
global retrocede
while True:
tecla = await leer_teclado()
print(str(num_pantalla))
#Muestra pantalla incial menu
if (num_pantalla == 0 and inicio == 0):
inicio=1
LCD.clear()
LCD.move_to(0, 0)
LCD.putstr("Menu config.")
LCD.move_to(15, 0)
LCD.putstr("1")
LCD.move_to(0, 1)
LCD.putstr("Visualizacion.")
LCD.move_to(15, 1)
LCD.putstr("2")
tecla = None
await asyncio.sleep(0.1)
continue
#Muestra pantalla 1 de configuracion
if tecla=="1":
if (inicio==1 and num_pantalla not in (4,5,6)) or (tecla=="subir"and num_pantalla==2) or (tecla=="bajar"and num_pantalla==3):
num_pantalla=1
LCD.clear()
LCD.move_to(0, 0)
LCD.putstr("Semaforo 1")
LCD.move_to(0,1)
LCD.putstr("R:"+str(tiempo_rojo))
LCD.move_to(5, 1)
LCD.putstr("Y:"+str(tiempo_amarillo))
LCD.move_to(10, 1)
LCD.putstr("G:"+str(tiempo_verde))
await asyncio.sleep(0.1)
tecla = None
continue
#Muestra pantalla 1 de visualizacion
if tecla =="2" and inicio==1:
num_pantalla=4
if tecla== "regresar" or retrocede==1:
tecla=None
inicio=0
num_pantalla=0
await asyncio.sleep(0.1)
continue
await asyncio.sleep(0.05)
#
#
# if (tecla == "bajar" and inicio==1 and num_pantalla==1) or ( tecla=="subir" and num_pantalla==3 and inicio==1):
# num_pantalla=2
# LCD.clear()
# LCD.move_to(0, 0)
# LCD.putstr("Semaforo 2")
# LCD.move_to(0,1)
# LCD.putstr("R:"+str(tiempo_rojo2))
# LCD.move_to(5, 1)
# LCD.putstr("Y:"+str(tiempo_amarillo2))
# LCD.move_to(10, 1)
# LCD.putstr("G:"+str(tiempo_verde2))
# tecla = None
# continue
# if (tecla=="bajar" and inicio==1 and num_pantalla==2)or(tecla=="subir" and inicio==1 and num_pantalla==1) :
# num_pantalla=3
# LCD.clear()
# LCD.move_to(0, 0)
# LCD.putstr("Aux1=")
# LCD.move_to(5,0)
# LCD.putstr("R:"+str(tiempo_rojo1))
# LCD.move_to(10,0)
# LCD.putstr("G:"+str(tiempo_verde1))
# LCD.move_to(0, 1)
# LCD.putstr("Aux2=")
# LCD.move_to(5,1)
# LCD.putstr("R:"+str())
# LCD.move_to(10,1)
# LCD.putstr("G:")
# tecla = None
# continue
# #Termina menu configuracion
# #Inicia menu de visualizacion
if (num_pantalla==4) or (tecla=="subir"and num_pantalla==5) or (tecla=="bajar"and num_pantalla==6):
LCD.clear()
LCD.move_to(0, 0)
LCD.putstr("Semaforo 1")
LCD.move_to(0,1)
LCD.putstr("R:")
LCD.move_to(5, 1)
LCD.putstr("Y:"+str(tiempo_amarillo))
LCD.move_to(10, 1)
LCD.putstr("G:"+str(tiempo_verde))
LCD.move_to(15, 0)
LCD.putchar(chr(4))
tecla = None
await asyncio.sleep(0.1)
continue
if (tecla == "bajar" and inicio==1 and num_pantalla==4) or ( tecla=="subir" and num_pantalla==6 and inicio==1):
num_pantalla=5
LCD.clear()
LCD.move_to(0, 0)
LCD.putstr("Semaforo 2")
LCD.move_to(0,1)
LCD.putstr("R:"+str())
LCD.move_to(5, 1)
LCD.putstr("Y:")
LCD.move_to(10, 1)
LCD.putstr("G:")
LCD.move_to(15, 0)
LCD.putchar(chr(4))
tecla = None
continue
if (tecla=="bajar" and inicio==1 and num_pantalla==5)or(tecla=="subir" and inicio==1 and num_pantalla==4) :
num_pantalla=6
LCD.clear()
LCD.move_to(0, 0)
LCD.putstr("Aux1=")
LCD.move_to(5,0)
LCD.putstr("R:"+str(tiempo_rojo1))
LCD.move_to(10,0)
LCD.putstr("G:"+str(tiempo_verde1))
LCD.move_to(0, 1)
LCD.putstr("Aux2=")
LCD.move_to(5,1)
LCD.putstr("R:"+str())
LCD.move_to(10,1)
LCD.putstr("G:")
LCD.move_to(15, 0)
LCD.putchar(chr(4))
tecla = None
continue
# #Termina menu de visualizacion
# #Inicia menu edicion de variables
# #Si se presiona derecha habilita editar
# #Imprime el simbolo de visualizar (ojo)
# =========================
# PROGRAMA PRINCIPAL
# =========================
# Inicia el bucle principal
#asyncio.run(main())
async def main():
await asyncio.gather(
semaforo_principal(),
color_amarillo(),
semaforo_aux_auto1(),
semaforo_principal2(),
color_amarillo2(),
semaforo_aux_auto2(),
pantallas(),
activar_buzzer(),
activar_buzzer2()
)
# Inicia el bucle principal
asyncio.run(main())<
>
^
v
ATRAS
ENTER