141 lines
3.8 KiB
C
Executable File
141 lines
3.8 KiB
C
Executable File
#include "meter_ade7758.h"
|
|
#include "ade7758.h"
|
|
#include "meter_events.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_ade7758"
|
|
|
|
// === 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_ade7758_internal_data_t;
|
|
|
|
static meter_ade7758_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_ade7758_post_event(const meter_ade7758_internal_data_t *data) {
|
|
meter_event_data_t evt = {
|
|
.frequency = 0,
|
|
.power_factor = 0,
|
|
.total_energy = 0
|
|
};
|
|
|
|
memcpy(evt.vrms, data->vrms, sizeof(evt.vrms));
|
|
memcpy(evt.irms, data->irms, sizeof(evt.irms));
|
|
memcpy(evt.watt, data->watt, sizeof(evt.watt));
|
|
|
|
esp_err_t err = esp_event_post(METER_EVENT, METER_EVENT_DATA_READY,
|
|
&evt, sizeof(evt), pdMS_TO_TICKS(10));
|
|
|
|
if (err != ESP_OK) {
|
|
ESP_LOGW(TAG, "Falha ao emitir evento: %s", esp_err_to_name(err));
|
|
}
|
|
}
|
|
|
|
static void meter_ade7758_task_func(void *param) {
|
|
ESP_LOGI(TAG, "Meter task started");
|
|
|
|
meter_ade7758_internal_data_t previous = {0};
|
|
|
|
while (true) {
|
|
meter_ade7758_internal_data_t meterData = {0};
|
|
|
|
meterData.vrms[0] = avrms() / VRMS_CAL;
|
|
meterData.vrms[1] = bvrms() / VRMS_CAL;
|
|
meterData.vrms[2] = cvrms() / VRMS_CAL;
|
|
|
|
meterData.irms[0] = airms() / IRMS_CAL;
|
|
meterData.irms[1] = birms() / IRMS_CAL;
|
|
meterData.irms[2] = cirms() / IRMS_CAL;
|
|
|
|
if (setPotLine(PHASE_A, 20)) meterData.watt[0] = getWatt(PHASE_A);
|
|
if (setPotLine(PHASE_B, 20)) meterData.watt[1] = getWatt(PHASE_B);
|
|
if (setPotLine(PHASE_C, 20)) meterData.watt[2] = getWatt(PHASE_C);
|
|
|
|
if (memcmp(&previous, &meterData, sizeof(meterData)) != 0) {
|
|
if (xSemaphoreTake(meter_mutex, pdMS_TO_TICKS(10)) == pdTRUE) {
|
|
meter_data = meterData;
|
|
meter_watchdog_counter++;
|
|
xSemaphoreGive(meter_mutex);
|
|
|
|
meter_ade7758_post_event(&meterData);
|
|
}
|
|
previous = meterData;
|
|
}
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(METER_READ_INTERVAL_MS));
|
|
}
|
|
}
|
|
|
|
// === Interface pública: controle ===
|
|
|
|
esp_err_t meter_ade7758_init(void) {
|
|
ESP_LOGI(TAG, "Inicializando medidor ADE7758...");
|
|
|
|
if (!meter_mutex) {
|
|
meter_mutex = xSemaphoreCreateMutex();
|
|
if (!meter_mutex) {
|
|
ESP_LOGE(TAG, "Falha ao criar mutex");
|
|
return ESP_ERR_NO_MEM;
|
|
}
|
|
}
|
|
|
|
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_ade7758_start(void) {
|
|
if (meter_task) return ESP_ERR_INVALID_STATE;
|
|
|
|
BaseType_t result = xTaskCreate(meter_ade7758_task_func, "meter_ade7758_task", 4096, NULL, 3, &meter_task);
|
|
return result == pdPASS ? ESP_OK : ESP_FAIL;
|
|
}
|
|
|
|
void meter_ade7758_stop(void) {
|
|
if (meter_task) {
|
|
vTaskDelete(meter_task);
|
|
meter_task = NULL;
|
|
}
|
|
}
|