fix ade7758

This commit is contained in:
2025-06-25 06:34:03 +01:00
parent a0b2e048d4
commit 84f106eee5
53 changed files with 7079 additions and 18456 deletions

View File

@@ -9,6 +9,7 @@ set(srcs
evse_manager.c
evse_hardware.c
evse_pilot.c
evse_meter.c
)
idf_component_register(

View File

@@ -1,4 +1,4 @@
// evse_core.c - Função principal de controle do EVSE
// evse_core.c - Main EVSE control logic
#include "evse_fsm.h"
#include "evse_error.h"
@@ -13,23 +13,30 @@
static const char *TAG = "evse_core";
static SemaphoreHandle_t mutex;
static evse_state_t last_state = EVSE_STATE_A;
static void evse_core_task(void *arg);
// ================================
// Initialization
// ================================
void evse_init(void) {
ESP_LOGI(TAG, "EVSE Init");
mutex = xSemaphoreCreateMutex();
mutex = xSemaphoreCreateMutex(); // Optional: use static version for deterministic memory
evse_check_defaults();
evse_fsm_reset();
pilot_set_level(true); // Estado inicial do piloto
pilot_set_level(true); // Enable pilot output
xTaskCreate(evse_core_task, "evse_core_task", 4096, NULL, 5, NULL);
}
// ================================
// Main Processing Logic
// ================================
void evse_process(void) {
xSemaphoreTake(mutex, portMAX_DELAY);
@@ -39,42 +46,36 @@ void evse_process(void) {
pilot_measure(&pilot_voltage, &is_n12v);
ESP_LOGD(TAG, "Pilot: %d, -12V: %s", pilot_voltage, is_n12v ? "yes" : "no");
if (evse_get_error() == 0 && !evse_is_error_cleared()) {
evse_error_check(pilot_voltage, is_n12v);
evse_error_check(pilot_voltage, is_n12v);
// Só chama FSM, que decide tudo
evse_fsm_process(
pilot_voltage,
evse_state_get_authorized(),
evse_config_is_available(),
evse_config_is_enabled()
);
evse_fsm_process(
pilot_voltage,
evse_state_get_authorized(),
evse_config_is_available(),
evse_config_is_enabled()
);
evse_limits_check();
evse_limits_check();
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;
}
evse_mark_error_cleared();
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;
}
evse_mark_error_cleared();
xSemaphoreGive(mutex);
}
// ================================
// Interface pública
// Public Configuration Interface
// ================================
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);
@@ -90,21 +91,12 @@ void evse_set_available(bool value) {
}
// ================================
// Tarefa principal
// Background Task
// ================================
static void evse_core_task(void *arg) {
while (true) {
evse_process();
vTaskDelay(pdMS_TO_TICKS(100));
vTaskDelay(pdMS_TO_TICKS(100)); // 10 Hz cycle
}
}
uint32_t evse_get_total_energy(void) {
return 0; // Stub de 1 kWh
}
uint32_t evse_get_instant_power(void) {
return 0; // Stub de 2 kW
}
}

View File

