#include "meter_ade7758.h" #include "ade7758.h" #include #include #include #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_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_ade7758_read_internal(meter_ade7758_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_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 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_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; } } meter_ade7758_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_ade7758_start(void) { if (meter_task) return ESP_ERR_INVALID_STATE; meter_ade7758_clear_internal_data(); BaseType_t result = xTaskCreate(meter_ade7758_task_func, "meter_ade7758_task", 4096, NULL, 5, &meter_task); return result == pdPASS ? ESP_OK : ESP_FAIL; } void meter_ade7758_stop(void) { if (meter_task) { vTaskDelete(meter_task); meter_task = NULL; } meter_ade7758_clear_internal_data(); } bool meter_ade7758_is_running(void) { return meter_task != NULL; } void meter_ade7758_clear_data(void) { meter_ade7758_clear_internal_data(); } // === Interface pública: acesso aos dados === float meter_ade7758_get_vrms_l1(void) { meter_ade7758_internal_data_t d; return meter_ade7758_read_internal(&d) ? d.vrms[0] : 0; } float meter_ade7758_get_vrms_l2(void) { meter_ade7758_internal_data_t d; return meter_ade7758_read_internal(&d) ? d.vrms[1] : 0; } float meter_ade7758_get_vrms_l3(void) { meter_ade7758_internal_data_t d; return meter_ade7758_read_internal(&d) ? d.vrms[2] : 0; } float meter_ade7758_get_irms_l1(void) { meter_ade7758_internal_data_t d; return meter_ade7758_read_internal(&d) ? d.irms[0] : 0; } float meter_ade7758_get_irms_l2(void) { meter_ade7758_internal_data_t d; return meter_ade7758_read_internal(&d) ? d.irms[1] : 0; } float meter_ade7758_get_irms_l3(void) { meter_ade7758_internal_data_t d; return meter_ade7758_read_internal(&d) ? d.irms[2] : 0; } int meter_ade7758_get_watt_l1(void) { meter_ade7758_internal_data_t d; return meter_ade7758_read_internal(&d) ? d.watt[0] : 0; } int meter_ade7758_get_watt_l2(void) { meter_ade7758_internal_data_t d; return meter_ade7758_read_internal(&d) ? d.watt[1] : 0; } int meter_ade7758_get_watt_l3(void) { meter_ade7758_internal_data_t d; return meter_ade7758_read_internal(&d) ? d.watt[2] : 0; } int meter_ade7758_get_var_l1(void) { meter_ade7758_internal_data_t d; return meter_ade7758_read_internal(&d) ? d.var[0] : 0; } int meter_ade7758_get_var_l2(void) { meter_ade7758_internal_data_t d; return meter_ade7758_read_internal(&d) ? d.var[1] : 0; } int meter_ade7758_get_var_l3(void) { meter_ade7758_internal_data_t d; return meter_ade7758_read_internal(&d) ? d.var[2] : 0; } int meter_ade7758_get_va_l1(void) { meter_ade7758_internal_data_t d; return meter_ade7758_read_internal(&d) ? d.va[0] : 0; } int meter_ade7758_get_va_l2(void) { meter_ade7758_internal_data_t d; return meter_ade7758_read_internal(&d) ? d.va[1] : 0; } int meter_ade7758_get_va_l3(void) { meter_ade7758_internal_data_t d; return meter_ade7758_read_internal(&d) ? d.va[2] : 0; } // === Diagnóstico === uint32_t meter_ade7758_get_watchdog_counter(void) { return meter_watchdog_counter; }