# SolarFlow - Estacao Inteligente de Recarga GoodWe
# Loop principal: botoes, maquina de estados, atuadores, display e log.
import time
import config
from sensores import SensorSolar, SensorSOC, Botao
from relogio import RelogioSimulado
from ponto_recarga import PontoRecarga
from atuadores import (SaidaPonto, IndicadorOrigem, Buzzer, piscar,
SOM_CONECTAR, SOM_DESCONECTAR, SOM_COMPLETO,
SOM_MODO, SOM_EMERGENCIA, SOM_RESET)
from display import Painel
# ================= Inicializacao =================
solar = SensorSolar(config.PIN_LDR)
sensor_soc = {"A": SensorSOC(config.PIN_POT_A), "B": SensorSOC(config.PIN_POT_B)}
btn_emergencia = Botao(config.PIN_BTN_EMERG)
btn_modo = Botao(config.PIN_BTN_MODO)
btn_ponto = {"A": Botao(config.PIN_BTN_A), "B": Botao(config.PIN_BTN_B)}
pontos = {"A": PontoRecarga("A"), "B": PontoRecarga("B")}
saidas = {
"A": SaidaPonto(config.PIN_LED_A, config.PIN_RELE_A),
"B": SaidaPonto(config.PIN_LED_B, config.PIN_RELE_B),
}
origem = IndicadorOrigem()
buzzer = Buzzer(config.PIN_BUZZER)
relogio = RelogioSimulado()
painel = Painel()
modo_eco = False
emergencia = False
total_kw = 0.0
atualizar_agora = False # forca o redesenho imediato apos um clique
def log(mensagem):
print("[{}] {}".format(relogio.texto(), mensagem))
def alocar_potencia(pontos):
"""PROVISORIO (Bloco 2): cada ponto ativo recebe a potencia maxima.
No Bloco 3 esta funcao sera substituida pelo gestor de energia
(solar -> bateria -> rede) e pelo algoritmo de divisao proporcional.
"""
alocacao = {}
for nome, p in pontos.items():
alocacao[nome] = config.PONTO_POTENCIA_MAX_KW if p.quer_energia() else 0.0
return alocacao
log("SolarFlow iniciado - estacao disponivel")
ultimo_ciclo = time.ticks_ms()
# ================= Loop principal =================
while True:
# ---- 1. Botoes (verificados a cada 20 ms) ----
if btn_emergencia.foi_pressionado():
atualizar_agora = True
emergencia = not emergencia
if emergencia:
for p in pontos.values():
p.entrar_emergencia()
buzzer.tocar(*SOM_EMERGENCIA)
log("EMERGENCIA ACIONADA - recarga interrompida nos dois pontos")
else:
for p in pontos.values():
p.resetar()
buzzer.tocar(*SOM_RESET)
log("Emergencia resetada - reconecte os veiculos")
if btn_modo.foi_pressionado() and not emergencia:
atualizar_agora = True
modo_eco = not modo_eco
buzzer.tocar(*SOM_MODO)
log("Modo " + ("ECO" if modo_eco else "NORMAL"))
for nome, botao in btn_ponto.items():
if botao.foi_pressionado() and not emergencia:
atualizar_agora = True
p = pontos[nome]
evento = p.botao(sensor_soc[nome].ler())
if evento == "conectado":
buzzer.tocar(*SOM_CONECTAR)
log("Ponto {}: veiculo conectado (SOC {:.0f}%)".format(nome, p.soc))
elif evento == "ja_completo":
buzzer.tocar(*SOM_COMPLETO)
log("Ponto {}: veiculo ja esta acima do alvo (SOC {:.0f}%)".format(nome, p.soc))
elif evento == "desconectado":
buzzer.tocar(*SOM_DESCONECTAR)
log("Ponto {}: veiculo desconectado ({:.2f} kWh entregues)".format(
nome, p.energia_sessao_kwh))
# ---- 2. Ciclo da simulacao (a cada CICLO_MS) ----
agora = time.ticks_ms()
if atualizar_agora or time.ticks_diff(agora, ultimo_ciclo) >= config.CICLO_MS:
atualizar_agora = False
ultimo_ciclo = agora
dt_h = relogio.avancar()
solar.ler()
alocacao = alocar_potencia(pontos)
for nome, p in pontos.items():
if p.atualizar(alocacao[nome], dt_h) == "completo":
buzzer.tocar(*SOM_COMPLETO)
log("Ponto {}: recarga completa (SOC {:.0f}%, {:.2f} kWh entregues)".format(
nome, p.soc, p.energia_sessao_kwh))
total_kw = sum(p.potencia_kw for p in pontos.values())
painel.desenhar(relogio.texto(), relogio.em_ponta(), modo_eco,
solar.potencia_kw, pontos, total_kw, emergencia)
# ---- 3. Saidas (a cada 20 ms, para os LEDs piscarem) ----
for nome, saida in saidas.items():
saida.aplicar(pontos[nome].estado)
if emergencia:
origem.aplicar(False, False, piscar(250)) # LED vermelho piscando
else:
# PROVISORIO (Bloco 2): sem gestor de energia, toda recarga vem da rede.
# No Bloco 3 os LEDs passam a mostrar a origem real (sol, bateria, rede).
origem.aplicar(False, False, total_kw > 0)
buzzer.atualizar()
time.sleep_ms(20)