from machine import Pin, PWM, I2C
from time import sleep, sleep_ms
# ==========================================
# CONFIGURACION DE HARDWARE
# ==========================================
# LCD I2C
i2c = I2C(
0,
scl=Pin(1),
sda=Pin(0),
freq=400000
)
# Buscar direccion I2C del LCD
dispositivos = i2c.scan()
if len(dispositivos) > 0:
LCD_ADDR = dispositivos[0]
else:
LCD_ADDR = 0x27
# Teclado matricial
rows = [
Pin(2, Pin.OUT),
Pin(3, Pin.OUT),
Pin(4, Pin.OUT),
Pin(5, Pin.OUT)
]
cols = [
Pin(6, Pin.IN, Pin.PULL_DOWN),
Pin(7, Pin.IN, Pin.PULL_DOWN),
Pin(8, Pin.IN, Pin.PULL_DOWN),
Pin(9, Pin.IN, Pin.PULL_DOWN)
]
keys = [
["1", "2", "3", "A"],
["4", "5", "6", "B"],
["7", "8", "9", "C"],
["*", "0", "#", "D"]
]
# LEDs
led_verde = Pin(16, Pin.OUT)
led_rojo = Pin(17, Pin.OUT)
# Servomotor
servo = PWM(Pin(15))
servo.freq(50)
# ==========================================
# FUNCIONES DEL LCD I2C
# ==========================================
LCD_BACKLIGHT = 0x08
LCD_ENABLE = 0x04
LCD_RS = 0x01
def lcd_write_byte(data):
i2c.writeto(LCD_ADDR, bytes([data]))
def lcd_pulse(data):
lcd_write_byte(data | LCD_ENABLE | LCD_BACKLIGHT)
sleep_ms(1)
lcd_write_byte(
(data & ~LCD_ENABLE) | LCD_BACKLIGHT
)
def lcd_send(value, mode):
high = value & 0xF0
low = (value << 4) & 0xF0
lcd_pulse(high | mode)
lcd_pulse(low | mode)
def lcd_command(command):
lcd_send(command, 0)
def lcd_data(data):
lcd_send(data, LCD_RS)
def lcd_init():
sleep_ms(50)
lcd_pulse(0x30)
sleep_ms(5)
lcd_pulse(0x30)
sleep_ms(1)
lcd_pulse(0x30)
lcd_pulse(0x20)
lcd_command(0x28)
lcd_command(0x0C)
lcd_command(0x06)
lcd_command(0x01)
sleep_ms(5)
def lcd_clear():
lcd_command(0x01)
sleep_ms(2)
def lcd_print(texto, fila=0):
if fila == 0:
lcd_command(0x80)
else:
lcd_command(0xC0)
texto = str(texto)
# Limitar el texto a 16 caracteres
texto = texto[:16]
# Completar con espacios hasta 16 caracteres
while len(texto) < 16:
texto += " "
# Enviar cada caracter al LCD
for caracter in texto:
lcd_data(ord(caracter))
def lcd_mensaje(linea1, linea2=""):
lcd_clear()
lcd_print(linea1, 0)
lcd_print(linea2, 1)
# ==========================================
# CONTROL DEL SERVOMOTOR
# ==========================================
def mover_servo(angulo):
pulso = int(1000 + (angulo / 180) * 1000)
servo.duty_ns(pulso * 1000)
def cerrar_cerradura():
mover_servo(0)
def abrir_cerradura():
mover_servo(90)
# ==========================================
# LECTURA DEL TECLADO
# ==========================================
def leer_teclado():
for fila in range(4):
rows[fila].value(1)
for columna in range(4):
if cols[columna].value():
tecla = keys[fila][columna]
# Esperar que se suelte
while cols[columna].value():
sleep_ms(10)
rows[fila].value(0)
# Antirrebote
sleep_ms(50)
return tecla
rows[fila].value(0)
return None
# ==========================================
# INGRESO DE CONTRASENA
# ==========================================
def ingresar_password(mensaje):
ingresada = ""
lcd_mensaje(mensaje, "Clave: ")
while True:
tecla = leer_teclado()
if tecla is None:
sleep_ms(30)
continue
# Confirmar
if tecla == "#":
return ingresada
# Borrar
elif tecla == "*":
ingresada = ""
lcd_mensaje(mensaje, "Clave: ")
# Aceptar solamente numeros
elif tecla.isdigit():
if len(ingresada) < 4:
ingresada += tecla
# Mostrar asteriscos
lcd_mensaje(
mensaje,
"*" * len(ingresada)
)
# ==========================================
# FASE 1: CONFIGURACION INICIAL
# ==========================================
def configurar_password():
while True:
lcd_mensaje("Bienvenido", "Cerradura")
sleep(2)
# Primera contraseña
primera = ingresar_password(
"Nueva clave"
)
# Confirmacion
segunda = ingresar_password(
"Repita clave"
)
lcd_mensaje(
"Cargando",
"contrasena..."
)
sleep(2)
# Verificar coincidencia
if primera == segunda and len(primera) == 4:
password = primera
lcd_mensaje(
"Carga exitosa",
"Clave guardada"
)
print("Contrasena configurada")
sleep(2)
# Festejo de LEDs
festejo()
return password
else:
lcd_mensaje(
"Carga denegada",
"Intente otra vez"
)
sleep(2)
# ==========================================
# FASE 2: FESTEJO
# ==========================================
def festejo():
inicio = time_ms()
while time_ms() - inicio < 2000:
led_verde.value(1)
led_rojo.value(0)
sleep_ms(100)
led_verde.value(0)
led_rojo.value(1)
sleep_ms(100)
led_verde.value(0)
led_rojo.value(0)
# ==========================================
# FASE 3: ACCESO NORMAL
# ==========================================
def acceso(password):
while True:
ingresada = ingresar_password(
"Ingrese clave"
)
if ingresada == password:
lcd_mensaje(
"Acceso autorizado",
"Abriendo..."
)
led_verde.value(1)
led_rojo.value(0)
abrir_cerradura()
sleep(3)
cerrar_cerradura()
led_verde.value(0)
lcd_mensaje(
"Cerradura",
"bloqueada"
)
sleep(2)
else:
lcd_mensaje(
"Acceso denegado",
"Clave incorrecta"
)
led_rojo.value(1)
sleep(2)
led_rojo.value(0)
# ==========================================
# PROGRAMA PRINCIPAL
# ==========================================
from time import ticks_ms as time_ms
lcd_init()
led_verde.value(0)
led_rojo.value(0)
cerrar_cerradura()
print("Sistema iniciado")
# Configuracion de contraseña
password_guardada = configurar_password()
# Funcionamiento normal
acceso(password_guardada)