@@ -1,5 +1,3 @@
// evse_fsm.c - Máquina de Estados EVSE com controle centralizado
#include "evse_fsm.h"
#include "evse_api.h"
#include "evse_pilot.h"
@@ -11,6 +9,7 @@
#include "proximity.h"
#include "rcm.h"
#include "evse_state.h"
#include "evse_error.h"
static const char *TAG = "evse_fsm";
@@ -27,6 +26,8 @@ void evse_fsm_reset(void) {
c1_d1_relay_to = 0;
}
// ... includes e defines como já estão
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();
@@ -36,6 +37,21 @@ 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
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) {
socket_lock_set_locked(false);
}
return;
}
// Fluxo normal
switch (state) {
case EVSE_STATE_A:
case EVSE_STATE_E:
@@ -53,7 +69,6 @@ static void update_outputs(evse_state_t state) {
if (board_config.socket_lock && socket_outlet) {
socket_lock_set_locked(true);
}
if (rcm_test()) {
ESP_LOGI(TAG, "RCM self test passed");
} else {
@@ -76,12 +91,28 @@ static void update_outputs(evse_state_t state) {
case EVSE_STATE_C2:
case EVSE_STATE_D2:
pilot_set_amps(MIN(current * 10, cable_max_current * 10));
ac_relay_set_state(true);
ac_relay_set_state(true); // Só chega aqui se não há erro!
break;
}
}
void evse_fsm_process(pilot_voltage_t pilot_voltage, bool authorized, bool available, bool enabled) {
// FSM principal - centraliza a lógica de erro e de todos os estados
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) {
if (evse_get_state() != EVSE_STATE_F) {
ESP_LOGW(TAG, "Erro ativo detectado: forçando estado FAULT (F)");
evse_set_state(EVSE_STATE_F);
}
update_outputs(EVSE_STATE_F);
return;
}
TickType_t now = xTaskGetTickCount();
evse_state_t prev = evse_get_state();
evse_state_t curr = prev;
@@ -101,7 +132,6 @@ void evse_fsm_process(pilot_voltage_t pilot_voltage, bool authorized, bool avail
evse_set_state(EVSE_STATE_F);
break;
}
switch (pilot_voltage) {
case PILOT_VOLTAGE_12:
evse_set_state(EVSE_STATE_A);
@@ -127,15 +157,15 @@ void evse_fsm_process(pilot_voltage_t pilot_voltage, bool authorized, bool avail
break;
}
}
__attribute__((fallthrough)); // Evita warning de fallthrough implícito
__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);
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);
@@ -155,18 +185,23 @@ void evse_fsm_process(pilot_voltage_t pilot_voltage, bool authorized, bool avail
break;
case EVSE_STATE_E:
break; // Sem transições a partir de E
// Estado elétrico grave: só reset manual
break;
case EVSE_STATE_F:
if (available) {
// 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));
update_outputs(next);
ESP_LOGI(TAG, "State changed: %s -> %s",
evse_state_to_str(prev),
evse_state_to_str(next));
}
}

View File

@@ -1,6 +1,7 @@
#include "evse_state.h"
#include "evse_api.h"
#include "evse_limits.h"
#include "evse_meter.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@@ -146,8 +147,8 @@ void evse_limits_check(void) {
bool reached = false;
uint32_t energy = evse_get_total_energy();
uint32_t power = evse_get_instant_power();
uint32_t energy = evse_meter_get_total_energy();
uint32_t power = evse_meter_get_instant_power();
TickType_t now = xTaskGetTickCount();
TickType_t start = evse_get_session_start();

View File

@@ -4,6 +4,7 @@
#include "evse_hardware.h"
#include "evse_config.h"
#include "evse_api.h"
#include "evse_meter.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@@ -87,6 +88,7 @@ void evse_manager_init(void) {
evse_error_init();
evse_hardware_init();
evse_state_init();
evse_meter_init();
ESP_ERROR_CHECK(esp_event_handler_register(AUTH_EVENTS, ESP_EVENT_ANY_ID, &on_auth_event, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(LOADBALANCER_EVENTS, ESP_EVENT_ANY_ID, &on_loadbalancer_event, NULL));
@@ -120,29 +122,3 @@ void evse_manager_tick(void) {
xSemaphoreGive(evse_mutex);
}
// ===== API pública =====
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();
}

View File

