new upgrade
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
// components/evse/evse_fsm.c
|
||||
#include "evse_fsm.h"
|
||||
#include "evse_api.h"
|
||||
#include "evse_pilot.h"
|
||||
@@ -17,16 +18,14 @@ static const char *TAG = "evse_fsm";
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
static bool c1_d1_waiting = false;
|
||||
static TickType_t c1_d1_relay_to = 0;
|
||||
|
||||
void evse_fsm_reset(void)
|
||||
{
|
||||
evse_set_state(EVSE_STATE_A);
|
||||
c1_d1_waiting = false;
|
||||
c1_d1_relay_to = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Atualiza saídas de hardware (pilot, relé, trava) em função do estado lógico.
|
||||
*/
|
||||
static void update_outputs(evse_state_t state)
|
||||
{
|
||||
const uint16_t current = evse_get_runtime_charging_current();
|
||||
@@ -38,7 +37,7 @@ static void update_outputs(evse_state_t state)
|
||||
cable_max_current = proximity_get_max_current();
|
||||
}
|
||||
|
||||
// Segurança: relé sempre off e outputs seguros em caso de erro
|
||||
// Segurança total: qualquer erro ativo força saída segura
|
||||
if (evse_get_error() != 0)
|
||||
{
|
||||
if (ac_relay_get_state())
|
||||
@@ -46,8 +45,14 @@ static void update_outputs(evse_state_t state)
|
||||
ac_relay_set_state(false);
|
||||
ESP_LOGW(TAG, "ERRO ativo: relé estava ligado, agora desligado por segurança!");
|
||||
}
|
||||
ac_relay_set_state(false);
|
||||
else
|
||||
{
|
||||
ac_relay_set_state(false);
|
||||
}
|
||||
|
||||
// Em erro, garantir pilot OFF (não PWM / não +12V)
|
||||
pilot_set_level(true);
|
||||
|
||||
if (board_config.socket_lock && socket_outlet)
|
||||
{
|
||||
socket_lock_set_locked(false);
|
||||
@@ -55,14 +60,16 @@ static void update_outputs(evse_state_t state)
|
||||
return;
|
||||
}
|
||||
|
||||
// Fluxo normal
|
||||
switch (state)
|
||||
{
|
||||
case EVSE_STATE_A:
|
||||
case EVSE_STATE_E:
|
||||
case EVSE_STATE_F:
|
||||
ac_relay_set_state(false);
|
||||
|
||||
// A → pilot alto (+12V), E/F → pilot OFF
|
||||
pilot_set_level(state == EVSE_STATE_A);
|
||||
|
||||
if (board_config.socket_lock && socket_outlet)
|
||||
{
|
||||
socket_lock_set_locked(false);
|
||||
@@ -72,66 +79,77 @@ static void update_outputs(evse_state_t state)
|
||||
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");
|
||||
}
|
||||
(void)rcm_test();
|
||||
break;
|
||||
|
||||
case EVSE_STATE_B2:
|
||||
pilot_set_amps(MIN(current, cable_max_current));
|
||||
ac_relay_set_state(false);
|
||||
|
||||
if (board_config.socket_lock && socket_outlet)
|
||||
{
|
||||
socket_lock_set_locked(true);
|
||||
}
|
||||
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);
|
||||
|
||||
if (board_config.socket_lock && socket_outlet)
|
||||
{
|
||||
socket_lock_set_locked(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case EVSE_STATE_C2:
|
||||
case EVSE_STATE_D2:
|
||||
pilot_set_amps(MIN(current, cable_max_current));
|
||||
ac_relay_set_state(true);
|
||||
|
||||
if (board_config.socket_lock && socket_outlet)
|
||||
{
|
||||
socket_lock_set_locked(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// FSM principal
|
||||
/**
|
||||
* @brief Máquina de estados principal do EVSE (IEC 61851).
|
||||
*/
|
||||
void evse_fsm_process(
|
||||
pilot_voltage_t pilot_voltage,
|
||||
bool authorized,
|
||||
bool available,
|
||||
bool enabled)
|
||||
{
|
||||
// Proteção total: erro força F sempre!
|
||||
if (evse_get_error() != 0)
|
||||
// 1) Erros globais: dominam qualquer outra lógica
|
||||
uint32_t err_bits = evse_get_error();
|
||||
if (err_bits != 0)
|
||||
{
|
||||
if (evse_get_state() != EVSE_STATE_F)
|
||||
evse_state_t forced_state =
|
||||
(err_bits & EVSE_ERR_PILOT_FAULT_BIT) ? EVSE_STATE_E : EVSE_STATE_F;
|
||||
|
||||
if (evse_get_state() != forced_state)
|
||||
{
|
||||
ESP_LOGW(TAG, "Erro ativo detectado: forçando estado FAULT (F)");
|
||||
evse_set_state(EVSE_STATE_F);
|
||||
ESP_LOGW(TAG, "Erro ativo detectado: forçando estado %s",
|
||||
evse_state_to_str(forced_state));
|
||||
evse_set_state(forced_state);
|
||||
}
|
||||
update_outputs(EVSE_STATE_F);
|
||||
|
||||
update_outputs(forced_state);
|
||||
return;
|
||||
}
|
||||
|
||||
TickType_t now = xTaskGetTickCount();
|
||||
evse_state_t prev = evse_get_state();
|
||||
evse_state_t curr = prev;
|
||||
evse_state_t curr = evse_get_state();
|
||||
|
||||
switch (curr)
|
||||
{
|
||||
@@ -153,17 +171,25 @@ void evse_fsm_process(
|
||||
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;
|
||||
|
||||
case PILOT_VOLTAGE_3:
|
||||
evse_set_state((authorized && enabled) ? EVSE_STATE_D2 : EVSE_STATE_D1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -171,52 +197,59 @@ void evse_fsm_process(
|
||||
|
||||
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)
|
||||
if (!available)
|
||||
{
|
||||
evse_set_state((curr == EVSE_STATE_D2 || curr == EVSE_STATE_D1)
|
||||
? EVSE_STATE_D1
|
||||
: EVSE_STATE_C1);
|
||||
evse_set_state(EVSE_STATE_F);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!enabled)
|
||||
{
|
||||
if (curr == EVSE_STATE_C2)
|
||||
{
|
||||
evse_set_state(EVSE_STATE_C1);
|
||||
}
|
||||
else if (curr == EVSE_STATE_D2)
|
||||
{
|
||||
evse_set_state(EVSE_STATE_D1);
|
||||
}
|
||||
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;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVSE_STATE_E:
|
||||
// Estado elétrico grave: só reset manual
|
||||
// ✅ Agora recupera como F: se disponível e sem erro -> volta a A
|
||||
if (available && evse_get_error() == 0)
|
||||
{
|
||||
evse_set_state(EVSE_STATE_A);
|
||||
}
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user