#include "meter.h" #include #include #include #include #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(); }