add orno driver
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"src/ade7758.c"
|
||||
"src/meter.c"
|
||||
"src/energy_meter.c"
|
||||
"src/meter_ade7758.c"
|
||||
INCLUDE_DIRS
|
||||
"include"
|
||||
REQUIRES
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
#ifndef METER_H_
|
||||
#define METER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
/**
|
||||
* @brief Grid energy meter model
|
||||
*/
|
||||
typedef enum {
|
||||
ENERGY_METER_NONE,
|
||||
ENERGY_METER_ORNO_515,
|
||||
ENERGY_METER_ORNO_517,
|
||||
} meter_model_t;
|
||||
|
||||
/**
|
||||
* @brief Estrutura com os dados de medição trifásica.
|
||||
*/
|
||||
typedef struct MeterData
|
||||
{
|
||||
float vrmsA;
|
||||
float vrmsB;
|
||||
float vrmsC;
|
||||
float irmsA;
|
||||
float irmsB;
|
||||
float irmsC;
|
||||
int32_t wattA;
|
||||
int32_t varA;
|
||||
int32_t vaA;
|
||||
int32_t wattB;
|
||||
int32_t varB;
|
||||
int32_t vaB;
|
||||
int32_t wattC;
|
||||
int32_t varC;
|
||||
int32_t vaC;
|
||||
} MeterData;
|
||||
|
||||
/**
|
||||
* @brief Inicializa o hardware do medidor e recursos internos (SPI, mutex).
|
||||
*/
|
||||
void meter_init(void);
|
||||
|
||||
/**
|
||||
* @brief Inicia a task de medição.
|
||||
*/
|
||||
void meter_start(void);
|
||||
|
||||
/**
|
||||
* @brief Para a task de medição e reseta dados.
|
||||
*/
|
||||
void meter_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Zera todos os campos da estrutura de dados do medidor.
|
||||
*/
|
||||
void meter_initData(void);
|
||||
|
||||
/**
|
||||
* @brief Retorna uma cópia segura dos dados atuais do medidor.
|
||||
*
|
||||
* @return MeterData Cópia da última leitura válida.
|
||||
*/
|
||||
MeterData meter_getData(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check if meter task is currently running.
|
||||
*
|
||||
* @return true if running, false otherwise.
|
||||
*/
|
||||
bool meter_is_running(void);
|
||||
|
||||
// High level energy meter API
|
||||
void energy_meter_init(void);
|
||||
bool meter_get_state(void);
|
||||
esp_err_t meter_set_state(bool _state);
|
||||
meter_model_t meter_get_model(void);
|
||||
esp_err_t meter_set_model(meter_model_t mode);
|
||||
void energy_meter_start_session(void);
|
||||
void energy_meter_stop_session(void);
|
||||
void energy_meter_process(bool charging, uint16_t charging_current);
|
||||
uint32_t energy_meter_get_power(void);
|
||||
uint32_t energy_meter_get_session_time(void);
|
||||
uint32_t energy_meter_get_charging_time(void);
|
||||
uint32_t energy_meter_get_consumption(void);
|
||||
void energy_meter_get_voltage(float *voltage);
|
||||
float energy_meter_get_l1_voltage(void);
|
||||
float energy_meter_get_l2_voltage(void);
|
||||
float energy_meter_get_l3_voltage(void);
|
||||
void energy_meter_get_current(float *current);
|
||||
float energy_meter_get_l1_current(void);
|
||||
float energy_meter_get_l2_current(void);
|
||||
float energy_meter_get_l3_current(void);
|
||||
const char *meter_model_to_str(meter_model_t mode);
|
||||
meter_model_t meter_str_to_model(const char *str);
|
||||
const char *meter_state_to_str(bool state);
|
||||
bool meter_str_to_state(const char *str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* METER_H_ */
|
||||
70
components/meter_ade7758/include/meter_ade7758.h
Executable file
70
components/meter_ade7758/include/meter_ade7758.h
Executable file
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
/**
|
||||
* @brief Inicializa o driver do medidor (SPI, mutex, registradores ADE7758).
|
||||
*/
|
||||
esp_err_t meter_init(void);
|
||||
|
||||
/**
|
||||
* @brief Inicia a tarefa de leitura de dados do medidor.
|
||||
*/
|
||||
esp_err_t meter_start(void);
|
||||
|
||||
/**
|
||||
* @brief Para a tarefa de leitura e limpa os dados internos.
|
||||
*/
|
||||
void meter_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Verifica se o medidor está em execução.
|
||||
*
|
||||
* @return true se a tarefa estiver ativa, false caso contrário.
|
||||
*/
|
||||
bool meter_is_running(void);
|
||||
|
||||
/**
|
||||
* @brief Limpa os dados armazenados no medidor (zera todos os valores).
|
||||
*/
|
||||
void meter_clear_data(void);
|
||||
|
||||
// ----- Leituras por fase (L1, L2, L3) -----
|
||||
|
||||
// Tensão RMS (em volts)
|
||||
float meter_get_vrms_l1(void);
|
||||
float meter_get_vrms_l2(void);
|
||||
float meter_get_vrms_l3(void);
|
||||
|
||||
// Corrente RMS (em amperes)
|
||||
float meter_get_irms_l1(void);
|
||||
float meter_get_irms_l2(void);
|
||||
float meter_get_irms_l3(void);
|
||||
|
||||
// Potência ativa (W)
|
||||
int meter_get_watt_l1(void);
|
||||
int meter_get_watt_l2(void);
|
||||
int meter_get_watt_l3(void);
|
||||
|
||||
// Potência reativa (VAR)
|
||||
int meter_get_var_l1(void);
|
||||
int meter_get_var_l2(void);
|
||||
int meter_get_var_l3(void);
|
||||
|
||||
// Potência aparente (VA)
|
||||
int meter_get_va_l1(void);
|
||||
int meter_get_va_l2(void);
|
||||
int meter_get_va_l3(void);
|
||||
|
||||
// (Opcional) contador de watchdog para diagnóstico
|
||||
uint32_t meter_get_watchdog_counter(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,237 +0,0 @@
|
||||
#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 "meter.h"
|
||||
#include "orno_modbus.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 orno_modbus_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);
|
||||
orno_modbus_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;
|
||||
}
|
||||
|
||||
bool meter_str_to_state(const char *str)
|
||||
{
|
||||
return strcmp(str, "CONNECTED") == 0;
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
#include "meter.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "ade7758.h"
|
||||
#include "evse_api.h"
|
||||
|
||||
#define TAG "meter"
|
||||
|
||||
// SPI Config
|
||||
#define PIN_NUM_CLK 15
|
||||
#define PIN_NUM_MOSI 2
|
||||
#define PIN_NUM_MISO 4
|
||||
#define PIN_NUM_CS 23
|
||||
#define EEPROM_HOST HSPI_HOST
|
||||
|
||||
// Calibration constants
|
||||
#define VRMS_CAL 4732.78f
|
||||
#define IRMS_CAL 53416.0f
|
||||
|
||||
#define METER_READ_INTERVAL_MS 5000
|
||||
|
||||
static TaskHandle_t meter_task = NULL;
|
||||
static MeterData metervalue;
|
||||
static SemaphoreHandle_t meter_mutex = NULL;
|
||||
|
||||
static uint32_t meter_watchdog_counter = 0;
|
||||
|
||||
void meter_initData(void) {
|
||||
if (xSemaphoreTake(meter_mutex, pdMS_TO_TICKS(10)) == pdTRUE) {
|
||||
memset(&metervalue, 0, sizeof(metervalue));
|
||||
xSemaphoreGive(meter_mutex);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Falha ao adquirir semáforo para zerar dados.");
|
||||
}
|
||||
}
|
||||
|
||||
MeterData meter_getData(void) {
|
||||
MeterData copy;
|
||||
if (xSemaphoreTake(meter_mutex, pdMS_TO_TICKS(10)) == pdTRUE) {
|
||||
copy = metervalue;
|
||||
xSemaphoreGive(meter_mutex);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Falha ao adquirir semáforo para leitura de dados.");
|
||||
memset(©, 0, sizeof(copy));
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
bool meter_is_running(void) {
|
||||
return meter_task != NULL;
|
||||
}
|
||||
|
||||
uint32_t meter_get_watchdog_counter(void) {
|
||||
return meter_watchdog_counter;
|
||||
}
|
||||
|
||||
static void meter_task_func(void *param) {
|
||||
ESP_LOGI(TAG, "Meter task started");
|
||||
|
||||
MeterData previousData = {0};
|
||||
bool dataChanged = false;
|
||||
|
||||
while (true) {
|
||||
if (evse_state_is_charging(evse_get_state())) {
|
||||
MeterData local = {0};
|
||||
|
||||
local.vrmsA = avrms() / VRMS_CAL;
|
||||
local.vrmsB = bvrms() / VRMS_CAL;
|
||||
local.vrmsC = cvrms() / VRMS_CAL;
|
||||
|
||||
local.irmsA = airms() / IRMS_CAL;
|
||||
local.irmsB = birms() / IRMS_CAL;
|
||||
local.irmsC = cirms() / IRMS_CAL;
|
||||
|
||||
ESP_LOGD(TAG, "VRMS: A=%.2f, B=%.2f, C=%.2f", local.vrmsA, local.vrmsB, local.vrmsC);
|
||||
ESP_LOGD(TAG, "IRMS: A=%.2f, B=%.2f, C=%.2f", local.irmsA, local.irmsB, local.irmsC);
|
||||
|
||||
if (setPotLine(PHASE_A, 20)) {
|
||||
local.wattA = getWatt(PHASE_A);
|
||||
ESP_LOGD(TAG, "Watt A: %" PRIi32, local.wattA);
|
||||
}
|
||||
|
||||
if (setPotLine(PHASE_B, 20)) {
|
||||
local.wattB = getWatt(PHASE_B);
|
||||
ESP_LOGD(TAG, "Watt B: %" PRIi32, local.wattB);
|
||||
}
|
||||
|
||||
if (setPotLine(PHASE_C, 20)) {
|
||||
local.wattC = getWatt(PHASE_C);
|
||||
ESP_LOGI(TAG, "Watt C: %" PRIi32, local.wattC);
|
||||
}
|
||||
|
||||
// Verifique se os dados mudaram antes de atualizar
|
||||
if (memcmp(&local, &previousData, sizeof(MeterData)) != 0) {
|
||||
dataChanged = true;
|
||||
previousData = local;
|
||||
} else {
|
||||
dataChanged = false;
|
||||
}
|
||||
|
||||
if (dataChanged && xSemaphoreTake(meter_mutex, pdMS_TO_TICKS(10)) == pdTRUE) {
|
||||
metervalue = local;
|
||||
meter_watchdog_counter++;
|
||||
xSemaphoreGive(meter_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(METER_READ_INTERVAL_MS));
|
||||
}
|
||||
}
|
||||
|
||||
void Calibrate_ADE7758(void) {
|
||||
gainSetup(INTEGRATOR_OFF, FULLSCALESELECT_0_5V, GAIN_1, GAIN_1);
|
||||
setupDivs(1, 1, 1);
|
||||
setLcycMode(0x00);
|
||||
resetStatus();
|
||||
}
|
||||
|
||||
void meter_init(void) {
|
||||
ESP_LOGI(TAG, "Initializing meter");
|
||||
|
||||
if (!meter_mutex) {
|
||||
meter_mutex = xSemaphoreCreateMutex();
|
||||
if (!meter_mutex) {
|
||||
ESP_LOGE(TAG, "Erro ao criar semáforo de mutex");
|
||||
return; // Pode parar a inicialização caso não consiga criar o mutex
|
||||
}
|
||||
}
|
||||
|
||||
meter_initData();
|
||||
esp_err_t err = Init(EEPROM_HOST, PIN_NUM_MISO, PIN_NUM_MOSI, PIN_NUM_CLK);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Erro na inicialização do hardware SPI: %d", err);
|
||||
return;
|
||||
}
|
||||
|
||||
InitSpi(PIN_NUM_CS);
|
||||
}
|
||||
|
||||
void meter_start(void) {
|
||||
ESP_LOGI(TAG, "Starting meter");
|
||||
|
||||
Calibrate_ADE7758();
|
||||
meter_initData();
|
||||
|
||||
if (!meter_task) {
|
||||
xTaskCreate(meter_task_func, "meter_task", 5 * 1024, NULL, 5, &meter_task);
|
||||
}
|
||||
}
|
||||
|
||||
void meter_stop(void) {
|
||||
ESP_LOGI(TAG, "Stopping meter");
|
||||
|
||||
if (meter_task) {
|
||||
vTaskDelete(meter_task);
|
||||
meter_task = NULL;
|
||||
}
|
||||
|
||||
meter_initData();
|
||||
}
|
||||
177
components/meter_ade7758/src/meter_ade7758.c
Executable file
177
components/meter_ade7758/src/meter_ade7758.c
Executable file
@@ -0,0 +1,177 @@
|
||||
#include "meter_ade7758.h"
|
||||
#include "ade7758.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#include "driver/spi_master.h"
|
||||
|
||||
|
||||
#define TAG "meter"
|
||||
|
||||
// === Configurações de hardware ===
|
||||
#define PIN_NUM_CLK 15
|
||||
#define PIN_NUM_MOSI 2
|
||||
#define PIN_NUM_MISO 4
|
||||
#define PIN_NUM_CS 23
|
||||
#define EEPROM_HOST HSPI_HOST
|
||||
|
||||
// === Constantes de calibração ===
|
||||
#define VRMS_CAL 4732.78f
|
||||
#define IRMS_CAL 53416.0f
|
||||
|
||||
#define METER_READ_INTERVAL_MS 5000
|
||||
|
||||
// === Dados internos ===
|
||||
typedef struct {
|
||||
float vrms[3];
|
||||
float irms[3];
|
||||
int watt[3];
|
||||
int var[3]; // reservados
|
||||
int va[3]; // reservados
|
||||
} meter_internal_data_t;
|
||||
|
||||
static meter_internal_data_t meter_data;
|
||||
static TaskHandle_t meter_task = NULL;
|
||||
static SemaphoreHandle_t meter_mutex = NULL;
|
||||
static uint32_t meter_watchdog_counter = 0;
|
||||
|
||||
// === Utilitários internos ===
|
||||
|
||||
static void meter_clear_internal_data(void) {
|
||||
if (meter_mutex && xSemaphoreTake(meter_mutex, pdMS_TO_TICKS(10)) == pdTRUE) {
|
||||
memset(&meter_data, 0, sizeof(meter_data));
|
||||
xSemaphoreGive(meter_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static bool meter_read_internal(meter_internal_data_t *out) {
|
||||
if (!out) return false;
|
||||
if (xSemaphoreTake(meter_mutex, pdMS_TO_TICKS(10)) == pdTRUE) {
|
||||
*out = meter_data;
|
||||
xSemaphoreGive(meter_mutex);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void meter_task_func(void *param) {
|
||||
ESP_LOGI(TAG, "Meter task started");
|
||||
|
||||
meter_internal_data_t previous = {0};
|
||||
|
||||
while (true) {
|
||||
meter_internal_data_t current = {0};
|
||||
|
||||
current.vrms[0] = avrms() / VRMS_CAL;
|
||||
current.vrms[1] = bvrms() / VRMS_CAL;
|
||||
current.vrms[2] = cvrms() / VRMS_CAL;
|
||||
|
||||
current.irms[0] = airms() / IRMS_CAL;
|
||||
current.irms[1] = birms() / IRMS_CAL;
|
||||
current.irms[2] = cirms() / IRMS_CAL;
|
||||
|
||||
if (setPotLine(PHASE_A, 20)) current.watt[0] = getWatt(PHASE_A);
|
||||
if (setPotLine(PHASE_B, 20)) current.watt[1] = getWatt(PHASE_B);
|
||||
if (setPotLine(PHASE_C, 20)) current.watt[2] = getWatt(PHASE_C);
|
||||
|
||||
if (memcmp(&previous, ¤t, sizeof(current)) != 0) {
|
||||
if (xSemaphoreTake(meter_mutex, pdMS_TO_TICKS(10)) == pdTRUE) {
|
||||
meter_data = current;
|
||||
meter_watchdog_counter++;
|
||||
xSemaphoreGive(meter_mutex);
|
||||
}
|
||||
previous = current;
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(METER_READ_INTERVAL_MS));
|
||||
}
|
||||
}
|
||||
|
||||
// === Interface pública: controle ===
|
||||
|
||||
esp_err_t meter_init(void) {
|
||||
ESP_LOGI(TAG, "Inicializando medidor...");
|
||||
|
||||
if (!meter_mutex) {
|
||||
meter_mutex = xSemaphoreCreateMutex();
|
||||
if (!meter_mutex) {
|
||||
ESP_LOGE(TAG, "Falha ao criar mutex");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
meter_clear_internal_data();
|
||||
|
||||
esp_err_t err = Init(EEPROM_HOST, PIN_NUM_MISO, PIN_NUM_MOSI, PIN_NUM_CLK);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Erro ao inicializar SPI (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
InitSpi(PIN_NUM_CS);
|
||||
gainSetup(INTEGRATOR_OFF, FULLSCALESELECT_0_5V, GAIN_1, GAIN_1);
|
||||
setupDivs(1, 1, 1);
|
||||
setLcycMode(0x00);
|
||||
resetStatus();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t meter_start(void) {
|
||||
if (meter_task) return ESP_ERR_INVALID_STATE;
|
||||
|
||||
meter_clear_internal_data();
|
||||
BaseType_t result = xTaskCreate(meter_task_func, "meter_task", 4096, NULL, 5, &meter_task);
|
||||
return result == pdPASS ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
void meter_stop(void) {
|
||||
if (meter_task) {
|
||||
vTaskDelete(meter_task);
|
||||
meter_task = NULL;
|
||||
}
|
||||
meter_clear_internal_data();
|
||||
}
|
||||
|
||||
bool meter_is_running(void) {
|
||||
return meter_task != NULL;
|
||||
}
|
||||
|
||||
void meter_clear_data(void) {
|
||||
meter_clear_internal_data();
|
||||
}
|
||||
|
||||
// === Interface pública: acesso aos dados ===
|
||||
|
||||
float meter_get_vrms_l1(void) { meter_internal_data_t d; return meter_read_internal(&d) ? d.vrms[0] : 0; }
|
||||
float meter_get_vrms_l2(void) { meter_internal_data_t d; return meter_read_internal(&d) ? d.vrms[1] : 0; }
|
||||
float meter_get_vrms_l3(void) { meter_internal_data_t d; return meter_read_internal(&d) ? d.vrms[2] : 0; }
|
||||
|
||||
float meter_get_irms_l1(void) { meter_internal_data_t d; return meter_read_internal(&d) ? d.irms[0] : 0; }
|
||||
float meter_get_irms_l2(void) { meter_internal_data_t d; return meter_read_internal(&d) ? d.irms[1] : 0; }
|
||||
float meter_get_irms_l3(void) { meter_internal_data_t d; return meter_read_internal(&d) ? d.irms[2] : 0; }
|
||||
|
||||
int meter_get_watt_l1(void) { meter_internal_data_t d; return meter_read_internal(&d) ? d.watt[0] : 0; }
|
||||
int meter_get_watt_l2(void) { meter_internal_data_t d; return meter_read_internal(&d) ? d.watt[1] : 0; }
|
||||
int meter_get_watt_l3(void) { meter_internal_data_t d; return meter_read_internal(&d) ? d.watt[2] : 0; }
|
||||
|
||||
int meter_get_var_l1(void) { meter_internal_data_t d; return meter_read_internal(&d) ? d.var[0] : 0; }
|
||||
int meter_get_var_l2(void) { meter_internal_data_t d; return meter_read_internal(&d) ? d.var[1] : 0; }
|
||||
int meter_get_var_l3(void) { meter_internal_data_t d; return meter_read_internal(&d) ? d.var[2] : 0; }
|
||||
|
||||
int meter_get_va_l1(void) { meter_internal_data_t d; return meter_read_internal(&d) ? d.va[0] : 0; }
|
||||
int meter_get_va_l2(void) { meter_internal_data_t d; return meter_read_internal(&d) ? d.va[1] : 0; }
|
||||
int meter_get_va_l3(void) { meter_internal_data_t d; return meter_read_internal(&d) ? d.va[2] : 0; }
|
||||
|
||||
// === Diagnóstico ===
|
||||
|
||||
uint32_t meter_get_watchdog_counter(void) {
|
||||
return meter_watchdog_counter;
|
||||
}
|
||||
Reference in New Issue
Block a user