new module
This commit is contained in:
@@ -20,94 +20,108 @@ static const char *TAG = "evse_fsm";
|
||||
static bool c1_d1_waiting = false;
|
||||
static TickType_t c1_d1_relay_to = 0;
|
||||
|
||||
void evse_fsm_reset(void) {
|
||||
void evse_fsm_reset(void)
|
||||
{
|
||||
evse_set_state(EVSE_STATE_A);
|
||||
c1_d1_waiting = false;
|
||||
c1_d1_relay_to = 0;
|
||||
}
|
||||
|
||||
// ... includes e defines como já estão
|
||||
|
||||
static void update_outputs(evse_state_t state) {
|
||||
static void update_outputs(evse_state_t state)
|
||||
{
|
||||
const uint16_t current = evse_get_runtime_charging_current();
|
||||
uint8_t cable_max_current = evse_get_max_charging_current();
|
||||
const bool socket_outlet = evse_get_socket_outlet();
|
||||
|
||||
if (socket_outlet) {
|
||||
if (socket_outlet)
|
||||
{
|
||||
cable_max_current = proximity_get_max_current();
|
||||
}
|
||||
|
||||
// Segurança: relé sempre off e outputs seguros em caso de erro
|
||||
if (evse_get_error() != 0) {
|
||||
if (ac_relay_get_state()) {
|
||||
if (evse_get_error() != 0)
|
||||
{
|
||||
if (ac_relay_get_state())
|
||||
{
|
||||
ac_relay_set_state(false);
|
||||
ESP_LOGW(TAG, "ERRO ativo: relé estava ligado, agora desligado por segurança!");
|
||||
}
|
||||
ac_relay_set_state(false); // redundância tolerável
|
||||
pilot_set_level(true); // sinal pilot sempre 12V (A)
|
||||
if (board_config.socket_lock && socket_outlet) {
|
||||
ac_relay_set_state(false);
|
||||
pilot_set_level(true);
|
||||
if (board_config.socket_lock && socket_outlet)
|
||||
{
|
||||
socket_lock_set_locked(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Fluxo normal
|
||||
switch (state) {
|
||||
case EVSE_STATE_A:
|
||||
case EVSE_STATE_E:
|
||||
case EVSE_STATE_F:
|
||||
ac_relay_set_state(false);
|
||||
pilot_set_level(state == EVSE_STATE_A);
|
||||
if (board_config.socket_lock && socket_outlet) {
|
||||
socket_lock_set_locked(false);
|
||||
}
|
||||
break;
|
||||
|
||||
case EVSE_STATE_B1:
|
||||
pilot_set_level(true);
|
||||
ac_relay_set_state(false);
|
||||
if (board_config.socket_lock && socket_outlet) {
|
||||
socket_lock_set_locked(true);
|
||||
}
|
||||
|
||||
if (rcm_test()) {
|
||||
//ESP_LOGI(TAG, "RCM self test passed");
|
||||
} else {
|
||||
//ESP_LOGW(TAG, "RCM self test failed");
|
||||
}
|
||||
break;
|
||||
|
||||
case EVSE_STATE_B2:
|
||||
pilot_set_amps(MIN(current, cable_max_current));
|
||||
ac_relay_set_state(false);
|
||||
break;
|
||||
|
||||
case EVSE_STATE_C1:
|
||||
case EVSE_STATE_D1: {
|
||||
pilot_set_amps(MIN(current, cable_max_current)); // mantém PWM
|
||||
ac_relay_set_state(false); // relé ainda desligado
|
||||
c1_d1_waiting = true;
|
||||
c1_d1_relay_to = xTaskGetTickCount() + pdMS_TO_TICKS(6000);
|
||||
break;
|
||||
switch (state)
|
||||
{
|
||||
case EVSE_STATE_A:
|
||||
case EVSE_STATE_E:
|
||||
case EVSE_STATE_F:
|
||||
ac_relay_set_state(false);
|
||||
pilot_set_level(state == EVSE_STATE_A);
|
||||
if (board_config.socket_lock && socket_outlet)
|
||||
{
|
||||
socket_lock_set_locked(false);
|
||||
}
|
||||
case EVSE_STATE_C2:
|
||||
case EVSE_STATE_D2:
|
||||
pilot_set_amps(MIN(current, cable_max_current));
|
||||
ac_relay_set_state(true); // Só chega aqui se não há erro!
|
||||
break;
|
||||
break;
|
||||
|
||||
case EVSE_STATE_B1:
|
||||
pilot_set_level(true);
|
||||
ac_relay_set_state(false);
|
||||
if (board_config.socket_lock && socket_outlet)
|
||||
{
|
||||
socket_lock_set_locked(true);
|
||||
}
|
||||
|
||||
if (rcm_test())
|
||||
{
|
||||
// ESP_LOGI(TAG, "RCM self test passed");
|
||||
}
|
||||
else
|
||||
{
|
||||
// ESP_LOGW(TAG, "RCM self test failed");
|
||||
}
|
||||
break;
|
||||
|
||||
case EVSE_STATE_B2:
|
||||
pilot_set_amps(MIN(current, cable_max_current));
|
||||
ac_relay_set_state(false);
|
||||
break;
|
||||
|
||||
case EVSE_STATE_C1:
|
||||
case EVSE_STATE_D1:
|
||||
{
|
||||
pilot_set_amps(MIN(current, cable_max_current));
|
||||
ac_relay_set_state(false);
|
||||
c1_d1_waiting = true;
|
||||
c1_d1_relay_to = xTaskGetTickCount() + pdMS_TO_TICKS(6000);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVSE_STATE_C2:
|
||||
case EVSE_STATE_D2:
|
||||
pilot_set_amps(MIN(current, cable_max_current));
|
||||
ac_relay_set_state(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// FSM principal - centraliza a lógica de erro e de todos os estados
|
||||
// FSM principal
|
||||
void evse_fsm_process(
|
||||
pilot_voltage_t pilot_voltage,
|
||||
bool authorized,
|
||||
bool available,
|
||||
bool enabled
|
||||
) {
|
||||
bool enabled)
|
||||
{
|
||||
// Proteção total: erro força F sempre!
|
||||
if (evse_get_error() != 0) {
|
||||
if (evse_get_state() != EVSE_STATE_F) {
|
||||
if (evse_get_error() != 0)
|
||||
{
|
||||
if (evse_get_state() != EVSE_STATE_F)
|
||||
{
|
||||
ESP_LOGW(TAG, "Erro ativo detectado: forçando estado FAULT (F)");
|
||||
evse_set_state(EVSE_STATE_F);
|
||||
}
|
||||
@@ -119,91 +133,97 @@ void evse_fsm_process(
|
||||
evse_state_t prev = evse_get_state();
|
||||
evse_state_t curr = prev;
|
||||
|
||||
switch (curr) {
|
||||
case EVSE_STATE_A:
|
||||
if (!available) {
|
||||
evse_set_state(EVSE_STATE_F);
|
||||
} else if (pilot_voltage == PILOT_VOLTAGE_9) {
|
||||
evse_set_state(EVSE_STATE_B1);
|
||||
}
|
||||
break;
|
||||
switch (curr)
|
||||
{
|
||||
case EVSE_STATE_A:
|
||||
if (!available)
|
||||
{
|
||||
evse_set_state(EVSE_STATE_F);
|
||||
}
|
||||
else if (pilot_voltage == PILOT_VOLTAGE_9)
|
||||
{
|
||||
evse_set_state(EVSE_STATE_B1);
|
||||
}
|
||||
break;
|
||||
|
||||
case EVSE_STATE_B1:
|
||||
case EVSE_STATE_B2:
|
||||
if (!available) {
|
||||
case EVSE_STATE_B1:
|
||||
case EVSE_STATE_B2:
|
||||
if (!available)
|
||||
{
|
||||
evse_set_state(EVSE_STATE_F);
|
||||
break;
|
||||
}
|
||||
switch (pilot_voltage)
|
||||
{
|
||||
case PILOT_VOLTAGE_12:
|
||||
evse_set_state(EVSE_STATE_A);
|
||||
break;
|
||||
case PILOT_VOLTAGE_9:
|
||||
evse_set_state((authorized && enabled) ? EVSE_STATE_B2 : EVSE_STATE_B1);
|
||||
break;
|
||||
case PILOT_VOLTAGE_6:
|
||||
evse_set_state((authorized && enabled) ? EVSE_STATE_C2 : EVSE_STATE_C1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVSE_STATE_C1:
|
||||
case EVSE_STATE_D1:
|
||||
if (c1_d1_waiting && now >= c1_d1_relay_to)
|
||||
{
|
||||
ac_relay_set_state(false);
|
||||
c1_d1_waiting = false;
|
||||
if (!available)
|
||||
{
|
||||
evse_set_state(EVSE_STATE_F);
|
||||
break;
|
||||
}
|
||||
switch (pilot_voltage) {
|
||||
case PILOT_VOLTAGE_12:
|
||||
evse_set_state(EVSE_STATE_A);
|
||||
break;
|
||||
case PILOT_VOLTAGE_9:
|
||||
evse_set_state((authorized && enabled) ? EVSE_STATE_B2 : EVSE_STATE_B1);
|
||||
break;
|
||||
case PILOT_VOLTAGE_6:
|
||||
evse_set_state((authorized && enabled) ? EVSE_STATE_C2 : EVSE_STATE_C1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
__attribute__((fallthrough));
|
||||
|
||||
case EVSE_STATE_C1:
|
||||
case EVSE_STATE_D1:
|
||||
if (c1_d1_waiting && now >= c1_d1_relay_to) {
|
||||
ac_relay_set_state(false);
|
||||
c1_d1_waiting = false;
|
||||
if (!available) {
|
||||
evse_set_state(EVSE_STATE_F);
|
||||
break;
|
||||
}
|
||||
}
|
||||
__attribute__((fallthrough));
|
||||
|
||||
case EVSE_STATE_C2:
|
||||
case EVSE_STATE_D2:
|
||||
if (!enabled || !available) {
|
||||
evse_set_state((curr == EVSE_STATE_D2 || curr == EVSE_STATE_D1)
|
||||
? EVSE_STATE_D1 : EVSE_STATE_C1);
|
||||
break;
|
||||
}
|
||||
switch (pilot_voltage) {
|
||||
case PILOT_VOLTAGE_6:
|
||||
evse_set_state((authorized && enabled) ? EVSE_STATE_C2 : EVSE_STATE_C1);
|
||||
break;
|
||||
case PILOT_VOLTAGE_3:
|
||||
evse_set_state((authorized && enabled) ? EVSE_STATE_D2 : EVSE_STATE_D1);
|
||||
break;
|
||||
case PILOT_VOLTAGE_9:
|
||||
evse_set_state((authorized && enabled) ? EVSE_STATE_B2 : EVSE_STATE_B1);
|
||||
break;
|
||||
case PILOT_VOLTAGE_12:
|
||||
evse_set_state(EVSE_STATE_A);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case EVSE_STATE_C2:
|
||||
case EVSE_STATE_D2:
|
||||
if (!enabled || !available)
|
||||
{
|
||||
evse_set_state((curr == EVSE_STATE_D2 || curr == EVSE_STATE_D1)
|
||||
? EVSE_STATE_D1
|
||||
: EVSE_STATE_C1);
|
||||
break;
|
||||
|
||||
case EVSE_STATE_E:
|
||||
// Estado elétrico grave: só reset manual
|
||||
}
|
||||
switch (pilot_voltage)
|
||||
{
|
||||
case PILOT_VOLTAGE_6:
|
||||
evse_set_state((authorized && enabled) ? EVSE_STATE_C2 : EVSE_STATE_C1);
|
||||
break;
|
||||
|
||||
case EVSE_STATE_F:
|
||||
// Fault: só sai se disponível e sem erro
|
||||
if (available && evse_get_error() == 0) {
|
||||
evse_set_state(EVSE_STATE_A);
|
||||
}
|
||||
case PILOT_VOLTAGE_3:
|
||||
evse_set_state((authorized && enabled) ? EVSE_STATE_D2 : EVSE_STATE_D1);
|
||||
break;
|
||||
case PILOT_VOLTAGE_9:
|
||||
evse_set_state((authorized && enabled) ? EVSE_STATE_B2 : EVSE_STATE_B1);
|
||||
break;
|
||||
case PILOT_VOLTAGE_12:
|
||||
evse_set_state(EVSE_STATE_A);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVSE_STATE_E:
|
||||
// Estado elétrico grave: só reset manual
|
||||
break;
|
||||
|
||||
case EVSE_STATE_F:
|
||||
// Fault: só sai se disponível e sem erro
|
||||
if (available && evse_get_error() == 0)
|
||||
{
|
||||
evse_set_state(EVSE_STATE_A);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
evse_state_t next = evse_get_state();
|
||||
update_outputs(next);
|
||||
|
||||
if (next != prev) {
|
||||
ESP_LOGI(TAG, "State changed: %s -> %s",
|
||||
evse_state_to_str(prev),
|
||||
evse_state_to_str(next));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user