Files
chargeflow/projeto_parte2.c
2025-06-14 11:46:10 +01:00

1167 lines
30 KiB
C
Executable File

// === Início de: components/evse/evse_limits.c ===
#include "evse_state.h"
#include "evse_api.h"
#include "evse_limits.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
// ========================
// External state references
// ========================
//extern evse_state_t current_state; // Current EVSE FSM state
//extern TickType_t session_start_tick; // Timestamp of charging session start
// ========================
// Concurrency protection
// ========================
static portMUX_TYPE evse_mux = portMUX_INITIALIZER_UNLOCKED;
// ========================
// Runtime state (volatile)
// ========================
static bool limit_reached = false;
static uint32_t consumption_limit = 0; // Energy limit in Wh
static uint32_t charging_time_limit = 0; // Time limit in seconds
static uint16_t under_power_limit = 0; // Minimum acceptable power in W
// ========================
// Default (persistent) limits
// ========================
static uint32_t default_consumption_limit = 0;
static uint32_t default_charging_time_limit = 0;
static uint16_t default_under_power_limit = 0;
// ========================
// Limit status flag
// ========================
bool evse_get_limit_reached(void) {
bool val;
portENTER_CRITICAL(&evse_mux);
val = limit_reached;
portEXIT_CRITICAL(&evse_mux);
return val;
}
void evse_set_limit_reached(bool v) {
portENTER_CRITICAL(&evse_mux);
limit_reached = v;
portEXIT_CRITICAL(&evse_mux);
}
// ========================
// Runtime limit accessors
// ========================
uint32_t evse_get_consumption_limit(void) {
uint32_t val;
portENTER_CRITICAL(&evse_mux);
val = consumption_limit;
portEXIT_CRITICAL(&evse_mux);
return val;
}
void evse_set_consumption_limit(uint32_t value) {
portENTER_CRITICAL(&evse_mux);
consumption_limit = value;
portEXIT_CRITICAL(&evse_mux);
}
uint32_t evse_get_charging_time_limit(void) {
uint32_t val;
portENTER_CRITICAL(&evse_mux);
val = charging_time_limit;
portEXIT_CRITICAL(&evse_mux);
return val;
}
void evse_set_charging_time_limit(uint32_t value) {
portENTER_CRITICAL(&evse_mux);
charging_time_limit = value;
portEXIT_CRITICAL(&evse_mux);
}
uint16_t evse_get_under_power_limit(void) {
uint16_t val;
portENTER_CRITICAL(&evse_mux);
val = under_power_limit;
portEXIT_CRITICAL(&evse_mux);
return val;
}
void evse_set_under_power_limit(uint16_t value) {
portENTER_CRITICAL(&evse_mux);
under_power_limit = value;
portEXIT_CRITICAL(&evse_mux);
}
// ========================
// Default (persistent) limit accessors
// These values can be stored/restored via NVS
// ========================
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;
}
bool evse_is_limit_reached(void) {
return evse_get_limit_reached();
}
// ========================
// Limit checking logic
// This function must be called periodically while charging.
// It will flag the session as "limit reached" when thresholds are violated.
// ========================
void evse_limits_check(void) {
evse_state_t state = evse_get_state();
if (!evse_state_is_charging(state)) return;
bool reached = false;
uint32_t energy = evse_get_total_energy();
uint32_t power = evse_get_instant_power();
TickType_t now = xTaskGetTickCount();
TickType_t start = evse_get_session_start();
if (consumption_limit > 0 && energy >= consumption_limit) {
ESP_LOGW("EVSE", "Energy limit reached");
reached = true;
}
if (charging_time_limit > 0 &&
(now - start) >= pdMS_TO_TICKS(charging_time_limit * 1000)) {
ESP_LOGW("EVSE", "Charging time limit reached");
reached = true;
}
if (under_power_limit > 0 && power < under_power_limit) {
ESP_LOGW("EVSE", "Under power limit reached");
reached = true;
}
if (reached) {
evse_set_limit_reached(true);
}
}
// === Fim de: components/evse/evse_limits.c ===
// === Início de: components/evse/evse_config.c ===
#include <inttypes.h> // For PRI macros
#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;
// ========================
// Configurable parameters
// ========================
static uint8_t max_charging_current = MAX_CHARGING_CURRENT_LIMIT;
static uint16_t charging_current; // Persisted (NVS)
static uint16_t charging_current_runtime = 0; // Runtime only
static bool socket_outlet;
static bool rcm;
static uint8_t temp_threshold = 60;
static bool require_auth;
// ========================
// Initialization
// ========================
esp_err_t evse_config_init(void) {
ESP_LOGD(TAG, "Initializing NVS configuration...");
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;
ESP_LOGD(TAG, "Checking default parameters...");
// 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;
ESP_LOGW(TAG, "Invalid or missing max_chrg_curr, resetting to %d", max_charging_current);
} else {
max_charging_current = u8;
}
// Charging current (default, persisted)
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;
ESP_LOGW(TAG, "Invalid or missing def_chrg_curr, resetting to %d", charging_current);
} else {
charging_current = u16;
}
// Runtime charging current initialized from persisted default
charging_current_runtime = charging_current;
ESP_LOGD(TAG, "Runtime charging current initialized to: %d", charging_current_runtime);
// Auth required
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;
}
// Socket outlet
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;
}
// RCM
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;
}
// Temp threshold
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;
}
// Optional limits
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);
// Save to NVS if needed
if (needs_commit) {
err = nvs_commit(nvs);
if (err == ESP_OK) {
ESP_LOGD(TAG, "Configuration committed to NVS.");
} else {
ESP_LOGE(TAG, "Failed to commit configuration to NVS: %s", esp_err_to_name(err));
}
}
}
// ========================
// Charging current getters/setters
// ========================
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);
}
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;
if (nvs_get_u16(nvs, "def_chrg_curr", &value) == ESP_OK)
return value;
return charging_current;
}
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);
}
// ========================
// Runtime current (not saved)
// ========================
void evse_set_runtime_charging_current(uint16_t value) {
if (value < (MIN_CHARGING_CURRENT_LIMIT) || value > (max_charging_current)) {
ESP_LOGW(TAG, "Rejected runtime charging current (out of bounds): %d", value);
return;
}
charging_current_runtime = value;
ESP_LOGD(TAG, "Runtime charging current updated: %d", charging_current_runtime);
}
uint16_t evse_get_runtime_charging_current(void) {
return charging_current_runtime;
}
// ========================
// 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);
}
// ========================
// Temperature
// ========================
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);
}
// ========================
// Authentication
// ========================
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);
}
// ========================
// Availability
// ========================
static bool is_available = true;
bool evse_config_is_available(void) {
return is_available;
}
void evse_config_set_available(bool available) {
is_available = available;
}
// ========================
// Enable/Disable
// ========================
static bool is_enabled = true;
bool evse_config_is_enabled(void) {
return is_enabled;
}
void evse_config_set_enabled(bool enabled) {
is_enabled = enabled;
}
// === Fim de: components/evse/evse_config.c ===
// === Início de: components/evse/evse_manager.c ===
#include "evse_manager.h"
#include "evse_state.h"
#include "evse_error.h"
#include "evse_hardware.h"
#include "evse_config.h"
#include "evse_api.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include <string.h>
#include "auth_events.h"
#include "loadbalancer_events.h"
#include "esp_event.h"
static const char *TAG = "EVSE_Manager";
static SemaphoreHandle_t evse_mutex;
static bool auth_enabled = false;
#define EVSE_MANAGER_TICK_PERIOD_MS 1000 // 1 segundo
// ===== Task de ciclo principal =====
static void evse_manager_task(void *arg) {
while (true) {
evse_manager_tick();
vTaskDelay(pdMS_TO_TICKS(EVSE_MANAGER_TICK_PERIOD_MS));
}
}
// ===== Tratador de eventos de autenticação =====
static void on_auth_event(void* arg, esp_event_base_t base, int32_t id, void* data) {
if (base != AUTH_EVENTS || data == NULL) return;
switch (id) {
case AUTH_EVENT_TAG_PROCESSED: {
auth_tag_event_data_t *evt = (auth_tag_event_data_t*)data;
ESP_LOGI("EVSE", "Tag: %s | Autorizada: %s", evt->tag, evt->authorized ? "SIM" : "NÃO");
evse_state_set_authorized(evt->authorized);
break;
}
case AUTH_EVENT_ENABLED_CHANGED:
case AUTH_EVENT_INIT: {
auth_enabled_event_data_t *evt = (auth_enabled_event_data_t*)data;
auth_enabled = evt->enabled;
ESP_LOGI("EVSE", "Auth %s (%s)",
id == AUTH_EVENT_ENABLED_CHANGED ? "ficou" : "init",
evt->enabled ? "ATIVO" : "INATIVO");
if (!auth_enabled) {
evse_state_set_authorized(true);
ESP_LOGI("EVSE", "Autenticação desativada → autorização forçada.");
} else {
evse_state_set_authorized(false);
ESP_LOGI("EVSE", "Autenticação ativada → aguardando autorização por tag.");
}
break;
}
}
}
// ===== Tratador de eventos de loadbalancer =====
static void on_loadbalancer_event(void* handler_arg, esp_event_base_t event_base,
int32_t event_id, void* event_data) {
if (event_id == LOADBALANCER_EVENT_INIT || event_id == LOADBALANCER_EVENT_STATE_CHANGED) {
const loadbalancer_state_event_t* evt = (const loadbalancer_state_event_t*) event_data;
ESP_LOGI(TAG, "Loadbalancer %s (ts: %lld)",
evt->enabled ? "ENABLED" : "DISABLED", evt->timestamp_us);
// Ações adicionais podem ser adicionadas aqui conforme necessário
} else if (event_id == LOADBALANCER_EVENT_CHARGING_LIMIT_CHANGED) {
const loadbalancer_charging_limit_event_t* evt = (const loadbalancer_charging_limit_event_t*) event_data;
ESP_LOGD(TAG, "Novo limite de corrente: %.1f A (ts: %lld)", evt->limit, evt->timestamp_us);
evse_set_runtime_charging_current((uint16_t)(evt->limit));
}
}
// ===== Inicialização =====
void evse_manager_init(void) {
evse_mutex = xSemaphoreCreateMutex();
evse_config_init();
evse_error_init();
evse_hardware_init();
evse_state_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));
ESP_LOGI(TAG, "EVSE Manager inicializado.");
xTaskCreate(evse_manager_task, "evse_manager_task", 4096, NULL, 5, NULL);
}
// ===== Main Tick =====
void evse_manager_tick(void) {
xSemaphoreTake(evse_mutex, portMAX_DELAY);
evse_hardware_tick();
evse_error_tick();
evse_state_tick();
evse_temperature_check();
if (auth_enabled) {
// If the car is disconnected, revoke authorization
if (evse_state_get_authorized() && evse_get_state() == EVSE_STATE_A) {
ESP_LOGI(TAG, "Vehicle disconnected → revoking authorization.");
evse_state_set_authorized(false);
}
} else {
// If authentication is disabled, ensure authorization is always granted
if (!evse_state_get_authorized()) {
evse_state_set_authorized(true);
ESP_LOGI(TAG, "Authentication disabled → forced authorization.");
}
}
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();
}
// === Fim de: components/evse/evse_manager.c ===
// === Início de: components/evse/evse_events.c ===
#include "evse_events.h"
ESP_EVENT_DEFINE_BASE(EVSE_EVENTS);
// === Fim de: components/evse/evse_events.c ===
// === Início de: components/evse/include/evse_pilot.h ===
#ifndef PILOT_H_
#define PILOT_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
/**
* @brief Níveis categóricos de tensão no sinal CP (Control Pilot)
*/
typedef enum
{
PILOT_VOLTAGE_12, ///< Estado A: +12V
PILOT_VOLTAGE_9, ///< Estado B: +9V
PILOT_VOLTAGE_6, ///< Estado C: +6V
PILOT_VOLTAGE_3, ///< Estado D: +3V
PILOT_VOLTAGE_1 ///< Estado E/F: abaixo de 3V
} pilot_voltage_t;
/**
* @brief Inicializa o driver do sinal Pilot
*/
void pilot_init(void);
/**
* @brief Define o nível do Pilot: +12V ou -12V
*
* @param level true = +12V, false = -12V
*/
void pilot_set_level(bool level);
/**
* @brief Ativa o PWM do Pilot com corrente limitada
*
* @param amps Corrente em décimos de ampère (ex: 160 = 16A)
*/
void pilot_set_amps(uint16_t amps);
/**
* @brief Mede o nível de tensão do Pilot e detecta -12V
*
* @param up_voltage Valor categórico da tensão positiva
* @param down_voltage_n12 true se o nível negativo atingir -12V
*/
void pilot_measure(pilot_voltage_t *up_voltage, bool *down_voltage_n12);
/**
* @brief Retorna o estado lógico atual do Pilot (nível alto = +12V)
*
* @return true se nível atual for +12V, false se for -12V
*/
bool pilot_get_state(void);
/**
* @brief Cache interno opcional dos níveis de tensão reais do Pilot
*/
typedef struct {
uint16_t high_mv; ///< Pico positivo medido (mV)
uint16_t low_mv; ///< Pico negativo medido (mV)
} pilot_voltage_cache_t;
#ifdef __cplusplus
}
#endif
#endif /* PILOT_H_ */
// === Fim de: components/evse/include/evse_pilot.h ===
// === Início de: components/evse/include/evse_manager.h ===
#ifndef EVSE_MANAGER_H
#define EVSE_MANAGER_H
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>
/**
* @brief Inicializa os módulos internos do EVSE (hardware, estado, erros, etc.)
* e inicia a tarefa de supervisão periódica (tick).
*/
void evse_manager_init(void);
/**
* @brief Executa uma iteração do ciclo de controle do EVSE.
*
* Esta função é chamada automaticamente pela task periódica,
* mas pode ser chamada manualmente em testes.
*/
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
#endif // EVSE_MANAGER_H
// === Fim de: components/evse/include/evse_manager.h ===
// === Início de: components/evse/include/evse_fsm.h ===
#ifndef EVSE_FSM_H
#define EVSE_FSM_H
#include <stdint.h>
#include <stdbool.h>
#include "evse_api.h"
#include "evse_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
// === Fim de: components/evse/include/evse_fsm.h ===
// === Início de: components/evse/include/evse_hardware.h ===
#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
// === Fim de: components/evse/include/evse_hardware.h ===
// === Início de: components/evse/include/evse_config.h ===
#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 32 // 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);
// Configuração de socket outlet
bool evse_get_socket_outlet(void);
esp_err_t evse_set_socket_outlet(bool socket_outlet);
void evse_set_runtime_charging_current(uint16_t value);
uint16_t evse_get_runtime_charging_current(void);
// 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
// === Fim de: components/evse/include/evse_config.h ===
// === Início de: components/evse/include/evse_state.h ===
#ifndef EVSE_STATE_H
#define EVSE_STATE_H
#include <stdbool.h>
#include "freertos/FreeRTOS.h"
#include "evse_events.h"
// ============================
// EVSE Pilot Signal States
// ============================
typedef enum {
EVSE_STATE_A, // EV Not Connected (12V)
EVSE_STATE_B1, // EV Connected (9V, Not Authorized)
EVSE_STATE_B2, // EV Connected (9V, Authorized and Ready)
EVSE_STATE_C1, // Charging Requested (6V, Relay Off)
EVSE_STATE_C2, // Charging Active (6V, Relay On)
EVSE_STATE_D1, // Ventilation Required (3V, Relay Off)
EVSE_STATE_D2, // Ventilation Active (3V, Relay On)
EVSE_STATE_E, // Error: Pilot Short to Ground (0V)
EVSE_STATE_F // Fault: No Pilot or EVSE Unavailable
} evse_state_t;
// ============================
// Initialization & Core Control
// ============================
/**
* @brief Initializes the EVSE state machine.
*/
void evse_state_init(void);
/**
* @brief Periodic tick function for the state machine.
*/
void evse_state_tick(void);
// ============================
// State Access
// ============================
/**
* @brief Returns the current EVSE state.
*/
evse_state_t evse_get_state(void);
/**
* @brief Updates the current EVSE state and triggers events.
*/
void evse_set_state(evse_state_t state);
/**
* @brief Returns the tick count when charging session started.
*/
TickType_t evse_get_session_start(void);
/**
* @brief Converts the state enum to a human-readable string.
*/
const char* evse_state_to_str(evse_state_t state);
// ============================
// State Evaluators
// ============================
/**
* @brief Returns true if the state represents 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).
*/
bool evse_state_is_charging(evse_state_t state);
/**
* @brief Returns true if the vehicle is plugged in.
*/
bool evse_state_is_plugged(evse_state_t state);
// ============================
// Authorization
// ============================
/**
* @brief Sets the vehicle authorization state.
*/
void evse_state_set_authorized(bool authorized);
/**
* @brief Returns the current vehicle authorization state.
*/
bool evse_state_get_authorized(void);
#endif // EVSE_STATE_H
// === Fim de: components/evse/include/evse_state.h ===
// === Início de: components/evse/include/evse_error.h ===
#ifndef EVSE_ERROR_H
#define EVSE_ERROR_H
#include <stdint.h>
#include <stdbool.h>
#include "evse_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
// === Fim de: components/evse/include/evse_error.h ===
// === Início de: components/evse/include/evse_limits.h ===
#ifndef EVSE_LIMITS_H
#define EVSE_LIMITS_H
#include <stdint.h>
#include <stdbool.h>
#include "evse_state.h"
#ifdef __cplusplus
extern "C" {
#endif
// ========================
// Limit state control
// ========================
/**
* @brief Sets the 'limit reached' flag. Used internally when a session exceeds defined thresholds.
*/
void evse_set_limit_reached(bool value);
/**
* @brief Returns whether any session limit has been reached (energy, time or power).
*/
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.
*/
void evse_limits_check(void);
// ========================
// Runtime limit configuration
// ========================
uint32_t evse_get_consumption_limit(void);
void evse_set_consumption_limit(uint32_t value); // in Wh
uint32_t evse_get_charging_time_limit(void);
void evse_set_charging_time_limit(uint32_t value); // in seconds
uint16_t evse_get_under_power_limit(void);
void evse_set_under_power_limit(uint16_t value); // in Watts
// ========================
// Default (persistent) limits
// ========================
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
// === Fim de: components/evse/include/evse_limits.h ===