Adicionar primeiro
This commit is contained in:
18
components/evse/CMakeLists.txt
Executable file
18
components/evse/CMakeLists.txt
Executable file
@@ -0,0 +1,18 @@
|
||||
set(srcs
|
||||
evse_core.c
|
||||
evse_state.c
|
||||
evse_error.c
|
||||
evse_config.c
|
||||
evse_limits.c
|
||||
evse_events.c
|
||||
evse_fsm.c
|
||||
evse_manager.c
|
||||
evse_hardware.c
|
||||
)
|
||||
|
||||
idf_component_register(
|
||||
SRCS ${srcs}
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_REQUIRES nvs_flash
|
||||
REQUIRES peripherals
|
||||
)
|
||||
203
components/evse/evse_config.c
Executable file
203
components/evse/evse_config.c
Executable file
@@ -0,0 +1,203 @@
|
||||
#include "evse_config.h"
|
||||
#include "board_config.h"
|
||||
#include "evse_limits.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs.h"
|
||||
|
||||
static const char *TAG = "evse_config";
|
||||
|
||||
static nvs_handle_t nvs;
|
||||
|
||||
// Parâmetros configuráveis
|
||||
static uint8_t max_charging_current = MAX_CHARGING_CURRENT_LIMIT;
|
||||
static uint8_t grid_max_current = MAX_GRID_CURRENT_LIMIT;
|
||||
static uint16_t charging_current;
|
||||
static bool socket_outlet;
|
||||
static bool rcm;
|
||||
static uint8_t temp_threshold = 60;
|
||||
static bool require_auth;
|
||||
|
||||
esp_err_t evse_config_init(void) {
|
||||
ESP_LOGI(TAG, "Abrindo namespace NVS");
|
||||
return nvs_open("evse", NVS_READWRITE, &nvs);
|
||||
}
|
||||
|
||||
void evse_check_defaults(void) {
|
||||
esp_err_t err;
|
||||
uint8_t u8;
|
||||
uint16_t u16;
|
||||
uint32_t u32;
|
||||
bool needs_commit = false;
|
||||
|
||||
// Max charging current
|
||||
err = nvs_get_u8(nvs, "max_chrg_curr", &u8);
|
||||
if (err != ESP_OK || u8 < MIN_CHARGING_CURRENT_LIMIT || u8 > MAX_CHARGING_CURRENT_LIMIT) {
|
||||
max_charging_current = MAX_CHARGING_CURRENT_LIMIT;
|
||||
nvs_set_u8(nvs, "max_chrg_curr", max_charging_current);
|
||||
needs_commit = true;
|
||||
} else {
|
||||
max_charging_current = u8;
|
||||
}
|
||||
|
||||
// Grid max current
|
||||
err = nvs_get_u8(nvs, "grid_max_curr", &u8);
|
||||
if (err != ESP_OK || u8 < MIN_GRID_CURRENT_LIMIT || u8 > MAX_GRID_CURRENT_LIMIT) {
|
||||
grid_max_current = MAX_GRID_CURRENT_LIMIT;
|
||||
nvs_set_u8(nvs, "grid_max_curr", grid_max_current);
|
||||
needs_commit = true;
|
||||
} else {
|
||||
grid_max_current = u8;
|
||||
}
|
||||
|
||||
// Charging current (decA)
|
||||
err = nvs_get_u16(nvs, "def_chrg_curr", &u16);
|
||||
if (err != ESP_OK || u16 < (MIN_CHARGING_CURRENT_LIMIT * 10) || u16 > (max_charging_current * 10)) {
|
||||
charging_current = max_charging_current * 10;
|
||||
nvs_set_u16(nvs, "def_chrg_curr", charging_current);
|
||||
needs_commit = true;
|
||||
} else {
|
||||
charging_current = u16;
|
||||
}
|
||||
|
||||
err = nvs_get_u8(nvs, "require_auth", &u8);
|
||||
require_auth = (err == ESP_OK && u8 <= 1) ? u8 : false;
|
||||
if (err != ESP_OK) {
|
||||
nvs_set_u8(nvs, "require_auth", require_auth);
|
||||
needs_commit = true;
|
||||
}
|
||||
|
||||
err = nvs_get_u8(nvs, "socket_outlet", &u8);
|
||||
socket_outlet = (err == ESP_OK && u8) && board_config.proximity;
|
||||
if (err != ESP_OK) {
|
||||
nvs_set_u8(nvs, "socket_outlet", socket_outlet);
|
||||
needs_commit = true;
|
||||
}
|
||||
|
||||
err = nvs_get_u8(nvs, "rcm", &u8);
|
||||
rcm = (err == ESP_OK && u8) && board_config.rcm;
|
||||
if (err != ESP_OK) {
|
||||
nvs_set_u8(nvs, "rcm", rcm);
|
||||
needs_commit = true;
|
||||
}
|
||||
|
||||
err = nvs_get_u8(nvs, "temp_threshold", &u8);
|
||||
temp_threshold = (err == ESP_OK && u8 >= 40 && u8 <= 80) ? u8 : 60;
|
||||
if (err != ESP_OK) {
|
||||
nvs_set_u8(nvs, "temp_threshold", temp_threshold);
|
||||
needs_commit = true;
|
||||
}
|
||||
|
||||
// Limites adicionais
|
||||
if (nvs_get_u32(nvs, "def_cons_lim", &u32) == ESP_OK) {
|
||||
evse_set_consumption_limit(u32);
|
||||
}
|
||||
|
||||
if (nvs_get_u32(nvs, "def_ch_time_lim", &u32) == ESP_OK) {
|
||||
evse_set_charging_time_limit(u32);
|
||||
}
|
||||
|
||||
if (nvs_get_u16(nvs, "def_un_pwr_lim", &u16) == ESP_OK) {
|
||||
evse_set_under_power_limit(u16);
|
||||
}
|
||||
|
||||
if (needs_commit) {
|
||||
nvs_commit(nvs);
|
||||
}
|
||||
}
|
||||
|
||||
// Corrente
|
||||
uint8_t evse_get_max_charging_current(void) { return max_charging_current; }
|
||||
esp_err_t evse_set_max_charging_current(uint8_t value) {
|
||||
if (value < MIN_CHARGING_CURRENT_LIMIT || value > MAX_CHARGING_CURRENT_LIMIT)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
max_charging_current = value;
|
||||
nvs_set_u8(nvs, "max_chrg_curr", value);
|
||||
return nvs_commit(nvs);
|
||||
}
|
||||
|
||||
uint8_t grid_get_max_current(void) { return grid_max_current; }
|
||||
esp_err_t grid_set_max_current(uint8_t value) {
|
||||
if (value < MIN_GRID_CURRENT_LIMIT || value > MAX_GRID_CURRENT_LIMIT)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
grid_max_current = value;
|
||||
nvs_set_u8(nvs, "grid_max_curr", value);
|
||||
return nvs_commit(nvs);
|
||||
}
|
||||
|
||||
uint16_t evse_get_charging_current(void) { return charging_current; }
|
||||
esp_err_t evse_set_charging_current(uint16_t value) {
|
||||
if (value < (MIN_CHARGING_CURRENT_LIMIT * 10) || value > (max_charging_current * 10))
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
charging_current = value;
|
||||
nvs_set_u16(nvs, "def_chrg_curr", value);
|
||||
return nvs_commit(nvs);
|
||||
}
|
||||
|
||||
uint16_t evse_get_default_charging_current(void) {
|
||||
uint16_t value;
|
||||
nvs_get_u16(nvs, "def_chrg_curr", &value);
|
||||
return value;
|
||||
}
|
||||
esp_err_t evse_set_default_charging_current(uint16_t value) {
|
||||
if (value < (MIN_CHARGING_CURRENT_LIMIT * 10) || value > (max_charging_current * 10))
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
nvs_set_u16(nvs, "def_chrg_curr", value);
|
||||
return nvs_commit(nvs);
|
||||
}
|
||||
|
||||
// Socket outlet
|
||||
bool evse_get_socket_outlet(void) { return socket_outlet; }
|
||||
esp_err_t evse_set_socket_outlet(bool value) {
|
||||
if (value && !board_config.proximity) return ESP_ERR_INVALID_ARG;
|
||||
socket_outlet = value;
|
||||
nvs_set_u8(nvs, "socket_outlet", value);
|
||||
return nvs_commit(nvs);
|
||||
}
|
||||
|
||||
// RCM
|
||||
bool evse_is_rcm(void) { return rcm; }
|
||||
esp_err_t evse_set_rcm(bool value) {
|
||||
if (value && !board_config.rcm) return ESP_ERR_INVALID_ARG;
|
||||
rcm = value;
|
||||
nvs_set_u8(nvs, "rcm", value);
|
||||
return nvs_commit(nvs);
|
||||
}
|
||||
|
||||
// Temperatura
|
||||
uint8_t evse_get_temp_threshold(void) { return temp_threshold; }
|
||||
esp_err_t evse_set_temp_threshold(uint8_t value) {
|
||||
if (value < 40 || value > 80) return ESP_ERR_INVALID_ARG;
|
||||
temp_threshold = value;
|
||||
nvs_set_u8(nvs, "temp_threshold", value);
|
||||
return nvs_commit(nvs);
|
||||
}
|
||||
|
||||
// Autenticação
|
||||
bool evse_is_require_auth(void) { return require_auth; }
|
||||
void evse_set_require_auth(bool value) {
|
||||
require_auth = value;
|
||||
nvs_set_u8(nvs, "require_auth", value);
|
||||
nvs_commit(nvs);
|
||||
}
|
||||
|
||||
// Disponibilidade
|
||||
static bool is_available = true;
|
||||
|
||||
bool evse_config_is_available(void) {
|
||||
return is_available;
|
||||
}
|
||||
|
||||
void evse_config_set_available(bool available) {
|
||||
is_available = available;
|
||||
}
|
||||
|
||||
// Ativação/desativação
|
||||
static bool is_enabled = true;
|
||||
|
||||
bool evse_config_is_enabled(void) {
|
||||
return is_enabled;
|
||||
}
|
||||
|
||||
void evse_config_set_enabled(bool enabled) {
|
||||
is_enabled = enabled;
|
||||
}
|
||||
131
components/evse/evse_core.c
Executable file
131
components/evse/evse_core.c
Executable file
@@ -0,0 +1,131 @@
|
||||
// evse_core.c - Função principal de controle do EVSE
|
||||
|
||||
#include "evse_fsm.h"
|
||||
#include "evse_error.h"
|
||||
#include "evse_limits.h"
|
||||
#include "evse_config.h"
|
||||
#include "evse_api.h"
|
||||
#include "pilot.h"
|
||||
#include "energy_meter.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "evse_core";
|
||||
|
||||
static SemaphoreHandle_t mutex;
|
||||
|
||||
static evse_state_t last_state = EVSE_STATE_A;
|
||||
static bool authorized = false;
|
||||
static TickType_t auth_grant_to = 0;
|
||||
|
||||
static void evse_core_task(void *arg);
|
||||
|
||||
void evse_init(void) {
|
||||
ESP_LOGI(TAG, "EVSE Init");
|
||||
|
||||
mutex = xSemaphoreCreateMutex();
|
||||
|
||||
evse_check_defaults();
|
||||
evse_fsm_reset();
|
||||
pilot_set_level(true); // Estado inicial do piloto
|
||||
|
||||
xTaskCreate(evse_core_task, "evse_core_task", 4096, NULL, 5, NULL);
|
||||
}
|
||||
|
||||
void evse_process(void) {
|
||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||
|
||||
pilot_voltage_t pilot_voltage;
|
||||
bool is_n12v = false;
|
||||
|
||||
pilot_measure(&pilot_voltage, &is_n12v);
|
||||
ESP_LOGD(TAG, "Pilot: %d, -12V: %s", pilot_voltage, is_n12v ? "yes" : "no");
|
||||
|
||||
evse_error_check(pilot_voltage, is_n12v);
|
||||
|
||||
if (evse_get_error() == 0 && !evse_is_error_cleared()) {
|
||||
// Autorização temporária se exigida
|
||||
if (!authorized && evse_is_require_auth()) {
|
||||
authorized = auth_grant_to >= xTaskGetTickCount();
|
||||
if (auth_grant_to) auth_grant_to = 0;
|
||||
} else {
|
||||
authorized = true;
|
||||
}
|
||||
|
||||
evse_fsm_process(
|
||||
pilot_voltage,
|
||||
authorized,
|
||||
evse_config_is_available(),
|
||||
evse_config_is_enabled()
|
||||
);
|
||||
|
||||
evse_limits_check(evse_get_state());
|
||||
|
||||
evse_state_t current = evse_get_state();
|
||||
if (current != last_state) {
|
||||
ESP_LOGI(TAG, "State changed: %s → %s", evse_state_to_str(last_state), evse_state_to_str(current));
|
||||
last_state = current;
|
||||
}
|
||||
}
|
||||
|
||||
if (evse_get_error() == 0) {
|
||||
evse_mark_error_cleared();
|
||||
}
|
||||
|
||||
xSemaphoreGive(mutex);
|
||||
|
||||
energy_meter_process(
|
||||
evse_state_is_charging(evse_get_state()),
|
||||
evse_get_charging_current()
|
||||
);
|
||||
}
|
||||
|
||||
// ================================
|
||||
// Interface pública
|
||||
// ================================
|
||||
|
||||
bool evse_is_enabled(void) {
|
||||
return evse_config_is_enabled();
|
||||
}
|
||||
|
||||
void evse_set_enabled(bool value) {
|
||||
ESP_LOGI(TAG, "Set enabled %d", value);
|
||||
evse_config_set_enabled(value);
|
||||
}
|
||||
|
||||
bool evse_is_available(void) {
|
||||
return evse_config_is_available();
|
||||
}
|
||||
|
||||
void evse_set_available(bool value) {
|
||||
ESP_LOGI(TAG, "Set available %d", value);
|
||||
evse_config_set_available(value);
|
||||
}
|
||||
|
||||
bool evse_is_pending_auth(void) {
|
||||
return evse_state_is_session(evse_get_state()) && !authorized;
|
||||
}
|
||||
|
||||
void evse_authorize(void) {
|
||||
ESP_LOGI(TAG, "Authorize");
|
||||
auth_grant_to = xTaskGetTickCount() + pdMS_TO_TICKS(60000);
|
||||
}
|
||||
|
||||
void evse_set_authorized(bool value) {
|
||||
ESP_LOGI(TAG, "Set authorized %d", value);
|
||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||
authorized = value;
|
||||
xSemaphoreGive(mutex);
|
||||
}
|
||||
|
||||
// ================================
|
||||
// Tarefa principal
|
||||
// ================================
|
||||
|
||||
static void evse_core_task(void *arg) {
|
||||
while (true) {
|
||||
evse_process();
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
}
|
||||
119
components/evse/evse_error.c
Executable file
119
components/evse/evse_error.c
Executable file
@@ -0,0 +1,119 @@
|
||||
#include "evse_error.h"
|
||||
#include "evse_config.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "ntc_sensor.h"
|
||||
|
||||
static const char *TAG = "evse_error";
|
||||
|
||||
static uint32_t error_bits = 0;
|
||||
static TickType_t auto_clear_timeout = 0;
|
||||
static bool error_cleared = false;
|
||||
|
||||
void evse_error_init(void) {
|
||||
// Inicialização do sistema de erros
|
||||
}
|
||||
|
||||
void evse_error_check(pilot_voltage_t pilot_voltage, bool is_n12v) {
|
||||
ESP_LOGD(TAG, "Verificando erro: pilot_voltage = %d, is_n12v = %s",
|
||||
pilot_voltage, is_n12v ? "true" : "false");
|
||||
|
||||
// Falha elétrica geral no pilot
|
||||
if (pilot_voltage == PILOT_VOLTAGE_1) {
|
||||
if (!(error_bits & EVSE_ERR_PILOT_FAULT_BIT)) { // Verifica se o erro já foi registrado
|
||||
evse_error_set(EVSE_ERR_PILOT_FAULT_BIT);
|
||||
ESP_LOGW(TAG, "Erro: pilot abaixo de 2V (falha)");
|
||||
}
|
||||
}
|
||||
|
||||
// Falta de -12V durante PWM (C ou D)
|
||||
if ((pilot_voltage == PILOT_VOLTAGE_6 || pilot_voltage == PILOT_VOLTAGE_3) && !is_n12v) {
|
||||
if (!(error_bits & EVSE_ERR_DIODE_SHORT_BIT)) { // Verifica se o erro já foi registrado
|
||||
evse_error_set(EVSE_ERR_DIODE_SHORT_BIT);
|
||||
ESP_LOGW(TAG, "Erro: ausência de -12V no PWM (sem diodo)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void evse_temperature_check(void) {
|
||||
float temp_c = ntc_temp_sensor(); // leitura atual (última medida válida)
|
||||
uint8_t threshold = evse_get_temp_threshold(); // padrão 60°C, configurável
|
||||
|
||||
// Log informativo com os valores
|
||||
ESP_LOGD(TAG, "Verificando temperatura: atual = %.2f °C, limite = %d °C", temp_c, threshold);
|
||||
|
||||
// Se a temperatura parecer inválida, aplica erro de sensor
|
||||
if (temp_c < -40.0f || temp_c > 150.0f) {
|
||||
if (!(error_bits & EVSE_ERR_TEMPERATURE_FAULT_BIT)) { // Verifica se o erro já foi registrado
|
||||
evse_error_set(EVSE_ERR_TEMPERATURE_FAULT_BIT);
|
||||
ESP_LOGW(TAG, "Sensor NTC falhou ou está desconectado");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
evse_error_clear(EVSE_ERR_TEMPERATURE_FAULT_BIT); // leitura válida
|
||||
|
||||
if (temp_c >= threshold) {
|
||||
if (!(error_bits & EVSE_ERR_TEMPERATURE_HIGH_BIT)) { // Verifica se o erro já foi registrado
|
||||
evse_error_set(EVSE_ERR_TEMPERATURE_HIGH_BIT);
|
||||
ESP_LOGW(TAG, "Temperatura acima do limite: %.2f °C ≥ %d °C", temp_c, threshold);
|
||||
}
|
||||
} else {
|
||||
evse_error_clear(EVSE_ERR_TEMPERATURE_HIGH_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t evse_get_error(void) {
|
||||
return error_bits;
|
||||
}
|
||||
|
||||
bool evse_is_error_cleared(void) {
|
||||
return error_cleared;
|
||||
}
|
||||
|
||||
void evse_mark_error_cleared(void) {
|
||||
error_cleared = false;
|
||||
}
|
||||
|
||||
// Já existentes
|
||||
void evse_error_set(uint32_t bitmask) {
|
||||
error_bits |= bitmask;
|
||||
|
||||
if (bitmask & EVSE_ERR_AUTO_CLEAR_BITS) {
|
||||
auto_clear_timeout = xTaskGetTickCount() + pdMS_TO_TICKS(60000); // 60s
|
||||
}
|
||||
}
|
||||
|
||||
void evse_error_clear(uint32_t bitmask) {
|
||||
bool had_error = error_bits != 0;
|
||||
error_bits &= ~bitmask;
|
||||
|
||||
if (had_error && error_bits == 0) {
|
||||
error_cleared = true;
|
||||
}
|
||||
}
|
||||
|
||||
void evse_error_tick(void) {
|
||||
if ((error_bits & EVSE_ERR_AUTO_CLEAR_BITS) && xTaskGetTickCount() >= auto_clear_timeout) {
|
||||
evse_error_clear(EVSE_ERR_AUTO_CLEAR_BITS);
|
||||
auto_clear_timeout = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool evse_error_is_active(void) {
|
||||
return error_bits != 0;
|
||||
}
|
||||
|
||||
uint32_t evse_error_get_bits(void) {
|
||||
return error_bits;
|
||||
}
|
||||
|
||||
void evse_error_reset_flag(void) {
|
||||
error_cleared = false;
|
||||
}
|
||||
|
||||
bool evse_error_cleared_flag(void) {
|
||||
return error_cleared;
|
||||
}
|
||||
3
components/evse/evse_events.c
Executable file
3
components/evse/evse_events.c
Executable file
@@ -0,0 +1,3 @@
|
||||
#include "evse_events.h"
|
||||
|
||||
ESP_EVENT_DEFINE_BASE(EVSE_EVENT);
|
||||
175
components/evse/evse_fsm.c
Executable file
175
components/evse/evse_fsm.c
Executable file
@@ -0,0 +1,175 @@
|
||||
// evse_fsm.c - Máquina de Estados EVSE com controle centralizado
|
||||
|
||||
#include "evse_fsm.h"
|
||||
#include "evse_api.h"
|
||||
#include "pilot.h"
|
||||
#include "esp_log.h"
|
||||
#include "ac_relay.h"
|
||||
#include "board_config.h"
|
||||
#include "socket_lock.h"
|
||||
#include "energy_meter.h"
|
||||
#include "proximity.h"
|
||||
#include "rcm.h"
|
||||
#include "evse_state.h"
|
||||
|
||||
static const char *TAG = "evse_fsm";
|
||||
|
||||
#ifndef MIN
|
||||
#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;
|
||||
}
|
||||
|
||||
static void update_outputs(evse_state_t state, uint16_t charging_current, uint8_t cable_max_current, bool socket_outlet) {
|
||||
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);
|
||||
}
|
||||
energy_meter_stop_session();
|
||||
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");
|
||||
}
|
||||
|
||||
if (socket_outlet) {
|
||||
cable_max_current = proximity_get_max_current();
|
||||
}
|
||||
|
||||
energy_meter_start_session();
|
||||
break;
|
||||
|
||||
case EVSE_STATE_B2:
|
||||
pilot_set_amps(MIN(charging_current, cable_max_current * 10));
|
||||
ac_relay_set_state(false);
|
||||
break;
|
||||
|
||||
case EVSE_STATE_C1:
|
||||
case EVSE_STATE_D1:
|
||||
pilot_set_level(true);
|
||||
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(charging_current, cable_max_current * 10));
|
||||
ac_relay_set_state(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void evse_fsm_process(pilot_voltage_t pilot_voltage, bool authorized, bool available, bool enabled) {
|
||||
TickType_t now = xTaskGetTickCount();
|
||||
evse_state_t previous_state = evse_get_state();
|
||||
evse_state_t current_state = previous_state;
|
||||
|
||||
switch (current_state) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
// fallthrough intencional
|
||||
case EVSE_STATE_C2:
|
||||
case EVSE_STATE_D2:
|
||||
if (!enabled || !available) {
|
||||
evse_set_state(
|
||||
(current_state == EVSE_STATE_D2 || current_state == 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;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVSE_STATE_E:
|
||||
// Sem transições a partir de E
|
||||
break;
|
||||
|
||||
case EVSE_STATE_F:
|
||||
if (available) {
|
||||
evse_set_state(EVSE_STATE_A);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
evse_state_t new_state = evse_get_state();
|
||||
if (new_state != previous_state) {
|
||||
ESP_LOGI(TAG, "State changed: %s -> %s", evse_state_to_str(previous_state), evse_state_to_str(new_state));
|
||||
update_outputs(new_state, evse_get_charging_current(), evse_get_max_charging_current(), evse_get_socket_outlet());
|
||||
}
|
||||
}
|
||||
55
components/evse/evse_hardware.c
Normal file
55
components/evse/evse_hardware.c
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "evse_hardware.h"
|
||||
#include "pilot.h"
|
||||
#include "ac_relay.h"
|
||||
#include "socket_lock.h"
|
||||
#include "proximity.h"
|
||||
|
||||
static const char *TAG = "evse_hardware";
|
||||
|
||||
void evse_hardware_init(void) {
|
||||
pilot_set_level(true); // Sinal piloto em 12V (inicial)
|
||||
ac_relay_set_state(false); // Relé desligado
|
||||
//socket_lock_set_locked(false); // Destrava o conector
|
||||
}
|
||||
|
||||
void evse_hardware_tick(void) {
|
||||
// Tick para atualizações de hardware com polling, se necessário
|
||||
}
|
||||
|
||||
bool evse_hardware_is_pilot_high(void) {
|
||||
return pilot_get_state(); // true se sinal piloto estiver em nível alto
|
||||
}
|
||||
|
||||
bool evse_hardware_is_vehicle_connected(void) {
|
||||
// Verifica se o veículo está conectado pelo resistor do pino PP
|
||||
return proximity_get_max_current() > 0;
|
||||
}
|
||||
|
||||
bool evse_hardware_is_energy_detected(void) {
|
||||
// TODO: Substituir com medição real de corrente ou consumo
|
||||
return true;
|
||||
}
|
||||
|
||||
void evse_hardware_relay_on(void) {
|
||||
ac_relay_set_state(true);
|
||||
}
|
||||
|
||||
void evse_hardware_relay_off(void) {
|
||||
ac_relay_set_state(false);
|
||||
}
|
||||
|
||||
bool evse_hardware_relay_status(void) {
|
||||
return ac_relay_get_state();
|
||||
}
|
||||
|
||||
void evse_hardware_lock(void) {
|
||||
socket_lock_set_locked(true);
|
||||
}
|
||||
|
||||
void evse_hardware_unlock(void) {
|
||||
socket_lock_set_locked(false);
|
||||
}
|
||||
|
||||
bool evse_hardware_is_locked(void) {
|
||||
return socket_lock_get_status() == SOCKED_LOCK_STATUS_IDLE;
|
||||
}
|
||||
97
components/evse/evse_limits.c
Executable file
97
components/evse/evse_limits.c
Executable file
@@ -0,0 +1,97 @@
|
||||
#include "evse_limits.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// ========================
|
||||
// Estado interno
|
||||
// ========================
|
||||
|
||||
static bool limit_reached = false;
|
||||
static uint32_t consumption_limit = 0;
|
||||
static uint32_t charging_time_limit = 0;
|
||||
static uint16_t under_power_limit = 0;
|
||||
|
||||
static uint32_t default_consumption_limit = 0;
|
||||
static uint32_t default_charging_time_limit = 0;
|
||||
static uint16_t default_under_power_limit = 0;
|
||||
|
||||
// ========================
|
||||
// Estado de controle
|
||||
// ========================
|
||||
|
||||
void evse_set_limit_reached(uint8_t value) {
|
||||
limit_reached = (value != 0);
|
||||
}
|
||||
|
||||
bool evse_is_limit_reached(void) {
|
||||
return limit_reached;
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Limites em tempo de execução
|
||||
// ========================
|
||||
|
||||
uint32_t evse_get_consumption_limit(void) {
|
||||
return consumption_limit;
|
||||
}
|
||||
|
||||
void evse_set_consumption_limit(uint32_t value) {
|
||||
consumption_limit = value;
|
||||
}
|
||||
|
||||
uint32_t evse_get_charging_time_limit(void) {
|
||||
return charging_time_limit;
|
||||
}
|
||||
|
||||
void evse_set_charging_time_limit(uint32_t value) {
|
||||
charging_time_limit = value;
|
||||
}
|
||||
|
||||
uint16_t evse_get_under_power_limit(void) {
|
||||
return under_power_limit;
|
||||
}
|
||||
|
||||
void evse_set_under_power_limit(uint16_t value) {
|
||||
under_power_limit = value;
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Limites padrão (persistentes)
|
||||
// ========================
|
||||
|
||||
uint32_t evse_get_default_consumption_limit(void) {
|
||||
return default_consumption_limit;
|
||||
}
|
||||
|
||||
void evse_set_default_consumption_limit(uint32_t value) {
|
||||
default_consumption_limit = value;
|
||||
}
|
||||
|
||||
uint32_t evse_get_default_charging_time_limit(void) {
|
||||
return default_charging_time_limit;
|
||||
}
|
||||
|
||||
void evse_set_default_charging_time_limit(uint32_t value) {
|
||||
default_charging_time_limit = value;
|
||||
}
|
||||
|
||||
uint16_t evse_get_default_under_power_limit(void) {
|
||||
return default_under_power_limit;
|
||||
}
|
||||
|
||||
void evse_set_default_under_power_limit(uint16_t value) {
|
||||
default_under_power_limit = value;
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Lógica de verificação de limites
|
||||
// ========================
|
||||
|
||||
void evse_limits_check(evse_state_t state) {
|
||||
// Se algum limite estiver ativo, verifique o estado
|
||||
if ((consumption_limit > 0 || charging_time_limit > 0 || under_power_limit > 0)
|
||||
&& evse_state_is_charging(state)) {
|
||||
// (Lógica real a ser aplicada aqui, ex: medição de consumo, tempo ou potência)
|
||||
evse_set_limit_reached(1);
|
||||
}
|
||||
}
|
||||
81
components/evse/evse_manager.c
Normal file
81
components/evse/evse_manager.c
Normal file
@@ -0,0 +1,81 @@
|
||||
#include "evse_manager.h"
|
||||
#include "evse_state.h"
|
||||
#include "evse_error.h"
|
||||
#include "evse_hardware.h"
|
||||
#include "evse_config.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "evse_manager";
|
||||
|
||||
static SemaphoreHandle_t evse_mutex;
|
||||
|
||||
#define EVSE_MANAGER_TICK_PERIOD_MS 1000 // 1 segundo
|
||||
|
||||
|
||||
|
||||
void evse_manager_init(void) {
|
||||
evse_mutex = xSemaphoreCreateMutex();
|
||||
|
||||
evse_config_init();
|
||||
evse_error_init();
|
||||
evse_hardware_init();
|
||||
evse_state_init();
|
||||
ESP_LOGI(TAG, "EVSE Manager initialized");
|
||||
|
||||
xTaskCreate(
|
||||
evse_manager_task,
|
||||
"evse_manager_task",
|
||||
4096, // stack size
|
||||
NULL, // param
|
||||
5, // priority
|
||||
NULL // handle
|
||||
);
|
||||
}
|
||||
|
||||
void evse_manager_task(void *arg) {
|
||||
while (true) {
|
||||
evse_manager_tick();
|
||||
vTaskDelay(pdMS_TO_TICKS(EVSE_MANAGER_TICK_PERIOD_MS));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void evse_manager_tick(void) {
|
||||
xSemaphoreTake(evse_mutex, portMAX_DELAY);
|
||||
|
||||
// Atualizações cíclicas de módulos
|
||||
evse_hardware_tick();
|
||||
evse_error_tick();
|
||||
evse_state_tick();
|
||||
|
||||
evse_temperature_check();
|
||||
|
||||
xSemaphoreGive(evse_mutex);
|
||||
}
|
||||
|
||||
bool evse_manager_is_available(void) {
|
||||
return evse_config_is_available();
|
||||
}
|
||||
|
||||
void evse_manager_set_available(bool available) {
|
||||
evse_config_set_available(available);
|
||||
}
|
||||
|
||||
void evse_manager_set_authorized(bool authorized) {
|
||||
evse_state_set_authorized(authorized);
|
||||
}
|
||||
|
||||
bool evse_manager_is_charging(void) {
|
||||
return evse_state_is_charging(evse_get_state());
|
||||
}
|
||||
|
||||
void evse_manager_set_enabled(bool enabled) {
|
||||
evse_config_set_enabled(enabled);
|
||||
}
|
||||
|
||||
bool evse_manager_is_enabled(void) {
|
||||
return evse_config_is_enabled();
|
||||
}
|
||||
49
components/evse/evse_state.c
Normal file
49
components/evse/evse_state.c
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "evse_state.h"
|
||||
|
||||
static evse_state_t current_state = EVSE_STATE_A;
|
||||
|
||||
void evse_set_state(evse_state_t state) {
|
||||
current_state = state;
|
||||
}
|
||||
|
||||
evse_state_t evse_get_state(void) {
|
||||
return current_state;
|
||||
}
|
||||
|
||||
const char* evse_state_to_str(evse_state_t state) {
|
||||
switch (state) {
|
||||
case EVSE_STATE_A: return "A - EV Not Connected (12V)";
|
||||
case EVSE_STATE_B1: return "B1 - EV Connected (9V, Not Authorized)";
|
||||
case EVSE_STATE_B2: return "B2 - EV Connected (9V, Authorized and Ready)";
|
||||
case EVSE_STATE_C1: return "C1 - Charging Requested (6V, Relay Off)";
|
||||
case EVSE_STATE_C2: return "C2 - Charging Active (6V, Relay On)";
|
||||
case EVSE_STATE_D1: return "D1 - Ventilation Required (3V, Relay Off)";
|
||||
case EVSE_STATE_D2: return "D2 - Ventilation Active (3V, Relay On)";
|
||||
case EVSE_STATE_E: return "E - Error: Control Pilot Shorted to Ground (0V)";
|
||||
case EVSE_STATE_F: return "F - Fault: EVSE Unavailable or No Pilot Signal";
|
||||
default: return "Unknown State";
|
||||
}
|
||||
}
|
||||
|
||||
void evse_state_init(void) {
|
||||
// Inicialização do estado EVSE
|
||||
}
|
||||
|
||||
|
||||
void evse_state_tick(void) {
|
||||
// Tick do estado (placeholder)
|
||||
}
|
||||
|
||||
bool evse_state_is_charging(evse_state_t state) {
|
||||
return state == EVSE_STATE_C1 || state == EVSE_STATE_C2;
|
||||
}
|
||||
|
||||
bool evse_state_is_plugged(evse_state_t state) {
|
||||
return state == EVSE_STATE_B1 || state == EVSE_STATE_B2 ||
|
||||
state == EVSE_STATE_C1 || state == EVSE_STATE_C2 ||
|
||||
state == EVSE_STATE_D1 || state == EVSE_STATE_D2;
|
||||
}
|
||||
|
||||
bool evse_state_is_session(evse_state_t state) {
|
||||
return state == EVSE_STATE_B2 || state == EVSE_STATE_C1 || state == EVSE_STATE_C2;
|
||||
}
|
||||
70
components/evse/include/evse_api.h
Normal file
70
components/evse/include/evse_api.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#ifndef EVSE_API_H
|
||||
#define EVSE_API_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "evse_state.h" // Define evse_state_t
|
||||
|
||||
// Inicialização
|
||||
void evse_init(void);
|
||||
void evse_process(void);
|
||||
|
||||
// Estado
|
||||
evse_state_t evse_get_state(void);
|
||||
const char* evse_state_to_str(evse_state_t state);
|
||||
bool evse_is_connector_plugged(evse_state_t state);
|
||||
bool evse_is_limit_reached(void);
|
||||
|
||||
// Autorização e disponibilidade
|
||||
bool evse_is_enabled(void);
|
||||
void evse_set_enabled(bool value);
|
||||
bool evse_is_available(void);
|
||||
void evse_set_available(bool value);
|
||||
bool evse_is_require_auth(void);
|
||||
void evse_set_require_auth(bool value);
|
||||
void evse_authorize(void);
|
||||
bool evse_is_pending_auth(void);
|
||||
void evse_set_authorized(bool value);
|
||||
|
||||
// Corrente
|
||||
uint16_t evse_get_charging_current(void);
|
||||
esp_err_t evse_set_charging_current(uint16_t value);
|
||||
uint16_t evse_get_default_charging_current(void);
|
||||
esp_err_t evse_set_default_charging_current(uint16_t value);
|
||||
uint8_t evse_get_max_charging_current(void);
|
||||
esp_err_t evse_set_max_charging_current(uint8_t value);
|
||||
|
||||
// Grid
|
||||
uint8_t grid_get_max_current(void);
|
||||
esp_err_t grid_set_max_current(uint8_t value);
|
||||
|
||||
// Temperatura
|
||||
uint8_t evse_get_temp_threshold(void);
|
||||
esp_err_t evse_set_temp_threshold(uint8_t value);
|
||||
|
||||
// RCM / Socket
|
||||
bool evse_get_socket_outlet(void);
|
||||
esp_err_t evse_set_socket_outlet(bool value);
|
||||
bool evse_is_rcm(void);
|
||||
esp_err_t evse_set_rcm(bool value);
|
||||
|
||||
// Limites
|
||||
uint32_t evse_get_consumption_limit(void);
|
||||
void evse_set_consumption_limit(uint32_t value);
|
||||
uint32_t evse_get_charging_time_limit(void);
|
||||
void evse_set_charging_time_limit(uint32_t value);
|
||||
uint16_t evse_get_under_power_limit(void);
|
||||
void evse_set_under_power_limit(uint16_t value);
|
||||
|
||||
void evse_set_limit_reached(uint8_t value);
|
||||
|
||||
// Limites default
|
||||
uint32_t evse_get_default_consumption_limit(void);
|
||||
void evse_set_default_consumption_limit(uint32_t value);
|
||||
uint32_t evse_get_default_charging_time_limit(void);
|
||||
void evse_set_default_charging_time_limit(uint32_t value);
|
||||
uint16_t evse_get_default_under_power_limit(void);
|
||||
void evse_set_default_under_power_limit(uint16_t value);
|
||||
|
||||
#endif // EVSE_API_H
|
||||
78
components/evse/include/evse_config.h
Executable file
78
components/evse/include/evse_config.h
Executable file
@@ -0,0 +1,78 @@
|
||||
#ifndef EVSE_CONFIG_H
|
||||
#define EVSE_CONFIG_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// ========================
|
||||
// Limites Globais (Defines)
|
||||
// ========================
|
||||
|
||||
// Corrente máxima de carregamento (configurável pelo usuário)
|
||||
#define MIN_CHARGING_CURRENT_LIMIT 6 // A
|
||||
#define MAX_CHARGING_CURRENT_LIMIT 16 // A
|
||||
|
||||
// Corrente máxima da rede elétrica (grid)
|
||||
#define MIN_GRID_CURRENT_LIMIT 6 // A
|
||||
#define MAX_GRID_CURRENT_LIMIT 100 // A
|
||||
|
||||
// Corrente via cabo (proximity) — se configurável
|
||||
#define MIN_CABLE_CURRENT_LIMIT 6 // A
|
||||
#define MAX_CABLE_CURRENT_LIMIT 63 // A
|
||||
|
||||
// ========================
|
||||
// Funções de Configuração
|
||||
// ========================
|
||||
|
||||
// Inicialização
|
||||
esp_err_t evse_config_init(void);
|
||||
void evse_check_defaults(void);
|
||||
|
||||
// Corrente de carregamento
|
||||
uint8_t evse_get_max_charging_current(void);
|
||||
esp_err_t evse_set_max_charging_current(uint8_t value);
|
||||
|
||||
uint16_t evse_get_charging_current(void);
|
||||
esp_err_t evse_set_charging_current(uint16_t value);
|
||||
|
||||
uint16_t evse_get_default_charging_current(void);
|
||||
esp_err_t evse_set_default_charging_current(uint16_t value);
|
||||
|
||||
// Corrente da rede elétrica
|
||||
uint8_t grid_get_max_current(void);
|
||||
esp_err_t grid_set_max_current(uint8_t value);
|
||||
|
||||
// Configuração de socket outlet
|
||||
bool evse_get_socket_outlet(void);
|
||||
esp_err_t evse_set_socket_outlet(bool socket_outlet);
|
||||
|
||||
// RCM
|
||||
bool evse_is_rcm(void);
|
||||
esp_err_t evse_set_rcm(bool rcm);
|
||||
|
||||
// Temperatura
|
||||
uint8_t evse_get_temp_threshold(void);
|
||||
esp_err_t evse_set_temp_threshold(uint8_t threshold);
|
||||
|
||||
// Autenticação
|
||||
bool evse_is_require_auth(void);
|
||||
void evse_set_require_auth(bool require);
|
||||
|
||||
// Disponibilidade
|
||||
bool evse_config_is_available(void);
|
||||
void evse_config_set_available(bool available);
|
||||
|
||||
// Ativação/desativação do EVSE
|
||||
bool evse_config_is_enabled(void);
|
||||
void evse_config_set_enabled(bool enabled);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // EVSE_CONFIG_H
|
||||
45
components/evse/include/evse_error.h
Executable file
45
components/evse/include/evse_error.h
Executable file
@@ -0,0 +1,45 @@
|
||||
#ifndef EVSE_ERROR_H
|
||||
#define EVSE_ERROR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "pilot.h"
|
||||
|
||||
|
||||
#define EVSE_ERR_AUTO_CLEAR_BITS ( \
|
||||
EVSE_ERR_DIODE_SHORT_BIT | \
|
||||
EVSE_ERR_TEMPERATURE_HIGH_BIT | \
|
||||
EVSE_ERR_RCM_TRIGGERED_BIT )
|
||||
|
||||
// Error bits
|
||||
#define EVSE_ERR_DIODE_SHORT_BIT (1 << 0)
|
||||
#define EVSE_ERR_LOCK_FAULT_BIT (1 << 1)
|
||||
#define EVSE_ERR_UNLOCK_FAULT_BIT (1 << 2)
|
||||
#define EVSE_ERR_RCM_SELFTEST_FAULT_BIT (1 << 3)
|
||||
#define EVSE_ERR_RCM_TRIGGERED_BIT (1 << 4)
|
||||
#define EVSE_ERR_TEMPERATURE_HIGH_BIT (1 << 5)
|
||||
#define EVSE_ERR_PILOT_FAULT_BIT (1 << 6)
|
||||
#define EVSE_ERR_TEMPERATURE_FAULT_BIT (1 << 7)
|
||||
|
||||
// Inicialização do módulo de erros
|
||||
void evse_error_init(void);
|
||||
|
||||
// Verificações e monitoramento
|
||||
void evse_error_check(pilot_voltage_t pilot_voltage, bool is_n12v);
|
||||
|
||||
void evse_temperature_check(void);
|
||||
|
||||
void evse_error_tick(void);
|
||||
|
||||
// Leitura e controle de erros
|
||||
uint32_t evse_get_error(void);
|
||||
bool evse_is_error_cleared(void);
|
||||
void evse_mark_error_cleared(void);
|
||||
void evse_error_set(uint32_t bitmask);
|
||||
void evse_error_clear(uint32_t bitmask);
|
||||
bool evse_error_is_active(void);
|
||||
uint32_t evse_error_get_bits(void);
|
||||
void evse_error_reset_flag(void);
|
||||
bool evse_error_cleared_flag(void);
|
||||
|
||||
#endif // EVSE_ERROR_H
|
||||
33
components/evse/include/evse_events.h
Executable file
33
components/evse/include/evse_events.h
Executable file
@@ -0,0 +1,33 @@
|
||||
#ifndef EVSE_EVENTS_H
|
||||
#define EVSE_EVENTS_H
|
||||
|
||||
#include "evse_api.h"
|
||||
#include "esp_event_base.h"
|
||||
|
||||
// Certifique-se de que ESP_EVENT_DECLARE_BASE seja corretamente reconhecido
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Declaração da base de eventos EVSE (será definida em evse_events.c)
|
||||
ESP_EVENT_DECLARE_BASE(EVSE_EVENT);
|
||||
|
||||
typedef enum {
|
||||
EVSE_EVENT_STATE_CHANGED,
|
||||
EVSE_EVENT_ERROR,
|
||||
EVSE_EVENT_ERROR_CLEARED,
|
||||
EVSE_EVENT_LIMIT_REACHED,
|
||||
EVSE_EVENT_AUTH_GRANTED
|
||||
} evse_event_id_t;
|
||||
|
||||
// Estrutura do evento de mudança de estado
|
||||
typedef struct {
|
||||
evse_state_t previous;
|
||||
evse_state_t current;
|
||||
} evse_event_state_changed_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // EVSE_EVENTS_H
|
||||
37
components/evse/include/evse_fsm.h
Executable file
37
components/evse/include/evse_fsm.h
Executable file
@@ -0,0 +1,37 @@
|
||||
#ifndef EVSE_FSM_H
|
||||
#define EVSE_FSM_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "evse_api.h"
|
||||
#include "pilot.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Reinicia a máquina de estados do EVSE para o estado inicial (A).
|
||||
*/
|
||||
void evse_fsm_reset(void);
|
||||
|
||||
/**
|
||||
* @brief Processa uma leitura do sinal de piloto e atualiza a máquina de estados do EVSE.
|
||||
*
|
||||
* Esta função deve ser chamada periodicamente pelo núcleo de controle para
|
||||
* avaliar mudanças no estado do conector, disponibilidade do carregador e
|
||||
* autorização do usuário.
|
||||
*
|
||||
* @param pilot_voltage Leitura atual da tensão do sinal piloto.
|
||||
* @param authorized Indica se o carregamento foi autorizado.
|
||||
* @param available Indica se o carregador está disponível (ex: sem falhas).
|
||||
* @param enabled Indica se o carregador está habilitado via software.
|
||||
*/
|
||||
void evse_fsm_process(pilot_voltage_t pilot_voltage, bool authorized, bool available, bool enabled);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // EVSE_FSM_H
|
||||
71
components/evse/include/evse_hardware.h
Normal file
71
components/evse/include/evse_hardware.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifndef EVSE_HARDWARE_H
|
||||
#define EVSE_HARDWARE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Inicializa todos os periféricos de hardware do EVSE (pilot, relé, trava, etc.)
|
||||
*/
|
||||
void evse_hardware_init(void);
|
||||
|
||||
/**
|
||||
* @brief Executa atualizações periódicas no hardware (tick)
|
||||
*/
|
||||
void evse_hardware_tick(void);
|
||||
|
||||
/**
|
||||
* @brief Verifica se o sinal piloto está em nível alto (12V)
|
||||
*/
|
||||
bool evse_hardware_is_pilot_high(void);
|
||||
|
||||
/**
|
||||
* @brief Verifica se o veículo está fisicamente conectado via Proximity
|
||||
*/
|
||||
bool evse_hardware_is_vehicle_connected(void);
|
||||
|
||||
/**
|
||||
* @brief Verifica se há consumo de energia (corrente detectada)
|
||||
*/
|
||||
bool evse_hardware_is_energy_detected(void);
|
||||
|
||||
/**
|
||||
* @brief Liga o relé de fornecimento de energia
|
||||
*/
|
||||
void evse_hardware_relay_on(void);
|
||||
|
||||
/**
|
||||
* @brief Desliga o relé de fornecimento de energia
|
||||
*/
|
||||
void evse_hardware_relay_off(void);
|
||||
|
||||
/**
|
||||
* @brief Consulta o estado atual do relé
|
||||
* @return true se ligado, false se desligado
|
||||
*/
|
||||
bool evse_hardware_relay_status(void);
|
||||
|
||||
/**
|
||||
* @brief Aciona a trava física do conector
|
||||
*/
|
||||
void evse_hardware_lock(void);
|
||||
|
||||
/**
|
||||
* @brief Libera a trava física do conector
|
||||
*/
|
||||
void evse_hardware_unlock(void);
|
||||
|
||||
/**
|
||||
* @brief Verifica se o conector está travado
|
||||
*/
|
||||
bool evse_hardware_is_locked(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // EVSE_HARDWARE_H
|
||||
43
components/evse/include/evse_limits.h
Executable file
43
components/evse/include/evse_limits.h
Executable file
@@ -0,0 +1,43 @@
|
||||
#ifndef EVSE_LIMITS_H
|
||||
#define EVSE_LIMITS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "evse_state.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// Estado dos limites
|
||||
void evse_set_limit_reached(uint8_t value);
|
||||
bool evse_is_limit_reached(void);
|
||||
|
||||
/// Verifica e aplica lógica de limites com base no estado atual do EVSE
|
||||
void evse_limits_check(evse_state_t state);
|
||||
|
||||
/// Limites ativos (runtime)
|
||||
uint32_t evse_get_consumption_limit(void);
|
||||
void evse_set_consumption_limit(uint32_t value);
|
||||
|
||||
uint32_t evse_get_charging_time_limit(void);
|
||||
void evse_set_charging_time_limit(uint32_t value);
|
||||
|
||||
uint16_t evse_get_under_power_limit(void);
|
||||
void evse_set_under_power_limit(uint16_t value);
|
||||
|
||||
/// Limites padrão (persistentes)
|
||||
uint32_t evse_get_default_consumption_limit(void);
|
||||
void evse_set_default_consumption_limit(uint32_t value);
|
||||
|
||||
uint32_t evse_get_default_charging_time_limit(void);
|
||||
void evse_set_default_charging_time_limit(uint32_t value);
|
||||
|
||||
uint16_t evse_get_default_under_power_limit(void);
|
||||
void evse_set_default_under_power_limit(uint16_t value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // EVSE_LIMITS_H
|
||||
63
components/evse/include/evse_manager.h
Normal file
63
components/evse/include/evse_manager.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef EVSE_MANAGER_H
|
||||
#define EVSE_MANAGER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "evse_state.h"
|
||||
#include "evse_error.h"
|
||||
#include "evse_config.h"
|
||||
|
||||
/**
|
||||
* @brief Inicializa todos os módulos do EVSE e inicia a tarefa de supervisão periódica.
|
||||
*/
|
||||
void evse_manager_init(void);
|
||||
|
||||
/**
|
||||
* @brief Executa uma iteração do ciclo de controle do EVSE (chamada automaticamente pela task).
|
||||
*
|
||||
* Você normalmente não precisa chamar isso manualmente.
|
||||
*/
|
||||
void evse_manager_tick(void);
|
||||
|
||||
/**
|
||||
* @brief Verifica se o EVSE está disponível para conexão (não bloqueado, sem falha crítica, etc).
|
||||
*/
|
||||
bool evse_manager_is_available(void);
|
||||
|
||||
/**
|
||||
* @brief Define se o EVSE deve estar disponível.
|
||||
*
|
||||
* Pode ser usado, por exemplo, para bloquear carregamento via comando remoto.
|
||||
*/
|
||||
void evse_manager_set_available(bool available);
|
||||
|
||||
/**
|
||||
* @brief Define se o EVSE está autorizado a iniciar carregamento (ex: após autenticação).
|
||||
*/
|
||||
void evse_manager_set_authorized(bool authorized);
|
||||
|
||||
/**
|
||||
* @brief Verifica se o EVSE está em estado de carregamento ativo.
|
||||
*/
|
||||
bool evse_manager_is_charging(void);
|
||||
|
||||
/**
|
||||
* @brief Ativa ou desativa o EVSE (liga/desliga logicamente o carregamento).
|
||||
*/
|
||||
void evse_manager_set_enabled(bool enabled);
|
||||
|
||||
/**
|
||||
* @brief Verifica se o EVSE está ativado logicamente.
|
||||
*/
|
||||
bool evse_manager_is_enabled(void);
|
||||
|
||||
void evse_manager_task(void *arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // EVSE_MANAGER_H
|
||||
42
components/evse/include/evse_state.h
Normal file
42
components/evse/include/evse_state.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef EVSE_STATE_H
|
||||
#define EVSE_STATE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
// Estado do EVSE (pilot signal)
|
||||
typedef enum {
|
||||
EVSE_STATE_A,
|
||||
EVSE_STATE_B1,
|
||||
EVSE_STATE_B2,
|
||||
EVSE_STATE_C1,
|
||||
EVSE_STATE_C2,
|
||||
EVSE_STATE_D1,
|
||||
EVSE_STATE_D2,
|
||||
EVSE_STATE_E,
|
||||
EVSE_STATE_F
|
||||
} evse_state_t;
|
||||
|
||||
|
||||
// Funções públicas necessárias
|
||||
void evse_state_init(void);
|
||||
void evse_state_tick(void);
|
||||
|
||||
void evse_state_set_authorized(bool authorized);
|
||||
|
||||
evse_state_t evse_get_state(void);
|
||||
|
||||
void evse_set_state(evse_state_t state);
|
||||
|
||||
// Converte o estado para string
|
||||
const char* evse_state_to_str(evse_state_t state);
|
||||
|
||||
// Retorna true se o estado representa sessão ativa
|
||||
bool evse_state_is_session(evse_state_t state);
|
||||
|
||||
// Retorna true se o estado representa carregamento ativo
|
||||
bool evse_state_is_charging(evse_state_t state);
|
||||
|
||||
// Retorna true se o estado representa veículo conectado
|
||||
bool evse_state_is_plugged(evse_state_t state);
|
||||
|
||||
#endif // EVSE_STATE_H
|
||||
Reference in New Issue
Block a user