@@ -0,0 +1,105 @@
#include "evse_meter.h"
#include "meter_events.h"
#include "esp_event.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include <string.h>
#include <inttypes.h>
static const char *TAG = "evse_meter";
static SemaphoreHandle_t meter_mutex;
typedef struct {
uint32_t power_watts[EVSE_METER_PHASE_COUNT];
float voltage[EVSE_METER_PHASE_COUNT];
float current[EVSE_METER_PHASE_COUNT];
uint32_t energy_wh;
} evse_meter_data_t;
static evse_meter_data_t meter_data;
static void on_meter_event_dispatcher(void* arg, esp_event_base_t base, int32_t id, void* data) {
if (base == METER_EVENT && id == METER_EVENT_DATA_READY && data) {
const meter_event_data_t *evt = (const meter_event_data_t *)data;
if (strcmp(evt->source, "EVSE") == 0) {
evse_meter_on_meter_event(arg, data);
}
}
}
void evse_meter_on_meter_event(void* arg, void* event_data) {
const meter_event_data_t *evt = (const meter_event_data_t *)event_data;
if (!evt) return;
xSemaphoreTake(meter_mutex, portMAX_DELAY);
for (int i = 0; i < EVSE_METER_PHASE_COUNT; ++i) {
meter_data.power_watts[i] = evt->watt[i];
meter_data.voltage[i] = evt->vrms[i];
meter_data.current[i] = evt->irms[i];
}
meter_data.energy_wh = (uint32_t)(evt->total_energy * 1000.0f);
xSemaphoreGive(meter_mutex);
ESP_LOGD(TAG,
"Meter updated: power[W]={%" PRIu32 ",%" PRIu32 ",%" PRIu32 "}, "
"voltage[V]={%.2f,%.2f,%.2f}, "
"current[A]={%.2f,%.2f,%.2f}, "
"total_energy=%" PRIu32 "Wh",
meter_data.power_watts[0], meter_data.power_watts[1], meter_data.power_watts[2],
meter_data.voltage[0], meter_data.voltage[1], meter_data.voltage[2],
meter_data.current[0], meter_data.current[1], meter_data.current[2],
meter_data.energy_wh
);
}
void evse_meter_init(void) {
meter_mutex = xSemaphoreCreateMutex();
ESP_ERROR_CHECK(meter_mutex ? ESP_OK : ESP_FAIL);
ESP_ERROR_CHECK(esp_event_handler_register(
METER_EVENT, METER_EVENT_DATA_READY,
on_meter_event_dispatcher, NULL));
memset(&meter_data, 0, sizeof(meter_data));
ESP_LOGI(TAG, "EVSE Meter listener registered.");
}
uint32_t evse_meter_get_instant_power(void) {
xSemaphoreTake(meter_mutex, portMAX_DELAY);
uint32_t sum = 0;
for (int i = 0; i < EVSE_METER_PHASE_COUNT; ++i) {
sum += meter_data.power_watts[i];
}
xSemaphoreGive(meter_mutex);
return sum;
}
uint32_t evse_meter_get_total_energy(void) {
xSemaphoreTake(meter_mutex, portMAX_DELAY);
uint32_t val = meter_data.energy_wh;
xSemaphoreGive(meter_mutex);
return val;
}
void evse_meter_get_power(uint32_t power[EVSE_METER_PHASE_COUNT]) {
xSemaphoreTake(meter_mutex, portMAX_DELAY);
for (int i = 0; i < EVSE_METER_PHASE_COUNT; ++i) {
power[i] = meter_data.power_watts[i];
}
xSemaphoreGive(meter_mutex);
}
void evse_meter_get_voltage(float voltage[EVSE_METER_PHASE_COUNT]) {
xSemaphoreTake(meter_mutex, portMAX_DELAY);
for (int i = 0; i < EVSE_METER_PHASE_COUNT; ++i) {
voltage[i] = meter_data.voltage[i];
}
xSemaphoreGive(meter_mutex);
}
void evse_meter_get_current(float current[EVSE_METER_PHASE_COUNT]) {
xSemaphoreTake(meter_mutex, portMAX_DELAY);
for (int i = 0; i < EVSE_METER_PHASE_COUNT; ++i) {
current[i] = meter_data.current[i];
}
xSemaphoreGive(meter_mutex);
}

View File

