#include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" #include "esp_log.h" #include "outputs.h" static const char *TAG = "smart-oil-heater-control-system-outputs"; const uint8_t uCirculationPumpGpioPin = 27U; const uint8_t uBurnerGpioPin = 14U; const uint8_t uSafetyContactGpioPin = 12U; static SemaphoreHandle_t xMutexAccessOutputs = NULL; static eOutput sCirculationPumpState; static eOutput sBurnerState; static eOutput sSafetyContactState; void initOutputs(void) { gpio_config_t ioConfCirculationPump = { .pin_bit_mask = (1ULL << uCirculationPumpGpioPin), // Pin mask .mode = GPIO_MODE_OUTPUT, // Set as output .pull_up_en = GPIO_PULLUP_DISABLE, // Disable pull-up .pull_down_en = GPIO_PULLDOWN_DISABLE, // Disable pull-down .intr_type = GPIO_INTR_DISABLE // Disable interrupts }; gpio_config_t ioConfBurner = { .pin_bit_mask = (1ULL << uBurnerGpioPin), // Pin mask .mode = GPIO_MODE_OUTPUT, // Set as output .pull_up_en = GPIO_PULLUP_DISABLE, // Disable pull-up .pull_down_en = GPIO_PULLDOWN_DISABLE, // Disable pull-down .intr_type = GPIO_INTR_DISABLE // Disable interrupts }; gpio_config_t ioConfSafetyContact = { .pin_bit_mask = (1ULL << uSafetyContactGpioPin), // Pin mask .mode = GPIO_MODE_OUTPUT, // Set as output .pull_up_en = GPIO_PULLUP_DISABLE, // Disable pull-up .pull_down_en = GPIO_PULLDOWN_DISABLE, // Disable pull-down .intr_type = GPIO_INTR_DISABLE // Disable interrupts }; gpio_config(&ioConfCirculationPump); gpio_config(&ioConfBurner); gpio_config(&ioConfSafetyContact); xMutexAccessOutputs = xSemaphoreCreateRecursiveMutex(); if (xMutexAccessOutputs == NULL) { ESP_LOGE(TAG, "Unable to create mutex"); } xSemaphoreGiveRecursive(xMutexAccessOutputs); } eOutput getCirculationPumpState(void) { return sCirculationPumpState; } void setCirculationPumpState(eOutput in) { if (xSemaphoreTakeRecursive(xMutexAccessOutputs, pdMS_TO_TICKS(5000)) == pdTRUE) { sCirculationPumpState = in; switch (sCirculationPumpState) { case ENABLED: gpio_set_level(uCirculationPumpGpioPin, 1U); // Switch on Circulation Pump break; case DISABLED: gpio_set_level(uCirculationPumpGpioPin, 0U); // Switch off Circulation Pump default: break; } xSemaphoreGiveRecursive(xMutexAccessOutputs); } else { ESP_LOGE(TAG, "Unable to take mutex: setCirculationPumpState()"); } } eOutput getBurnerState(void) { eOutput ret = ENABLED; if (xSemaphoreTakeRecursive(xMutexAccessOutputs, pdMS_TO_TICKS(5000)) == pdTRUE) { ret = sBurnerState; xSemaphoreGiveRecursive(xMutexAccessOutputs); } else { ESP_LOGE(TAG, "Unable to take mutex: getBurnerState()"); } return ret; } void setBurnerState(eOutput in) { if (xSemaphoreTakeRecursive(xMutexAccessOutputs, pdMS_TO_TICKS(5000)) == pdTRUE) { sBurnerState = in; switch (sBurnerState) { case ENABLED: gpio_set_level(uBurnerGpioPin, 0U); // Switch on Burner break; case DISABLED: gpio_set_level(uBurnerGpioPin, 1U); // Switch off Burner default: break; } xSemaphoreGiveRecursive(xMutexAccessOutputs); } else { ESP_LOGE(TAG, "Unable to take mutex: setBurnerState()"); } } eOutput getSafetyControlState(void) { eOutput ret = ENABLED; if (xSemaphoreTakeRecursive(xMutexAccessOutputs, pdMS_TO_TICKS(5000)) == pdTRUE) { ret = sSafetyContactState; xSemaphoreGiveRecursive(xMutexAccessOutputs); } else { ESP_LOGE(TAG, "Unable to take mutex: getSafetyControlState()"); } return ret; } void setSafetyControlState(eOutput in) { if (xSemaphoreTakeRecursive(xMutexAccessOutputs, pdMS_TO_TICKS(5000)) == pdTRUE) { sSafetyContactState = in; switch (sSafetyContactState) { case ENABLED: gpio_set_level(uSafetyContactGpioPin, 0U); // Switch on power for Burner break; case DISABLED: gpio_set_level(uSafetyContactGpioPin, 1U); // Switch off power for Burner default: break; } xSemaphoreGiveRecursive(xMutexAccessOutputs); } else { ESP_LOGE(TAG, "Unable to take mutex: setSafetyControlState()"); } }