from machine import Pin, I2C
from lcd_i2c import LCD
import time
import ustruct
# Configuración de pines SDA y SCL para I2C
sda = Pin(21, Pin.OUT)
scl = Pin(22, Pin.OUT)
NUM_ROWS = 2
NUM_COLS = 16
i2c = I2C(0, sda=sda, scl=scl, freq=400000)
lcd_addr = i2c.scan()[0]
lcd = LCD(addr=lcd_addr, cols=NUM_COLS, rows=NUM_ROWS, i2c=i2c)
lcd.begin()
lcd.print("CODERE")
# Pines
pin_red = Pin(4, Pin.IN, Pin.PULL_DOWN)
pin_grupo2 = Pin(18, Pin.IN, Pin.PULL_DOWN) # antes grupo1
pin_confirmacion_red = Pin(5, Pin.IN, Pin.PULL_DOWN)
pin_grupo3 = Pin(32, Pin.IN, Pin.PULL_DOWN) # antes grupo2
boton_tiempo = Pin(23, Pin.IN, Pin.PULL_DOWN)
pin_relay_general = Pin(19, Pin.OUT)
salida_red_abrir = Pin(27, Pin.OUT)
salida_red_cerrar = Pin(13, Pin.OUT)
salida_grupo2_abrir = Pin(14, Pin.OUT) # antes grupo1
salida_grupo2_cerrar = Pin(15, Pin.OUT) # antes grupo1
salida_grupo3_abrir = Pin(25, Pin.OUT) # antes grupo2
salida_grupo3_cerrar = Pin(26, Pin.OUT) # antes grupo2
ultima_pantalla = ("", "")
estado_actual = "RED"
grupo_actual = None
tiempo_inicio_grupo = None
tiempo_fin_grupo = None
ultimos_cortes = []
mostrar_temporal = False
tiempo_mostrar_temporal = 0
# Funciones auxiliares
def mostrar_en_lcd(linea1, linea2=""):
global ultima_pantalla
lcd.clear()
lcd.print(linea1[:16])
lcd.set_cursor(0, 1)
lcd.print(linea2[:16])
ultima_pantalla = (linea1, linea2)
def cuenta_regresiva(mensaje, segundos=15):
for i in range(segundos, 0, -1):
lcd.clear()
lcd.print(mensaje[:16])
lcd.set_cursor(0, 1)
lcd.print(f"{i} segundos")
time.sleep(1)
def abrir_interruptor(pin):
pin.on()
time.sleep(5)
pin.off()
def cerrar_interruptor(pin):
pin.on()
time.sleep(5)
pin.off()
def transferir_a_grupo(grupo_num):
global tiempo_inicio_grupo, grupo_actual
mostrar_en_lcd(f"Transf. a G{grupo_num}", "Ejecutando...")
abrir_interruptor(salida_red_abrir)
time.sleep(1)
if grupo_num == 2:
cerrar_interruptor(salida_grupo2_cerrar)
else:
cerrar_interruptor(salida_grupo3_cerrar)
grupo_actual = grupo_num
tiempo_inicio_grupo = time.time()
mostrar_en_lcd(f"G{grupo_num} activo", "Energía estable")
def transferir_a_red():
global tiempo_fin_grupo, grupo_actual
mostrar_en_lcd("Transf. a RED", "Ejecutando...")
if grupo_actual == 2:
abrir_interruptor(salida_grupo2_abrir)
elif grupo_actual == 3:
abrir_interruptor(salida_grupo3_abrir)
time.sleep(1)
cerrar_interruptor(salida_red_cerrar)
tiempo_fin_grupo = time.time()
duracion = int(tiempo_fin_grupo - tiempo_inicio_grupo) if tiempo_inicio_grupo else 0
ultimos_cortes.insert(0, (grupo_actual, duracion))
if len(ultimos_cortes) > 5:
ultimos_cortes.pop()
grupo_actual = None
mostrar_en_lcd("Fuente: RED", "Energía estable")
def calcular_tiempo_actual():
if tiempo_inicio_grupo is None:
return "Tiempo en G", "0h 0m 0s"
tiempo_actual = time.time()
tiempo_total = int(tiempo_actual - tiempo_inicio_grupo)
horas = tiempo_total // 3600
minutos = (tiempo_total % 3600) // 60
segundos = tiempo_total % 60
return f"G{grupo_actual} activo", f"{horas}h {minutos}m {segundos}s"
def mostrar_cortes():
if not ultimos_cortes:
mostrar_en_lcd("Sin mediciones", "anteriores")
time.sleep(2)
return
for i, (grupo, dur) in enumerate(ultimos_cortes[:5], 1):
h = dur // 3600
m = (dur % 3600) // 60
s = dur % 60
mensaje = f"Corte {i} G{grupo}"
duracion = f"{h}h{m}m{s}s"
mostrar_en_lcd(mensaje, duracion)
time.sleep(3)
def abrir_grupo_actual():
if grupo_actual == 2:
abrir_interruptor(salida_grupo2_abrir)
elif grupo_actual == 3:
abrir_interruptor(salida_grupo3_abrir)
def funcion_inicializar():
mostrar_en_lcd("Inicializando...")
pin_relay_general.on()
abrir_interruptor(salida_grupo2_abrir)
abrir_interruptor(salida_grupo3_abrir)
cerrar_interruptor(salida_red_cerrar)
mostrar_en_lcd("Fuente: RED", "Energía estable")
# Inicio
funcion_inicializar()
while True:
red = pin_red.value()
g2 = pin_grupo2.value()
g3 = pin_grupo3.value()
confirm_red = pin_confirmacion_red.value()
# Botón presionado: mostrar cortes
if boton_tiempo.value() == 1:
mostrar_temporal = True
tiempo_mostrar_temporal = time.time()
mostrar_cortes()
continue
# Si se debe volver a pantalla principal después de mostrar cortes
if mostrar_temporal:
if time.time() - tiempo_mostrar_temporal >= 10:
mostrar_temporal = False
if estado_actual == "GRUPO":
mensaje1, mensaje2 = calcular_tiempo_actual()
mostrar_en_lcd(mensaje1, mensaje2)
else:
mostrar_en_lcd("Fuente: RED", "Energía estable")
continue
# Si estaba con GRUPO y se apagó
if estado_actual == "GRUPO":
if grupo_actual == 2 and g2 == 0:
abrir_grupo_actual()
if g3 == 1:
cuenta_regresiva("Transf. a G3", 15)
transferir_a_grupo(3)
else:
mostrar_en_lcd("G2 apagado", "Buscando grupo...")
while g2 == 0 and red == 0:
g2 = pin_grupo2.value()
red = pin_red.value()
time.sleep(1)
if red == 1 and confirm_red == 1:
cuenta_regresiva("Transf. a RED", 15)
transferir_a_red()
estado_actual = "RED"
elif g2 == 1:
cuenta_regresiva("Transf. a G2", 15)
transferir_a_grupo(2)
elif grupo_actual == 3 and g3 == 0:
abrir_grupo_actual()
if g2 == 1:
cuenta_regresiva("Transf. a G2", 15)
transferir_a_grupo(2)
else:
mostrar_en_lcd("G3 apagado", "Buscando grupo...")
while g3 == 0 and red == 0:
g3 = pin_grupo3.value()
red = pin_red.value()
time.sleep(1)
if red == 1 and confirm_red == 1:
cuenta_regresiva("Transf. a RED", 15)
transferir_a_red()
estado_actual = "RED"
elif g3 == 1:
cuenta_regresiva("Transf. a G3", 15)
transferir_a_grupo(3)
# Corte de red
elif estado_actual == "RED" and red == 0:
mostrar_en_lcd("Corte de RED", "Verificando grupos")
for _ in range(10):
if g2 == 1 or g3 == 1:
break
time.sleep(1)
g2 = pin_grupo2.value()
g3 = pin_grupo3.value()
if g2 == 1:
cuenta_regresiva("Transf. a G2", 15)
transferir_a_grupo(2)
estado_actual = "GRUPO"
elif g3 == 1:
cuenta_regresiva("Transf. a G3", 15)
transferir_a_grupo(3)
estado_actual = "GRUPO"
else:
mostrar_en_lcd("Sin grupos listos", "Esperando...")
while red == 0:
g2 = pin_grupo2.value()
g3 = pin_grupo3.value()
red = pin_red.value()
if g2 == 1 or g3 == 1:
break
time.sleep(1)
if g2 == 1:
cuenta_regresiva("Transf. a G2", 15)
transferir_a_grupo(2)
estado_actual = "GRUPO"
elif g3 == 1:
cuenta_regresiva("Transf. a G3", 15)
transferir_a_grupo(3)
estado_actual = "GRUPO"
# Red vuelve mientras GRUPO activo
if estado_actual == "GRUPO" and red == 1 and confirm_red == 1:
cuenta_regresiva("Transf. a RED", 15)
transferir_a_red()
estado_actual = "RED"
mostrar_en_lcd("Fuente: RED", "Apaga el G")
# Mensaje de grupo apagado luego de volver red
if estado_actual == "RED" and ultima_pantalla == ("Fuente: RED", "Apaga el G"):
if pin_grupo2.value() == 0 and pin_grupo3.value() == 0:
mostrar_en_lcd("Fuente: RED", "Red normalizada")
# Mostrar tiempo actual del grupo si está en GRUPO
if estado_actual == "GRUPO" and not mostrar_temporal:
mensaje1, mensaje2 = calcular_tiempo_actual()
mostrar_en_lcd(mensaje1, mensaje2)
time.sleep(1)