@@ -10,7 +10,7 @@
#include "esp_rom_sys.h"
#include "evse_pilot.h"
#include "adc.h"
#include "adc121s021_dma.h"
#include "board_config.h"
#define PILOT_PWM_TIMER LEDC_TIMER_0
@@ -23,10 +23,24 @@
#define MAX_SAMPLE_ATTEMPTS 1000
#define PILOT_EXTREME_PERCENT 10 // 10% superior e inferior
// ADC121S021 setup
#define ADC121_VREF_MV 3300 // AJUSTE conforme Vref do seu hardware!
#define ADC121_MAX 4095 // 12 bits
static const char *TAG = "evse_pilot";
// Memoização de estado para evitar comandos/logs desnecessários
static int last_pilot_level = -1;
static uint32_t last_pwm_duty = 0;
// Função para converter leitura bruta do ADC para mV
static int adc_raw_to_mv(uint16_t raw) {
return (raw * ADC121_VREF_MV) / ADC121_MAX;
}
void pilot_init(void)
{
// PWM (LEDC) configuração
ledc_timer_config_t ledc_timer = {
.speed_mode = PILOT_PWM_SPEED_MODE,
.timer_num = PILOT_PWM_TIMER,
@@ -47,27 +61,24 @@ void pilot_init(void)
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
ESP_ERROR_CHECK(ledc_stop(PILOT_PWM_SPEED_MODE, PILOT_PWM_CHANNEL, 0));
ESP_ERROR_CHECK(ledc_fade_func_install(0));
adc_oneshot_chan_cfg_t config = {
.bitwidth = ADC_BITWIDTH_DEFAULT,
.atten = ADC_ATTEN_DB_12,
};
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle, board_config.pilot_adc_channel, &config));
// Inicializa ADC121S021 externo
adc121s021_dma_init();
}
void pilot_set_level(bool level)
{
if (last_pilot_level == level) return; // só muda se necessário
last_pilot_level = level;
ESP_LOGI(TAG, "Set level %d", level);
ledc_stop(PILOT_PWM_SPEED_MODE, PILOT_PWM_CHANNEL, level ? 1 : 0);
last_pwm_duty = 0; // PWM parado
}
void pilot_set_amps(uint16_t amps)
{
ESP_LOGI(TAG, "Set amps %d", amps);
if (amps < 60 || amps > 800) {
ESP_LOGE(TAG, "Invalid ampere value: %d A*10", amps);
return;
@@ -79,14 +90,17 @@ void pilot_set_amps(uint16_t amps)
} else {
duty = ((PILOT_PWM_MAX_DUTY * amps) / 2500) + (64 * (PILOT_PWM_MAX_DUTY / 100));
}
if (duty > PILOT_PWM_MAX_DUTY) duty = PILOT_PWM_MAX_DUTY;
if (duty > PILOT_PWM_MAX_DUTY)
duty = PILOT_PWM_MAX_DUTY;
if (last_pilot_level == 0 && last_pwm_duty == duty) return;
last_pilot_level = 0;
last_pwm_duty = duty;
ESP_LOGI(TAG, "Set amp %dA*10 -> duty %lu/%d", amps, duty, PILOT_PWM_MAX_DUTY);
ledc_set_duty(PILOT_PWM_SPEED_MODE, PILOT_PWM_CHANNEL, duty);
ledc_update_duty(PILOT_PWM_SPEED_MODE, PILOT_PWM_CHANNEL);
}
static int compare_int(const void *a, const void *b) {
return (*(int *)a - *(int *)b);
}
@@ -94,10 +108,8 @@ static int compare_int(const void *a, const void *b) {
static int select_low_median_qsort(int *src, int n, int percent) {
int k = (n * percent) / 100;
if (k == 0) k = 1;
int *copy = alloca(n * sizeof(int));
memcpy(copy, src, n * sizeof(int));
qsort(copy, n, sizeof(int), compare_int);
return copy[k / 2];
}
@@ -105,10 +117,8 @@ static int select_low_median_qsort(int *src, int n, int percent) {
static int select_high_median_qsort(int *src, int n, int percent) {
int k = (n * percent) / 100;
if (k == 0) k = 1;
int *copy = alloca(n * sizeof(int));
memcpy(copy, src, n * sizeof(int));
qsort(copy, n, sizeof(int), compare_int);
return copy[n - k + (k / 2)];
}
@@ -119,11 +129,13 @@ void pilot_measure(pilot_voltage_t *up_voltage, bool *down_voltage_n12)
int samples[NUM_PILOT_SAMPLES];
int collected = 0, attempts = 0;
int sample;
uint16_t adc_sample = 0;
// Lê samples usando ADC121S021 externo
while (collected < NUM_PILOT_SAMPLES && attempts < MAX_SAMPLE_ATTEMPTS) {
if (adc_oneshot_read(adc_handle, board_config.pilot_adc_channel, &sample) == ESP_OK) {
samples[collected++] = sample;
adc_sample = 0;
if (adc121s021_dma_get_sample(&adc_sample)) {
samples[collected++] = adc_sample;
esp_rom_delay_us(10);
} else {
esp_rom_delay_us(100);
@@ -141,20 +153,10 @@ void pilot_measure(pilot_voltage_t *up_voltage, bool *down_voltage_n12)
int high_raw = select_high_median_qsort(samples, collected, PILOT_EXTREME_PERCENT);
int low_raw = select_low_median_qsort(samples, collected, PILOT_EXTREME_PERCENT);
int high_mv = adc_raw_to_mv(high_raw);
int low_mv = adc_raw_to_mv(low_raw);
ESP_LOGD(TAG, "Final: high_raw=%d, low_raw=%d", high_raw, low_raw);
int high_mv = 0;
int low_mv = 0;
if (adc_cali_raw_to_voltage(adc_cali_handle, high_raw, &high_mv) != ESP_OK ||
adc_cali_raw_to_voltage(adc_cali_handle, low_raw, &low_mv) != ESP_OK) {
ESP_LOGW(TAG, "ADC calibration failed");
*up_voltage = PILOT_VOLTAGE_1;
*down_voltage_n12 = false;
return;
}
// Aplica thresholds definidos em board_config (em mV)
if (high_mv >= board_config.pilot_down_threshold_12)
*up_voltage = PILOT_VOLTAGE_12;
else if (high_mv >= board_config.pilot_down_threshold_9)

View File

@@ -46,9 +46,14 @@ void evse_set_state(evse_state_t state) {
current_state = state;
changed = true;
// When entering a charging state, record the start tick
if (evse_state_is_charging(state) && !evse_state_is_charging(previous_state)) {
session_start_tick = xTaskGetTickCount();
}
// When exiting a charging state, reset the start tick
else if (!evse_state_is_charging(state) && evse_state_is_charging(previous_state)) {
session_start_tick = 0;
}
}
portEXIT_CRITICAL(&state_mux);
@@ -60,7 +65,11 @@ void evse_set_state(evse_state_t state) {
evse_state_event_data_t evt = {
.state = map_state_to_event(state)
};
esp_event_post(EVSE_EVENTS, EVSE_EVENT_STATE_CHANGED, &evt, sizeof(evt), portMAX_DELAY);
esp_event_post(EVSE_EVENTS,
EVSE_EVENT_STATE_CHANGED,
&evt,
sizeof(evt),
portMAX_DELAY);
}
}

View File

@@ -3,73 +3,77 @@
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "evse_state.h" // Define evse_state_t
#include "evse_state.h" // Tipos e estados
#include "freertos/FreeRTOS.h"
// Inicialização
void evse_init(void);
void evse_process(void);
#ifdef __cplusplus
extern "C" {
#endif
// Estado
// ===============================
// Core EVSE State
// ===============================
/**
* @brief Get current EVSE state (e.g., A, B1, C2).
*/
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);
/**
* @brief Set the EVSE state (e.g., called by FSM or hardware layer).
*/
void evse_set_state(evse_state_t state);
/**
* @brief Get timestamp when the current session started (for timing limits).
*/
TickType_t evse_get_session_start(void);
// ===============================
// Charging Session Info
// ===============================
/**
* @brief Returns true if the EV is charging (C1 or C2).
*/
bool evse_state_is_charging(evse_state_t state);
/**
* @brief Returns true if the EV is connected (plugged).
*/
bool evse_state_is_plugged(evse_state_t state);
/**
* @brief Returns true if a charging session is active (B2, C1, C2).
*/
bool evse_state_is_session(evse_state_t state);
// ===============================
// Authorization
// ===============================
/**
* @brief Set whether the vehicle is authorized to charge.
*/
void evse_state_set_authorized(bool authorized);
/**
* @brief Get current authorization status.
*/
bool evse_state_get_authorized(void);
// ===============================
// Limit Status
// ===============================
/**
* @brief Returns true if any runtime charging limit has been reached.
*/
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);
// 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);
// 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(bool value);
// Energia total acumulada da sessão (em Wh)
uint32_t evse_get_total_energy(void);
// Potência instantânea medida (em W)
uint32_t evse_get_instant_power(void);
// 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);
uint32_t evse_get_total_energy(void);
uint32_t evse_get_instant_power(void);
#ifdef __cplusplus
}
#endif
#endif // EVSE_API_H

View File

@@ -0,0 +1,17 @@
#ifndef EVSE_CORE_H
#define EVSE_CORE_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initializes the EVSE system and starts core task loop.
*/
void evse_init(void);
#ifdef __cplusplus
}
#endif
#endif // EVSE_CORE_H

View File

@@ -9,47 +9,58 @@
extern "C" {
#endif
// ========================
// Limit state control
// ========================
// ============================
// Limit Status & Evaluation
// ============================
/**
* @brief Sets the 'limit reached' flag. Used internally when a session exceeds defined thresholds.
* @brief Sets the internal 'limit reached' flag.
* Called internally when a limit condition is triggered.
*/
void evse_set_limit_reached(bool value);
/**
* @brief Returns whether any session limit has been reached (energy, time or power).
* @brief Returns true if any runtime charging limit has been reached.
*/
bool evse_get_limit_reached(void);
// ========================
// Limit checking
// ========================
/**
* @brief Evaluates if the session has exceeded any configured limits.
* Should be called periodically while in charging state.
* @brief Checks if any session limit has been exceeded (energy, time or power).
* Should be called periodically during charging.
*/
void evse_limits_check(void);
// ========================
// Runtime limit configuration
// ========================
// ============================
// Runtime Limit Configuration
// ============================
/**
* @brief Get/set energy consumption limit (in Wh).
*/
uint32_t evse_get_consumption_limit(void);
void evse_set_consumption_limit(uint32_t value); // in Wh
void evse_set_consumption_limit(uint32_t value);
/**
* @brief Get/set maximum charging time (in seconds).
*/
uint32_t evse_get_charging_time_limit(void);
void evse_set_charging_time_limit(uint32_t value); // in seconds
void evse_set_charging_time_limit(uint32_t value);
/**
* @brief Get/set minimum acceptable power level (in Watts).
* If the power remains below this for a long time, the session may be interrupted.
*/
uint16_t evse_get_under_power_limit(void);
void evse_set_under_power_limit(uint16_t value); // in Watts
void evse_set_under_power_limit(uint16_t value);
// ========================
// Default (persistent) limits
// ========================
// ============================
// Default (Persistent) Limits
// ============================
/**
* @brief Default values used after system boot or reset.
* These can be restored from NVS or fallback values.
*/
uint32_t evse_get_default_consumption_limit(void);
void evse_set_default_consumption_limit(uint32_t value);

View File

@@ -26,38 +26,6 @@ void evse_manager_init(void);
*/
void evse_manager_tick(void);
/**
* @brief Verifica se o EVSE está disponível para uso.
*
* Isso considera falhas críticas, disponibilidade configurada, etc.
*/
bool evse_manager_is_available(void);
/**
* @brief Define se o EVSE deve estar disponível (ex: via controle remoto).
*/
void evse_manager_set_available(bool available);
/**
* @brief Define se o EVSE está autorizado a carregar (ex: após autenticação).
*/
void evse_manager_set_authorized(bool authorized);
/**
* @brief Verifica se o EVSE está atualmente carregando.
*/
bool evse_manager_is_charging(void);
/**
* @brief Ativa ou desativa logicamente o EVSE (controla habilitação geral).
*/
void evse_manager_set_enabled(bool enabled);
/**
* @brief Verifica se o EVSE está ativado logicamente.
*/
bool evse_manager_is_enabled(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,37 @@
#ifndef EVSE_METER_H
#define EVSE_METER_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define EVSE_METER_PHASE_COUNT 3
/// Inicializa o módulo EVSE Meter e registra os tratadores de eventos
void evse_meter_init(void);
/// Retorna a potência instantânea (soma das 3 fases, em watts)
uint32_t evse_meter_get_instant_power(void);
/// Retorna a energia total acumulada (em Wh)
uint32_t evse_meter_get_total_energy(void);
/// Retorna as potências instantâneas nas fases L1, L2 e L3 (em watts)
void evse_meter_get_power(uint32_t power[EVSE_METER_PHASE_COUNT]);
/// Retorna as tensões medidas nas fases L1, L2 e L3 (em volts)
void evse_meter_get_voltage(float voltage[EVSE_METER_PHASE_COUNT]);
/// Retorna as correntes medidas nas fases L1, L2 e L3 (em amperes)
void evse_meter_get_current(float current[EVSE_METER_PHASE_COUNT]);
/// Handler interno para eventos do medidor (não chamar externamente)
void evse_meter_on_meter_event(void* arg, void* event_data);
#ifdef __cplusplus
}
#endif
#endif // EVSE_METER_H

View File

@@ -5,6 +5,10 @@
#include "freertos/FreeRTOS.h"
#include "evse_events.h"
#ifdef __cplusplus
extern "C" {
#endif
// ============================
// EVSE Pilot Signal States
// ============================
@@ -22,21 +26,21 @@ typedef enum {
} evse_state_t;
// ============================
// Initialization & Core Control
// Initialization
// ============================
/**
* @brief Initializes the EVSE state machine.
* @brief Initializes the EVSE state machine and default state.
*/
void evse_state_init(void);
/**
* @brief Periodic tick function for the state machine.
* @brief Periodic tick for state handling (optional hook).
*/
void evse_state_tick(void);
// ============================
// State Access
// State Access & Control
// ============================
/**
@@ -45,51 +49,55 @@ void evse_state_tick(void);
evse_state_t evse_get_state(void);
/**
* @brief Updates the current EVSE state and triggers events.
* @brief Sets the current EVSE state and emits a change event if needed.
*/
void evse_set_state(evse_state_t state);
/**
* @brief Returns the tick count when charging session started.
* @brief Returns the tick count when the current charging session began.
*/
TickType_t evse_get_session_start(void);
/**
* @brief Converts the state enum to a human-readable string.
* @brief Converts the state enum into a human-readable string.
*/
const char* evse_state_to_str(evse_state_t state);
// ============================
// State Evaluators
// State Evaluation Helpers
// ============================
/**
* @brief Returns true if the state represents an active session (B2, C1, C2).
* @brief True if EV is in an active session (B2, C1, C2).
*/
bool evse_state_is_session(evse_state_t state);
/**
* @brief Returns true if the state represents active charging (C1, C2).
* @brief True if EV is actively charging (C1, C2).
*/
bool evse_state_is_charging(evse_state_t state);
/**
* @brief Returns true if the vehicle is plugged in.
* @brief True if EV is physically plugged in (B1 and beyond).
*/
bool evse_state_is_plugged(evse_state_t state);
// ============================
// Authorization
// Authorization Control
// ============================
/**
* @brief Sets the vehicle authorization state.
* @brief Sets whether the EV is authorized to charge.
*/
void evse_state_set_authorized(bool authorized);
/**
* @brief Returns the current vehicle authorization state.
* @brief Gets whether the EV is currently authorized.
*/
bool evse_state_get_authorized(void);
#ifdef __cplusplus
}
#endif
#endif // EVSE_STATE_H