#include <stm32c0xx_hal.h>
#include "dht22.h" // Include the DHT22 library header
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include <semphr.h>
#include <stdio.h>
// GPIO Pins Definition
#define HUMIDITY_SENSOR1_PIN GPIO_PIN_0 // Humidity Sensor 1 on PA0
#define HUMIDITY_SENSOR2_PIN GPIO_PIN_1 // Humidity Sensor 2 on PA1
#define VALVE1_PIN GPIO_PIN_5 // Simulated Valve 1 (LED) on PA5
#define VALVE2_PIN GPIO_PIN_6 // Simulated Valve 2 (LED) on PA6
#define EMERGENCY_BUTTON_PIN GPIO_PIN_4 // Emergency Stop Button on PA4
#define POTENTIOMETER_PIN GPIO_PIN_3 // Potentiometer on PB3
#define EMERGENCY_LED_PIN GPIO_PIN_7 // Red LED for Emergency Stop on PA7
// Global Variables
SemaphoreHandle_t emergencySemaphore;
SemaphoreHandle_t humidityThresholdMutex;
QueueHandle_t humidityQueue;
uint8_t humidityThreshold = 50; // Initial humidity threshold (50%)
// DHT22 objects
DHT22 dht1;
DHT22 dht2;
// Function Prototypes
void SystemClock_Config(void);
void GPIO_Init(void);
void ReadHumidityTask(void *pvParameters);
void ValveControlTask(void *pvParameters);
void EmergencyButtonTask(void *pvParameters);
void PotentiometerTask(void *pvParameters);
void LogEvent(const char* event);
// Main Function
int main(void) {
// HAL Initialization
HAL_Init();
// System Clock Configuration
SystemClock_Config();
// GPIO Initialization
GPIO_Init();
// Initialize DHT22 sensors
dht22_init(&dht1, GPIOA, HUMIDITY_SENSOR1_PIN);
dht22_init(&dht2, GPIOA, HUMIDITY_SENSOR2_PIN);
// Create FreeRTOS resources
emergencySemaphore = xSemaphoreCreateBinary();
humidityQueue = xQueueCreate(10, sizeof(uint8_t));
humidityThresholdMutex = xSemaphoreCreateMutex();
if (!humidityThresholdMutex || !humidityQueue || !emergencySemaphore) {
LogEvent("Error creating FreeRTOS resources.");
while (1);
}
// Create FreeRTOS tasks
xTaskCreate(ReadHumidityTask, "Read Humidity", 128, NULL, 1, NULL);
xTaskCreate(ValveControlTask, "Valve Control", 128, NULL, 2, NULL);
xTaskCreate(EmergencyButtonTask, "Emergency Button", 128, NULL, 3, NULL);
xTaskCreate(PotentiometerTask, "Potentiometer", 128, NULL, 1, NULL);
// Start the FreeRTOS scheduler
vTaskStartScheduler();
// If the scheduler fails
while (1);
}
// GPIO Initialization
void GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
// Configure humidity sensors and emergency button as input
GPIO_InitStruct.Pin = HUMIDITY_SENSOR1_PIN | HUMIDITY_SENSOR2_PIN | EMERGENCY_BUTTON_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Configure valves and emergency LED as output
GPIO_InitStruct.Pin = VALVE1_PIN | VALVE2_PIN | EMERGENCY_LED_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Configure potentiometer as input
GPIO_InitStruct.Pin = POTENTIOMETER_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
// Humidity Reading Task
void ReadHumidityTask(void *pvParameters) {
float humidity1, humidity2;
while (1) {
// Read humidity from DHT22 sensors
if (dht22_read(&dht1, &humidity1, NULL) && dht22_read(&dht2, &humidity2, NULL)) {
xSemaphoreTake(humidityThresholdMutex, portMAX_DELAY);
uint8_t currentThreshold = humidityThreshold;
xSemaphoreGive(humidityThresholdMutex);
// Send to queue if below threshold
if (humidity1 < currentThreshold) {
uint8_t zone = 1;
xQueueSend(humidityQueue, &zone, portMAX_DELAY);
}
if (humidity2 < currentThreshold) {
uint8_t zone = 2;
xQueueSend(humidityQueue, &zone, portMAX_DELAY);
}
} else {
LogEvent("DHT22 read error.");
}
vTaskDelay(pdMS_TO_TICKS(5000)); // 5-second interval
}
}
// Valve Control Task
void ValveControlTask(void *pvParameters) {
uint8_t zone;
while (1) {
if (xQueueReceive(humidityQueue, &zone, portMAX_DELAY)) {
if (zone == 1) {
HAL_GPIO_WritePin(GPIOA, VALVE1_PIN, GPIO_PIN_SET);
LogEvent("Valve 1 activated.");
vTaskDelay(pdMS_TO_TICKS(10000));
HAL_GPIO_WritePin(GPIOA, VALVE1_PIN, GPIO_PIN_RESET);
LogEvent("Valve 1 deactivated.");
} else if (zone == 2) {
HAL_GPIO_WritePin(GPIOA, VALVE2_PIN, GPIO_PIN_SET);
LogEvent("Valve 2 activated.");
vTaskDelay(pdMS_TO_TICKS(10000));
HAL_GPIO_WritePin(GPIOA, VALVE2_PIN, GPIO_PIN_RESET);
LogEvent("Valve 2 deactivated.");
}
}
}
}
// Emergency Button Task
void EmergencyButtonTask(void *pvParameters) {
while (1) {
if (HAL_GPIO_ReadPin(GPIOA, EMERGENCY_BUTTON_PIN) == GPIO_PIN_SET) {
HAL_GPIO_WritePin(GPIOA, VALVE1_PIN | VALVE2_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, EMERGENCY_LED_PIN, GPIO_PIN_SET);
LogEvent("Emergency stop activated!");
xSemaphoreGive(emergencySemaphore);
}
vTaskDelay(pdMS_TO_TICKS(50)); // Debouncing
}
}
// Potentiometer Task
void PotentiometerTask(void *pvParameters) {
while (1) {
uint8_t potentiometerValue = HAL_GPIO_ReadPin(GPIOB, POTENTIOMETER_PIN) ? 60 : 40;
xSemaphoreTake(humidityThresholdMutex, portMAX_DELAY);
humidityThreshold = potentiometerValue;
xSemaphoreGive(humidityThresholdMutex);
LogEvent("Humidity threshold updated.");
vTaskDelay(pdMS_TO_TICKS(5000));
}
}
// Event Logging Function
void LogEvent(const char* event) {
printf("%s\n", event);
}
// System Clock Configuration (Placeholder)
void SystemClock_Config(void) {
// Placeholder for clock configuration
}