234 lines
4.5 KiB
C
Executable File
234 lines
4.5 KiB
C
Executable File
#include <memory.h>
|
|
#include <math.h>
|
|
#include <stdbool.h> // <- Necessário para bool
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/semphr.h"
|
|
#include "esp_log.h"
|
|
#include "esp_timer.h"
|
|
#include "nvs.h"
|
|
|
|
#include "energy_meter.h"
|
|
#include "meter.h"
|
|
#include "serial_mdb.h"
|
|
|
|
#define NVS_NAMESPACE "evse_emeter"
|
|
#define NVS_MODEL "model"
|
|
#define NVS_STATE "state"
|
|
|
|
static const char *TAG = "energy_meter";
|
|
|
|
static nvs_handle nvs;
|
|
|
|
static bool state = false;
|
|
static meter_model_t model = ENERGY_METER_NONE;
|
|
|
|
static uint16_t power = 0;
|
|
static bool has_session = false;
|
|
static int64_t start_time = 0;
|
|
static uint32_t charging_time = 0; // ms
|
|
static uint32_t consumption = 0; // Ws
|
|
static float cur[3] = {0, 0, 0};
|
|
static float vlt[3] = {0, 0, 0};
|
|
static int64_t prev_time = 0;
|
|
|
|
static void set_calc_power(float p, uint32_t delta_ms)
|
|
{
|
|
consumption += roundf((p * delta_ms) / 1000.0f);
|
|
power = roundf(p);
|
|
}
|
|
|
|
void energy_meter_init(void)
|
|
{
|
|
ESP_LOGI(TAG, "energy_meter_init");
|
|
ESP_ERROR_CHECK(nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs));
|
|
|
|
uint8_t u8 = ENERGY_METER_NONE;
|
|
nvs_get_u8(nvs, NVS_MODEL, &u8);
|
|
model = u8;
|
|
}
|
|
|
|
bool meter_get_state(void)
|
|
{
|
|
return serial_mdb_get_meter_state();
|
|
}
|
|
|
|
esp_err_t meter_set_state(bool _state)
|
|
{
|
|
state = _state;
|
|
nvs_set_u8(nvs, NVS_STATE, state);
|
|
nvs_commit(nvs);
|
|
return ESP_OK;
|
|
}
|
|
|
|
meter_model_t meter_get_model(void)
|
|
{
|
|
return model;
|
|
}
|
|
|
|
esp_err_t meter_set_model(meter_model_t _model)
|
|
{
|
|
ESP_LOGI(TAG, "meter_set_model");
|
|
|
|
if (_model < 0 || _model > ENERGY_METER_ORNO_517) {
|
|
ESP_LOGE(TAG, "Model out of range");
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
model = _model;
|
|
nvs_set_u8(nvs, NVS_MODEL, model);
|
|
nvs_commit(nvs);
|
|
serial_mdb_set_model(model != ENERGY_METER_NONE);
|
|
return ESP_OK;
|
|
}
|
|
|
|
void energy_meter_start_session(void)
|
|
{
|
|
if (!has_session) {
|
|
ESP_LOGI(TAG, "Start session");
|
|
start_time = esp_timer_get_time();
|
|
has_session = true;
|
|
//meter_start();
|
|
}
|
|
}
|
|
|
|
void energy_meter_stop_session(void)
|
|
{
|
|
if (has_session) {
|
|
ESP_LOGI(TAG, "Stop session");
|
|
start_time = 0;
|
|
consumption = 0;
|
|
charging_time = 0;
|
|
has_session = false;
|
|
//meter_stop();
|
|
}
|
|
}
|
|
|
|
void energy_meter_process(bool charging, uint16_t charging_current)
|
|
{
|
|
int64_t now = esp_timer_get_time();
|
|
uint32_t delta_ms = (now - prev_time) / 1000;
|
|
|
|
if (charging && meter_is_running()) {
|
|
MeterData data = meter_getData();
|
|
|
|
vlt[0] = data.vrmsA;
|
|
vlt[1] = data.vrmsB;
|
|
vlt[2] = data.vrmsC;
|
|
|
|
cur[0] = data.irmsA;
|
|
cur[1] = data.irmsB;
|
|
cur[2] = data.irmsC;
|
|
|
|
uint32_t total_power = data.wattA + data.wattB + data.wattC;
|
|
|
|
set_calc_power((float)total_power, delta_ms);
|
|
charging_time += delta_ms;
|
|
} else {
|
|
vlt[0] = vlt[1] = vlt[2] = 0;
|
|
cur[0] = cur[1] = cur[2] = 0;
|
|
power = 0;
|
|
}
|
|
|
|
prev_time = now;
|
|
}
|
|
|
|
uint32_t energy_meter_get_power(void)
|
|
{
|
|
return power;
|
|
}
|
|
|
|
uint32_t energy_meter_get_session_time(void)
|
|
{
|
|
return has_session ? (esp_timer_get_time() - start_time) / 1000000 : 0;
|
|
}
|
|
|
|
uint32_t energy_meter_get_charging_time(void)
|
|
{
|
|
return charging_time / 1000;
|
|
}
|
|
|
|
uint32_t energy_meter_get_consumption(void)
|
|
{
|
|
return consumption / 3600;
|
|
}
|
|
|
|
void energy_meter_get_voltage(float *voltage)
|
|
{
|
|
memcpy(voltage, vlt, sizeof(vlt));
|
|
}
|
|
|
|
float energy_meter_get_l1_voltage(void)
|
|
{
|
|
return vlt[0];
|
|
}
|
|
|
|
float energy_meter_get_l2_voltage(void)
|
|
{
|
|
return vlt[1];
|
|
}
|
|
|
|
float energy_meter_get_l3_voltage(void)
|
|
{
|
|
return vlt[2];
|
|
}
|
|
|
|
void energy_meter_get_current(float *current)
|
|
{
|
|
memcpy(current, cur, sizeof(cur));
|
|
}
|
|
|
|
float energy_meter_get_l1_current(void)
|
|
{
|
|
return cur[0];
|
|
}
|
|
|
|
float energy_meter_get_l2_current(void)
|
|
{
|
|
return cur[1];
|
|
}
|
|
|
|
float energy_meter_get_l3_current(void)
|
|
{
|
|
return cur[2];
|
|
}
|
|
|
|
|
|
const char *meter_state_to_str(bool state)
|
|
{
|
|
return state == true ? "CONNECTED" : "NOT CONNECTED";
|
|
}
|
|
|
|
const char *meter_model_to_str(meter_model_t mode)
|
|
{
|
|
|
|
switch (mode)
|
|
{
|
|
case ENERGY_METER_NONE:
|
|
return "NONE";
|
|
case ENERGY_METER_ORNO_515:
|
|
return "OR-WE-515";
|
|
case ENERGY_METER_ORNO_517:
|
|
return "OR-WE-517";
|
|
default:
|
|
return "NONE";
|
|
}
|
|
}
|
|
|
|
meter_model_t meter_str_to_model(const char *str)
|
|
{
|
|
if (!strcmp(str, "NONE"))
|
|
{
|
|
return ENERGY_METER_NONE;
|
|
}
|
|
if (!strcmp(str, "OR-WE-515"))
|
|
{
|
|
return ENERGY_METER_ORNO_515;
|
|
}
|
|
if (!strcmp(str, "OR-WE-517"))
|
|
{
|
|
return ENERGY_METER_ORNO_517;
|
|
}
|
|
|
|
return ENERGY_METER_NONE;
|
|
}
|