from machine import Pin, I2C, ADC
from time import sleep, sleep_ms
from pico_i2c_lcd import I2cLcd
import math
import random
import ds1307
TECLA_ARRIBA = const(0)
TECLA_ABAJO = const(1)
cancelar = 0
hora_apertura = "0800"
hora_cierre = "2200"
band=0
band2=0
#LCD
i2c = I2C(0, sda=Pin(16), scl=Pin(17), freq=400000)
lcd = I2cLcd(i2c,0x27 , 4, 20)
lcd.move_to(0, 1)
lcd.putstr("hora de cierre: ")
lcd.putstr(str(hora_cierre))
# Menú predeterminado
def menu():
print("fede")
#Definiciones ldr
ldr = ADC(27)
MAX_ADC_READING = 65535
ADC_REF_VOLTAGE = 3.3
REF_RESISTANCE = 50
caso_comp = 5
hora = 0
#Motores
# Configurar los pines como salida para los motores
motor1_dir = Pin(2, Pin.OUT) # Dirección del motor 1 (cortina clara)
motor1_step = Pin(3, Pin.OUT) # Pasos del motor 1
motor2_dir = Pin(4, Pin.OUT) # Dirección del motor 2 (cortina oscura)
motor2_step = Pin(5, Pin.OUT) # Pasos del motor 2
motor3_dir = Pin(6, Pin.OUT) #Dirección de motor 3 (Persiana)
motor3_step = Pin(7, Pin.OUT) #Pasos del motor 3
def setup():
# Inicializar los pines
motor1_dir.off()
motor1_step.off()
motor2_dir.off()
motor2_step.off()
motor3_dir.off()
motor3_step.off()
def move_motor(motor_dir, motor_step, steps, direction, delay=10):
"""
Controla un motor paso a paso.
:param motor_dir: Pin de dirección del motor.
:param motor_step: Pin de pasos del motor.
:param steps: Número de pasos a mover.
:param direction: Dirección del motor (True para abrir, False para cerrar).
:param delay: Tiempo en milisegundos entre pasos.
"""
motor_dir.value(direction) # Establecer dirección
for _ in range(steps):
motor_step.on()
sleep_ms(1) # Pulso de paso
motor_step.off()
sleep_ms(delay)
#RTC
i2c_rtc = I2C(0, scl=Pin(1), sda=Pin(0), freq=100000)
# I2C object
# creating an DS1307 RTC object using I2C
ds1307rtc = ds1307.DS1307(i2c_rtc, 0x68)
#Teclado
teclas = [['1', '2', '3', 'A'],
['4', '5', '6', 'B'],
['7', '8', '9', 'C'],
['*', '0', '#', 'D']]
# Pines del GPIO
filas = [15, 14, 13, 12]
columnas = [11, 10, 9, 8]
# Define los pines de filas como salidas
fila_pines = [Pin(nombre_pin, mode=Pin.OUT) for nombre_pin in filas]
# Define los pines de columnas como entradas
columna_pines = [Pin(nombre_pin, mode=Pin.IN, pull=Pin.PULL_DOWN) for nombre_pin in columnas]
def init():
for fila in range(4):
fila_pines[fila].low()
# Define todas las columnas bajo -low-
init()
def scan(fila, columna):
""" Escanea todo el teclado """
# Define la columna actual en alto -high-
fila_pines[fila].high()
tecla = None
# Verifica si hay teclas presionadas
if columna_pines[columna].value() == TECLA_ABAJO:
tecla = TECLA_ABAJO
if columna_pines[columna].value() == TECLA_ARRIBA:
tecla = TECLA_ARRIBA
fila_pines[fila].low()
# Devuelve el estado de la tecla
return tecla
#Minutos dentro del rango
def validar_minutos(horario):
""" Verifica que los minutos estén en el rango válido (00-59). """
minutos = int(horario[-2:])
if 0 <= minutos <= 59:
return True
return False
#Cambio de horario
def cambio():
global cancelar
cancelar = 0
entrada = "" # Limpia la entrada al iniciar
sleep(0.5) # Espera breve para evitar capturar entradas previas
while cancelar == 0:
for fila in range(4):
for columna in range(4):
tecla = scan(fila, columna)
if tecla == TECLA_ABAJO:
ultima_tecla_presionada = teclas[fila][columna]
if ultima_tecla_presionada in ["A", "B", "C"]:
num = ultima_tecla_presionada
else:
entrada += ultima_tecla_presionada
num = ultima_tecla_presionada
if num not in ["A", "B"] and len(entrada) != 4:
print("Horario: ", entrada)
sleep(0.3)
if num == "A" or len(entrada) > 3:
if entrada.isdigit() and int(entrada) < 2400 and validar_minutos(entrada) and len(entrada) == 4:
print("Horario actualizado.")
return entrada
else:
print("Horario no permitido. Ingrese nuevamente.")
entrada = ""
sleep(0.3)
if num == "B":
entrada = ""
sleep(0.3)
if num == "C":
cancelar = 1
entrada = ""
sleep(0.3)
#Obtener horario
def get_date_string():
dt = ds1307rtc.datetime
return str(dt[2]) + "." + str(dt[1]) + "." + str(dt[0])
def get_time_string():
dt = ds1307rtc.datetime
return f"{dt[3]:02}:{dt[4]:02}" # Formatea con ceros iniciales
#return str(dt[3]) + ":" + str(dt[4])
#Comparar horarios
def comparar_horarios(hora_cierre, hora_apertura):
# Obtener hora y minutos actuales del RTC
dt = ds1307rtc.datetime
hora_actual = dt[3]
minutos_actuales = dt[4]
# Convertir el horario guardado en horas y minutos
hora_ap = int(hora_apertura[:2])
minutos_ap = int(hora_apertura[2:])
hora_ci = int(hora_cierre[:2])
minutos_ci = int(hora_cierre[2:])
# Comparar horarios de apertura
if (hora_actual > hora_ap) or (hora_actual == hora_ap and minutos_actuales >= minutos_ap):
apertura_estado = True # Horario actual está dentro o después del horario de apertura
else:
apertura_estado = False
# Comparar horarios de cierre
if (hora_actual < hora_ci) or (hora_actual == hora_ci and minutos_actuales < minutos_ci):
cierre_estado = False # Horario actual está antes del horario de cierre
else:
cierre_estado = True
if apertura_estado and not cierre_estado:
return 0
else:
return 1
#Valor ldr
def valor_ldr(ldrResistance, caso_comp, hora):
if hora == 0:
# Persiana abierta
if ldrResistance < 775:
# No hace nada
return 0
elif 775 <= ldrResistance < 2400:
# Cierra cortina clara
return 1
elif ldrResistance >= 2400:
# Cierra cortina oscura
return 2
else:
# Cierra persiana (((((((((((No se usa)))))))))))
return 3
def main():
global hora_cierre, hora_apertura, hora, caso_comp, band, band2
menu()
while True:
#print("\n")
print(get_time_string())
#hora: indica si es horario de cierre o apertura
hora = comparar_horarios(hora_cierre, hora_apertura)
#Lecturas del ldr
rawData = ldr.read_u16()
resistorVoltage = rawData / MAX_ADC_READING * ADC_REF_VOLTAGE
ldrVoltage = ADC_REF_VOLTAGE - resistorVoltage
ldrResistance = ldrVoltage / resistorVoltage * REF_RESISTANCE
print(f"LDR resistance: {ldrResistance}")
#funcion de ldr. De acá sale el valor que controlará que cortina se cierra.
caso = valor_ldr(ldrResistance, caso_comp, hora)
caso_comp = caso
print(caso)
print(hora)
#print(hora)
sleep(1)
'''TECLADO'''
for fila in range(4):
for columna in range(4):
opcion = scan(fila, columna)
if opcion == TECLA_ABAJO:
opcion_presionada = teclas[fila][columna]
sleep(0.5) # Espera para evitar capturar el número del menú en el horario
if opcion_presionada == '1':
print("Ingrese nuevo horario de cierre:")
hora_cierre = cambio()
menu()
sleep(5)
elif opcion_presionada == '2':
print("Ingrese nuevo horario de apertura:")
hora_apertura = cambio()
menu()
sleep(5)
#Control motores
'''PERSIANA'''
if (hora==0) and (band==0): #Abrir la persiana
band=1
print("Abriendo persiana.")
move_motor(motor3_dir, motor3_step, steps=200, direction=True)
if (hora==1) and (band==1): #Cierra la persiana
band=0
print("Cerrando persiana.")
move_motor(motor3_dir, motor3_step, steps=200, direction=False)
'''CORTINAS'''
if (caso==0) and (band2==0): #Abre las 2 cortinas
band2=1
print("Abriendo cortina clara.")
move_motor(motor1_dir, motor1_step, steps=200, direction=True)
#led_clara.value(1)
print("Abriendo cortina oscura.")
move_motor(motor2_dir, motor2_step, steps=200, direction=True)
#led_oscura.value(1)
if (caso==1) and (band2==1): #Cierra cortina clara
band2=2
print("Cerrando cortina clara.")
move_motor(motor1_dir, motor1_step, steps=200, direction=False)
#led_clara.value(0)
if (caso==2) and (band2==2 or band2==1): #Cierra cortina oscura
if (band2==1):
band2=0
print("Cerrando cortina clara.")
move_motor(motor1_dir, motor1_step, steps=200, direction=False)
#led_clara.value(0)
print("Cerrando cortina oscura.")
move_motor(motor2_dir, motor2_step, steps=200, direction=False)
#led_oscura.value(0)
if (band2==2):
band2=0
print("Cerrando cortina oscura.")
move_motor(motor2_dir, motor2_step, steps=200, direction=False)
#led_oscura.value(0)
if (caso==1) and (band2==0): #Abriendo cortina oscura
band2=3
print("Abriendo cortina oscura.")
move_motor(motor2_dir, motor2_step, steps=200, direction=True)
#led_oscura.value(1)
if (caso==0) and (band2==3 or band2==2): #Abriendo cortina clara
band2=1
print("Abriendo cortina clara.")
move_motor(motor1_dir, motor1_step, steps=200, direction=True)
#led_clara.value(1)
if __name__ == "__main__":
main()