new meter
This commit is contained in:
@@ -8,11 +8,12 @@ set(srcs
|
||||
evse_fsm.c
|
||||
evse_manager.c
|
||||
evse_hardware.c
|
||||
evse_pilot.c
|
||||
)
|
||||
|
||||
idf_component_register(
|
||||
SRCS ${srcs}
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_REQUIRES nvs_flash
|
||||
REQUIRES peripherals auth
|
||||
PRIV_REQUIRES nvs_flash driver
|
||||
REQUIRES peripherals auth loadbalancer
|
||||
)
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <inttypes.h> // Include for PRI macros
|
||||
|
||||
#include <inttypes.h> // For PRI macros
|
||||
#include "evse_config.h"
|
||||
#include "board_config.h"
|
||||
#include "evse_limits.h"
|
||||
@@ -10,18 +9,22 @@ static const char *TAG = "evse_config";
|
||||
|
||||
static nvs_handle_t nvs;
|
||||
|
||||
// ========================
|
||||
// Configurable parameters
|
||||
// ========================
|
||||
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 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...");
|
||||
ESP_LOGI(TAG, "Opening NVS namespace");
|
||||
return nvs_open("evse", NVS_READWRITE, &nvs);
|
||||
}
|
||||
|
||||
@@ -36,244 +39,221 @@ void evse_check_defaults(void) {
|
||||
|
||||
// Max charging current
|
||||
err = nvs_get_u8(nvs, "max_chrg_curr", &u8);
|
||||
ESP_LOGD(TAG, "Max charging current read: %d", 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_LOGD(TAG, "Max charging current adjusted to: %d", max_charging_current);
|
||||
ESP_LOGW(TAG, "Invalid or missing max_chrg_curr, resetting to %d", max_charging_current);
|
||||
} else {
|
||||
max_charging_current = u8;
|
||||
}
|
||||
|
||||
// Grid max current
|
||||
err = nvs_get_u8(nvs, "grid_max_curr", &u8);
|
||||
ESP_LOGD(TAG, "Grid max current read: %d", 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;
|
||||
ESP_LOGD(TAG, "Grid max current adjusted to: %d", grid_max_current);
|
||||
} else {
|
||||
grid_max_current = u8;
|
||||
}
|
||||
|
||||
// Charging current (decA)
|
||||
// Charging current (default, persisted)
|
||||
err = nvs_get_u16(nvs, "def_chrg_curr", &u16);
|
||||
ESP_LOGD(TAG, "Charging current read: %d", 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_LOGD(TAG, "Charging current adjusted to: %d", charging_current);
|
||||
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;
|
||||
ESP_LOGD(TAG, "Require auth adjusted to: %d", require_auth);
|
||||
}
|
||||
|
||||
// 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;
|
||||
ESP_LOGD(TAG, "Socket outlet adjusted to: %d", socket_outlet);
|
||||
}
|
||||
|
||||
// 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;
|
||||
ESP_LOGD(TAG, "RCM adjusted to: %d", rcm);
|
||||
}
|
||||
|
||||
// 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;
|
||||
ESP_LOGD(TAG, "Temp threshold adjusted to: %d", temp_threshold);
|
||||
}
|
||||
|
||||
// Additional limits
|
||||
if (nvs_get_u32(nvs, "def_cons_lim", &u32) == ESP_OK) {
|
||||
// Optional limits
|
||||
if (nvs_get_u32(nvs, "def_cons_lim", &u32) == ESP_OK)
|
||||
evse_set_consumption_limit(u32);
|
||||
ESP_LOGD(TAG, "Consumption limit read and applied: %" PRIu32, u32); // Updated to PRIu32
|
||||
}
|
||||
|
||||
if (nvs_get_u32(nvs, "def_ch_time_lim", &u32) == ESP_OK) {
|
||||
if (nvs_get_u32(nvs, "def_ch_time_lim", &u32) == ESP_OK)
|
||||
evse_set_charging_time_limit(u32);
|
||||
ESP_LOGD(TAG, "Charging time limit read and applied: %" PRIu32, u32); // Updated to PRIu32
|
||||
}
|
||||
|
||||
if (nvs_get_u16(nvs, "def_un_pwr_lim", &u16) == ESP_OK) {
|
||||
if (nvs_get_u16(nvs, "def_un_pwr_lim", &u16) == ESP_OK)
|
||||
evse_set_under_power_limit(u16);
|
||||
ESP_LOGD(TAG, "Under power limit read and applied: %d", u16);
|
||||
}
|
||||
|
||||
// Save to NVS if needed
|
||||
if (needs_commit) {
|
||||
nvs_commit(nvs);
|
||||
ESP_LOGD(TAG, "Changes committed to NVS.");
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Current
|
||||
// ========================
|
||||
// Charging current getters/setters
|
||||
// ========================
|
||||
uint8_t evse_get_max_charging_current(void) {
|
||||
ESP_LOGI(TAG, "Max charging current read: %d", max_charging_current);
|
||||
return max_charging_current;
|
||||
}
|
||||
|
||||
esp_err_t evse_set_max_charging_current(uint8_t value) {
|
||||
ESP_LOGI(TAG, "Attempting to set max charging current: %d", 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);
|
||||
nvs_commit(nvs);
|
||||
ESP_LOGD(TAG, "Max charging current adjusted to: %d", max_charging_current);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint8_t grid_get_max_current(void) {
|
||||
ESP_LOGD(TAG, "Grid max current read: %d", grid_max_current);
|
||||
return grid_max_current;
|
||||
}
|
||||
|
||||
esp_err_t grid_set_max_current(uint8_t value) {
|
||||
ESP_LOGD(TAG, "Attempting to set grid max current: %d", 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);
|
||||
nvs_commit(nvs);
|
||||
ESP_LOGD(TAG, "Grid max current adjusted to: %d", grid_max_current);
|
||||
return ESP_OK;
|
||||
return nvs_commit(nvs);
|
||||
}
|
||||
|
||||
uint16_t evse_get_charging_current(void) {
|
||||
ESP_LOGD(TAG, "Charging current read: %d", charging_current);
|
||||
return charging_current;
|
||||
}
|
||||
|
||||
esp_err_t evse_set_charging_current(uint16_t value) {
|
||||
ESP_LOGD(TAG, "Attempting to set charging current: %d", 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);
|
||||
nvs_commit(nvs);
|
||||
ESP_LOGD(TAG, "Charging current adjusted to: %d", charging_current);
|
||||
return ESP_OK;
|
||||
return nvs_commit(nvs);
|
||||
}
|
||||
|
||||
uint16_t evse_get_default_charging_current(void) {
|
||||
uint16_t value;
|
||||
nvs_get_u16(nvs, "def_chrg_curr", &value);
|
||||
ESP_LOGD(TAG, "Default charging current read: %d", value);
|
||||
return 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) {
|
||||
ESP_LOGD(TAG, "Attempting to set default charging current: %d", 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);
|
||||
nvs_commit(nvs);
|
||||
ESP_LOGD(TAG, "Default charging current adjusted to: %d", value);
|
||||
return ESP_OK;
|
||||
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) {
|
||||
ESP_LOGD(TAG, "Socket outlet read: %d", socket_outlet);
|
||||
return socket_outlet;
|
||||
}
|
||||
|
||||
esp_err_t evse_set_socket_outlet(bool value) {
|
||||
ESP_LOGD(TAG, "Attempting to set socket outlet: %d", value);
|
||||
if (value && !board_config.proximity) return ESP_ERR_INVALID_ARG;
|
||||
if (value && !board_config.proximity)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
socket_outlet = value;
|
||||
nvs_set_u8(nvs, "socket_outlet", value);
|
||||
nvs_commit(nvs);
|
||||
ESP_LOGD(TAG, "Socket outlet adjusted to: %d", socket_outlet);
|
||||
return ESP_OK;
|
||||
return nvs_commit(nvs);
|
||||
}
|
||||
|
||||
// ========================
|
||||
// RCM
|
||||
// ========================
|
||||
bool evse_is_rcm(void) {
|
||||
ESP_LOGD(TAG, "RCM read: %d", rcm);
|
||||
return rcm;
|
||||
}
|
||||
|
||||
esp_err_t evse_set_rcm(bool value) {
|
||||
ESP_LOGD(TAG, "Attempting to set RCM: %d", value);
|
||||
if (value && !board_config.rcm) return ESP_ERR_INVALID_ARG;
|
||||
if (value && !board_config.rcm)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
rcm = value;
|
||||
nvs_set_u8(nvs, "rcm", value);
|
||||
nvs_commit(nvs);
|
||||
ESP_LOGD(TAG, "RCM adjusted to: %d", rcm);
|
||||
return ESP_OK;
|
||||
return nvs_commit(nvs);
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Temperature
|
||||
// ========================
|
||||
uint8_t evse_get_temp_threshold(void) {
|
||||
ESP_LOGD(TAG, "Temp threshold read: %d", temp_threshold);
|
||||
return temp_threshold;
|
||||
}
|
||||
|
||||
esp_err_t evse_set_temp_threshold(uint8_t value) {
|
||||
ESP_LOGI(TAG, "Attempting to set temp threshold: %d", value);
|
||||
if (value < 40 || value > 80) return ESP_ERR_INVALID_ARG;
|
||||
if (value < 40 || value > 80)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
temp_threshold = value;
|
||||
nvs_set_u8(nvs, "temp_threshold", value);
|
||||
nvs_commit(nvs);
|
||||
ESP_LOGI(TAG, "Temp threshold adjusted to: %d", temp_threshold);
|
||||
return ESP_OK;
|
||||
return nvs_commit(nvs);
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Authentication
|
||||
// ========================
|
||||
bool evse_is_require_auth(void) {
|
||||
ESP_LOGD(TAG, "Require auth read: %d", require_auth);
|
||||
return require_auth;
|
||||
}
|
||||
|
||||
void evse_set_require_auth(bool value) {
|
||||
ESP_LOGI(TAG, "Attempting to set require auth: %d", value);
|
||||
require_auth = value;
|
||||
nvs_set_u8(nvs, "require_auth", value);
|
||||
nvs_commit(nvs);
|
||||
ESP_LOGD(TAG, "Require auth adjusted to: %d", require_auth);
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Availability
|
||||
// ========================
|
||||
static bool is_available = true;
|
||||
|
||||
bool evse_config_is_available(void) {
|
||||
ESP_LOGD(TAG, "Checking availability: %d", is_available);
|
||||
return is_available;
|
||||
}
|
||||
|
||||
void evse_config_set_available(bool available) {
|
||||
ESP_LOGD(TAG, "Setting availability to: %d", available);
|
||||
is_available = available;
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Enable/Disable
|
||||
// ========================
|
||||
static bool is_enabled = true;
|
||||
|
||||
bool evse_config_is_enabled(void) {
|
||||
ESP_LOGD(TAG, "Checking if enabled: %d", is_enabled);
|
||||
return is_enabled;
|
||||
}
|
||||
|
||||
void evse_config_set_enabled(bool enabled) {
|
||||
ESP_LOGD(TAG, "Setting enabled state to: %d", enabled);
|
||||
is_enabled = enabled;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "evse_limits.h"
|
||||
#include "evse_config.h"
|
||||
#include "evse_api.h"
|
||||
#include "pilot.h"
|
||||
#include "evse_pilot.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
@@ -15,8 +15,6 @@ 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);
|
||||
|
||||
@@ -41,15 +39,13 @@ void evse_process(void) {
|
||||
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()) {
|
||||
|
||||
bool authorized = evse_state_get_authorized();
|
||||
evse_error_check(pilot_voltage, is_n12v);
|
||||
|
||||
evse_fsm_process(
|
||||
pilot_voltage,
|
||||
authorized,
|
||||
evse_state_get_authorized(),
|
||||
evse_config_is_available(),
|
||||
evse_config_is_enabled()
|
||||
);
|
||||
@@ -58,18 +54,19 @@ void evse_process(void) {
|
||||
|
||||
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));
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
// ================================
|
||||
// Interface pública
|
||||
// ================================
|
||||
@@ -92,22 +89,6 @@ void evse_set_available(bool 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");
|
||||
evse_state_set_authorized(true);
|
||||
}
|
||||
|
||||
void evse_set_authorized(bool value) {
|
||||
ESP_LOGI(TAG, "Set authorized %d", value);
|
||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||
authorized = value;
|
||||
xSemaphoreGive(mutex);
|
||||
}
|
||||
|
||||
// ================================
|
||||
// Tarefa principal
|
||||
// ================================
|
||||
|
||||
@@ -33,6 +33,7 @@ void evse_error_check(pilot_voltage_t pilot_voltage, bool 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)");
|
||||
ESP_LOGW(TAG, "Verificando erro: pilot_voltage = %d, is_n12v = %s", pilot_voltage, is_n12v ? "true" : "false");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#include "evse_events.h"
|
||||
|
||||
ESP_EVENT_DEFINE_BASE(EVSE_EVENT);
|
||||
ESP_EVENT_DEFINE_BASE(EVSE_EVENTS);
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
#include "evse_fsm.h"
|
||||
#include "evse_api.h"
|
||||
#include "pilot.h"
|
||||
#include "evse_pilot.h"
|
||||
#include "evse_config.h"
|
||||
#include "esp_log.h"
|
||||
#include "ac_relay.h"
|
||||
#include "board_config.h"
|
||||
@@ -26,7 +27,15 @@ void evse_fsm_reset(void) {
|
||||
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) {
|
||||
static void update_outputs(evse_state_t state) {
|
||||
const uint16_t current = evse_get_runtime_charging_current();
|
||||
uint8_t cable_max_current = evse_get_max_charging_current();
|
||||
const bool socket_outlet = evse_get_socket_outlet();
|
||||
|
||||
if (socket_outlet) {
|
||||
cable_max_current = proximity_get_max_current();
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case EVSE_STATE_A:
|
||||
case EVSE_STATE_E:
|
||||
@@ -36,7 +45,6 @@ static void update_outputs(evse_state_t state, uint16_t charging_current, uint8_
|
||||
if (board_config.socket_lock && socket_outlet) {
|
||||
socket_lock_set_locked(false);
|
||||
}
|
||||
//energy_meter_stop_session();
|
||||
break;
|
||||
|
||||
case EVSE_STATE_B1:
|
||||
@@ -51,16 +59,10 @@ static void update_outputs(evse_state_t state, uint16_t charging_current, uint8_
|
||||
} 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));
|
||||
pilot_set_amps(MIN(current * 10, cable_max_current * 10));
|
||||
ac_relay_set_state(false);
|
||||
break;
|
||||
|
||||
@@ -73,7 +75,7 @@ static void update_outputs(evse_state_t state, uint16_t charging_current, uint8_
|
||||
|
||||
case EVSE_STATE_C2:
|
||||
case EVSE_STATE_D2:
|
||||
pilot_set_amps(MIN(charging_current, cable_max_current * 10));
|
||||
pilot_set_amps(MIN(current * 10, cable_max_current * 10));
|
||||
ac_relay_set_state(true);
|
||||
break;
|
||||
}
|
||||
@@ -81,10 +83,10 @@ static void update_outputs(evse_state_t state, uint16_t charging_current, uint8_
|
||||
|
||||
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;
|
||||
evse_state_t prev = evse_get_state();
|
||||
evse_state_t curr = prev;
|
||||
|
||||
switch (current_state) {
|
||||
switch (curr) {
|
||||
case EVSE_STATE_A:
|
||||
if (!available) {
|
||||
evse_set_state(EVSE_STATE_F);
|
||||
@@ -125,15 +127,12 @@ void evse_fsm_process(pilot_voltage_t pilot_voltage, bool authorized, bool avail
|
||||
break;
|
||||
}
|
||||
}
|
||||
// fallthrough intencional
|
||||
__attribute__((fallthrough)); // Evita warning de fallthrough implícito
|
||||
|
||||
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
|
||||
);
|
||||
evse_set_state((curr == EVSE_STATE_D2 || curr == EVSE_STATE_D1) ? EVSE_STATE_D1 : EVSE_STATE_C1);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -156,8 +155,7 @@ void evse_fsm_process(pilot_voltage_t pilot_voltage, bool authorized, bool avail
|
||||
break;
|
||||
|
||||
case EVSE_STATE_E:
|
||||
// Sem transições a partir de E
|
||||
break;
|
||||
break; // Sem transições a partir de E
|
||||
|
||||
case EVSE_STATE_F:
|
||||
if (available) {
|
||||
@@ -166,9 +164,9 @@ void evse_fsm_process(pilot_voltage_t pilot_voltage, bool authorized, bool avail
|
||||
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());
|
||||
evse_state_t next = evse_get_state();
|
||||
if (next != prev) {
|
||||
ESP_LOGI(TAG, "State changed: %s -> %s", evse_state_to_str(prev), evse_state_to_str(next));
|
||||
update_outputs(next);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "evse_hardware.h"
|
||||
#include "pilot.h"
|
||||
#include "evse_pilot.h"
|
||||
#include "ac_relay.h"
|
||||
#include "socket_lock.h"
|
||||
#include "proximity.h"
|
||||
@@ -7,6 +7,7 @@
|
||||
static const char *TAG = "evse_hardware";
|
||||
|
||||
void evse_hardware_init(void) {
|
||||
pilot_init();
|
||||
pilot_set_level(true); // Sinal piloto em 12V (inicial)
|
||||
ac_relay_set_state(false); // Relé desligado
|
||||
//socket_lock_set_locked(false); // Destrava o conector
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "evse_hardware.h"
|
||||
#include "evse_config.h"
|
||||
#include "evse_api.h"
|
||||
#include "auth.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@@ -13,12 +12,14 @@
|
||||
#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 TickType_t auth_expiration = 0;
|
||||
|
||||
static SemaphoreHandle_t evse_mutex;
|
||||
static QueueHandle_t auth_event_queue = NULL;
|
||||
static bool auth_enabled = false;
|
||||
|
||||
#define EVSE_MANAGER_TICK_PERIOD_MS 1000 // 1 segundo
|
||||
|
||||
@@ -30,27 +31,55 @@ static void evse_manager_task(void *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
static void evse_auth_event_task(void *arg) {
|
||||
auth_event_t evt;
|
||||
// ===== 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;
|
||||
|
||||
while (true) {
|
||||
if (xQueueReceive(auth_event_queue, &evt, portMAX_DELAY)) {
|
||||
ESP_LOGI(TAG, "Evento de autenticação recebido: %s (%s)",
|
||||
evt.tag, evt.authorized ? "AUTORIZADO" : "NEGADO");
|
||||
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;
|
||||
}
|
||||
|
||||
if (evt.authorized) {
|
||||
evse_authorize();
|
||||
auth_expiration = xTaskGetTickCount() + pdMS_TO_TICKS(2 * 60 * 1000); // 2 minutos
|
||||
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_manager_set_authorized(false);
|
||||
ESP_LOGW(TAG, "Tag inválida, carregamento negado.");
|
||||
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 dos módulos do EVSE =====
|
||||
// ===== Inicialização =====
|
||||
void evse_manager_init(void) {
|
||||
evse_mutex = xSemaphoreCreateMutex();
|
||||
|
||||
@@ -59,17 +88,14 @@ void evse_manager_init(void) {
|
||||
evse_hardware_init();
|
||||
evse_state_init();
|
||||
|
||||
ESP_LOGI(TAG, "EVSE Manager inicializado.");
|
||||
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);
|
||||
}
|
||||
|
||||
// ===== Inicia processamento de eventos de autenticação =====
|
||||
void evse_manager_start(QueueHandle_t queue) {
|
||||
auth_event_queue = queue;
|
||||
xTaskCreate(evse_auth_event_task, "evse_auth_evt", 4096, NULL, 5, NULL);
|
||||
}
|
||||
|
||||
// ===== Main Tick =====
|
||||
void evse_manager_tick(void) {
|
||||
xSemaphoreTake(evse_mutex, portMAX_DELAY);
|
||||
|
||||
@@ -78,27 +104,25 @@ void evse_manager_tick(void) {
|
||||
evse_state_tick();
|
||||
evse_temperature_check();
|
||||
|
||||
// Verifica expiração de autorização somente se auth está habilitado
|
||||
if (auth_is_enabled()) {
|
||||
if (evse_state_get_authorized() && auth_expiration > 0 &&
|
||||
xTaskGetTickCount() >= auth_expiration) {
|
||||
ESP_LOGI(TAG, "Autorização expirada após 2 minutos.");
|
||||
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);
|
||||
auth_expiration = 0;
|
||||
}
|
||||
} else {
|
||||
// Se autenticação não é necessária, sempre considera autorizado
|
||||
// If authentication is disabled, ensure authorization is always granted
|
||||
if (!evse_state_get_authorized()) {
|
||||
evse_state_set_authorized(true);
|
||||
ESP_LOGI(TAG, "Autenticação desativada: autorização forçada.");
|
||||
ESP_LOGI(TAG, "Authentication disabled → forced authorization.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
xSemaphoreGive(evse_mutex);
|
||||
}
|
||||
|
||||
// ===== Controles e status =====
|
||||
|
||||
// ===== API pública =====
|
||||
bool evse_manager_is_available(void) {
|
||||
return evse_config_is_available();
|
||||
}
|
||||
|
||||
172
components/evse/evse_pilot.c
Executable file
172
components/evse/evse_pilot.c
Executable file
@@ -0,0 +1,172 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "driver/ledc.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#include "evse_pilot.h"
|
||||
#include "adc.h"
|
||||
#include "board_config.h"
|
||||
|
||||
#define PILOT_PWM_TIMER LEDC_TIMER_0
|
||||
#define PILOT_PWM_CHANNEL LEDC_CHANNEL_0
|
||||
#define PILOT_PWM_SPEED_MODE LEDC_LOW_SPEED_MODE
|
||||
#define PILOT_PWM_DUTY_RES LEDC_TIMER_10_BIT
|
||||
#define PILOT_PWM_MAX_DUTY 1023
|
||||
|
||||
#define NUM_PILOT_SAMPLES 100
|
||||
#define MAX_SAMPLE_ATTEMPTS 1000
|
||||
#define PILOT_EXTREME_PERCENT 10 // 10% superior e inferior
|
||||
|
||||
static const char *TAG = "evse_pilot";
|
||||
|
||||
void pilot_init(void)
|
||||
{
|
||||
ledc_timer_config_t ledc_timer = {
|
||||
.speed_mode = PILOT_PWM_SPEED_MODE,
|
||||
.timer_num = PILOT_PWM_TIMER,
|
||||
.duty_resolution = PILOT_PWM_DUTY_RES,
|
||||
.freq_hz = 1000,
|
||||
.clk_cfg = LEDC_AUTO_CLK
|
||||
};
|
||||
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
|
||||
|
||||
ledc_channel_config_t ledc_channel = {
|
||||
.speed_mode = PILOT_PWM_SPEED_MODE,
|
||||
.channel = PILOT_PWM_CHANNEL,
|
||||
.timer_sel = PILOT_PWM_TIMER,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.gpio_num = board_config.pilot_pwm_gpio,
|
||||
.duty = 0,
|
||||
.hpoint = 0
|
||||
};
|
||||
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));
|
||||
}
|
||||
|
||||
void pilot_set_level(bool level)
|
||||
{
|
||||
ESP_LOGI(TAG, "Set level %d", level);
|
||||
ledc_stop(PILOT_PWM_SPEED_MODE, PILOT_PWM_CHANNEL, level ? 1 : 0);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
uint32_t duty;
|
||||
if (amps <= 510) {
|
||||
duty = (PILOT_PWM_MAX_DUTY * amps) / 600;
|
||||
} 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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
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)];
|
||||
}
|
||||
|
||||
void pilot_measure(pilot_voltage_t *up_voltage, bool *down_voltage_n12)
|
||||
{
|
||||
ESP_LOGD(TAG, "pilot_measure");
|
||||
|
||||
int samples[NUM_PILOT_SAMPLES];
|
||||
int collected = 0, attempts = 0;
|
||||
int sample;
|
||||
|
||||
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;
|
||||
esp_rom_delay_us(10);
|
||||
} else {
|
||||
esp_rom_delay_us(100);
|
||||
attempts++;
|
||||
}
|
||||
}
|
||||
|
||||
if (collected < NUM_PILOT_SAMPLES) {
|
||||
ESP_LOGW(TAG, "Timeout on sample read (%d/%d)", collected, NUM_PILOT_SAMPLES);
|
||||
*up_voltage = PILOT_VOLTAGE_1;
|
||||
*down_voltage_n12 = false;
|
||||
return;
|
||||
}
|
||||
|
||||
int high_raw = select_high_median_qsort(samples, collected, PILOT_EXTREME_PERCENT);
|
||||
int low_raw = select_low_median_qsort(samples, collected, PILOT_EXTREME_PERCENT);
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (high_mv >= board_config.pilot_down_threshold_12)
|
||||
*up_voltage = PILOT_VOLTAGE_12;
|
||||
else if (high_mv >= board_config.pilot_down_threshold_9)
|
||||
*up_voltage = PILOT_VOLTAGE_9;
|
||||
else if (high_mv >= board_config.pilot_down_threshold_6)
|
||||
*up_voltage = PILOT_VOLTAGE_6;
|
||||
else if (high_mv >= board_config.pilot_down_threshold_3)
|
||||
*up_voltage = PILOT_VOLTAGE_3;
|
||||
else
|
||||
*up_voltage = PILOT_VOLTAGE_1;
|
||||
|
||||
*down_voltage_n12 = (low_mv <= board_config.pilot_down_threshold_n12);
|
||||
|
||||
ESP_LOGD(TAG, "Final: up_voltage=%d, down_voltage_n12=%d", *up_voltage, *down_voltage_n12);
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "evse_state.h"
|
||||
#include "evse_events.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/portmacro.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static evse_state_t current_state = EVSE_STATE_A;
|
||||
static bool is_authorized = false;
|
||||
@@ -8,10 +10,45 @@ static bool is_authorized = false;
|
||||
// Proteção básica para variáveis globais em sistemas concorrentes
|
||||
static portMUX_TYPE state_mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
static evse_state_event_t map_state_to_event(evse_state_t s) {
|
||||
switch (s) {
|
||||
case EVSE_STATE_A:
|
||||
return EVSE_STATE_EVENT_IDLE;
|
||||
case EVSE_STATE_B1:
|
||||
return EVSE_STATE_EVENT_WAITING;
|
||||
case EVSE_STATE_B2:
|
||||
case EVSE_STATE_C1:
|
||||
case EVSE_STATE_C2:
|
||||
return EVSE_STATE_EVENT_CHARGING;
|
||||
case EVSE_STATE_E:
|
||||
case EVSE_STATE_F:
|
||||
return EVSE_STATE_EVENT_FAULT;
|
||||
default:
|
||||
return EVSE_STATE_EVENT_IDLE;
|
||||
}
|
||||
}
|
||||
void evse_set_state(evse_state_t state) {
|
||||
bool changed = false;
|
||||
evse_state_t previous_state;
|
||||
|
||||
portENTER_CRITICAL(&state_mux);
|
||||
current_state = state;
|
||||
previous_state = current_state;
|
||||
if (state != current_state) {
|
||||
current_state = state;
|
||||
changed = true;
|
||||
}
|
||||
portEXIT_CRITICAL(&state_mux);
|
||||
|
||||
if (changed) {
|
||||
ESP_LOGI("EVSE_STATE", "Estado alterado de %s para %s",
|
||||
evse_state_to_str(previous_state),
|
||||
evse_state_to_str(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);
|
||||
}
|
||||
}
|
||||
|
||||
evse_state_t evse_get_state(void) {
|
||||
@@ -39,8 +76,15 @@ const char* evse_state_to_str(evse_state_t state) {
|
||||
void evse_state_init(void) {
|
||||
portENTER_CRITICAL(&state_mux);
|
||||
current_state = EVSE_STATE_A;
|
||||
is_authorized = false;
|
||||
is_authorized = true;
|
||||
portEXIT_CRITICAL(&state_mux);
|
||||
|
||||
ESP_LOGI("EVSE_STATE", "Inicializado em estado: %s", evse_state_to_str(current_state));
|
||||
|
||||
evse_state_event_data_t evt = {
|
||||
.state = map_state_to_event(current_state)
|
||||
};
|
||||
esp_event_post(EVSE_EVENTS, EVSE_EVENT_INIT, &evt, sizeof(evt), portMAX_DELAY);
|
||||
}
|
||||
|
||||
void evse_state_tick(void) {
|
||||
|
||||
@@ -23,9 +23,6 @@ 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);
|
||||
@@ -35,10 +32,6 @@ 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);
|
||||
|
||||
@@ -17,10 +17,6 @@ extern "C" {
|
||||
#define MIN_CHARGING_CURRENT_LIMIT 6 // A
|
||||
#define MAX_CHARGING_CURRENT_LIMIT 32 // 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
|
||||
@@ -43,14 +39,14 @@ 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);
|
||||
|
||||
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);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "pilot.h"
|
||||
#include "evse_pilot.h"
|
||||
|
||||
|
||||
#define EVSE_ERR_AUTO_CLEAR_BITS ( \
|
||||
|
||||
@@ -1,33 +1,27 @@
|
||||
#ifndef EVSE_EVENTS_H
|
||||
#define EVSE_EVENTS_H
|
||||
|
||||
#include "evse_api.h"
|
||||
#include "esp_event_base.h"
|
||||
#pragma once
|
||||
#include "esp_event.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);
|
||||
ESP_EVENT_DECLARE_BASE(EVSE_EVENTS);
|
||||
|
||||
typedef enum {
|
||||
EVSE_EVENT_INIT,
|
||||
EVSE_EVENT_STATE_CHANGED,
|
||||
EVSE_EVENT_ERROR,
|
||||
EVSE_EVENT_ERROR_CLEARED,
|
||||
EVSE_EVENT_LIMIT_REACHED,
|
||||
EVSE_EVENT_AUTH_GRANTED
|
||||
// Outros eventos possíveis futuramente
|
||||
} 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;
|
||||
typedef enum {
|
||||
EVSE_STATE_EVENT_IDLE,
|
||||
EVSE_STATE_EVENT_WAITING,
|
||||
EVSE_STATE_EVENT_CHARGING,
|
||||
EVSE_STATE_EVENT_FAULT
|
||||
} evse_state_event_t;
|
||||
|
||||
typedef struct {
|
||||
evse_state_event_t state;
|
||||
} evse_state_event_data_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // EVSE_EVENTS_H
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "evse_api.h"
|
||||
#include "pilot.h"
|
||||
#include "evse_pilot.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,27 +1,23 @@
|
||||
#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).
|
||||
* e inicia a tarefa de supervisão periódica (tick).
|
||||
*/
|
||||
void evse_manager_init(void);
|
||||
|
||||
/**
|
||||
* @brief Inicia a tarefa que processa eventos de autenticação recebidos via fila.
|
||||
*
|
||||
* @param queue Fila de eventos do tipo auth_event_t enviada pelo módulo auth.
|
||||
*/
|
||||
void evse_manager_start(QueueHandle_t queue);
|
||||
|
||||
/**
|
||||
* @brief Executa uma iteração do ciclo de controle do EVSE.
|
||||
*
|
||||
@@ -66,4 +62,5 @@ bool evse_manager_is_enabled(void);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // EVSE_MANAGER_H
|
||||
|
||||
69
components/evse/include/evse_pilot.h
Executable file
69
components/evse/include/evse_pilot.h
Executable file
@@ -0,0 +1,69 @@
|
||||
#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_ */
|
||||
@@ -1,6 +1,9 @@
|
||||
#ifndef EVSE_STATE_H
|
||||
#define EVSE_STATE_H
|
||||
|
||||
#include "evse_events.h"
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
// Estado do EVSE (pilot signal)
|
||||
@@ -41,4 +44,6 @@ 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);
|
||||
|
||||
//evse_state_event_t map_state_to_event(evse_state_t state);
|
||||
|
||||
#endif // EVSE_STATE_H
|
||||
|
||||
Reference in New Issue
Block a user