#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "stm32c0xx_hal.h"
#include <stdio.h>
// Pin Definitions
#define CAPTEUR_ZONE_1_CHANNEL ADC_CHANNEL_0
#define CAPTEUR_ZONE_2_CHANNEL ADC_CHANNEL_2
#define VANNE_1_PIN GPIO_PIN_0
#define VANNE_2_PIN GPIO_PIN_1
#define BOUTON_URGENCE_PIN GPIO_PIN_6
#define LED_URGENCE_PIN GPIO_PIN_10
#define POTENTIOMETRE_CHANNEL ADC_CHANNEL_8
// Shared Resources
QueueHandle_t queueVannes;
SemaphoreHandle_t semaphoreUrgence;
SemaphoreHandle_t mutexSeuilHumidite;
// Global Variables
volatile int seuilHumidite = 50; // Default humidity threshold
ADC_HandleTypeDef hadc1; // ADC1 handle
// Function Prototypes
void MX_GPIO_Init(void);
void MX_ADC1_Init(void);
void UART_Send(const char *message);
void SurveillanceHumidite_Task(void *pvParameters);
void ActivationVannes_Task(void *pvParameters);
void GestionUrgence_Task(void *pvParameters);
void AjustementSeuil_Task(void *pvParameters);
uint32_t Read_ADC_Value(uint32_t channel);
// UART Send Function
void UART_Send(const char *message) {
printf("%s", message);
}
// GPIO Initialization
void MX_GPIO_Init(void) {
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
// Configure GPIOs for valves
GPIO_InitStruct.Pin = VANNE_1_PIN | VANNE_2_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Configure GPIO for emergency button
GPIO_InitStruct.Pin = BOUTON_URGENCE_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Configure GPIO for emergency LED
GPIO_InitStruct.Pin = LED_URGENCE_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
// ADC Initialization
void MX_ADC1_Init(void) {
__HAL_RCC_ADC_CLK_ENABLE();
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK) {
UART_Send("ADC initialization failed!\n");
while (1);
}
}
// Read ADC Value
uint32_t Read_ADC_Value(uint32_t channel) {
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = channel;
sConfig.Rank = ADC_REGULAR_RANK_1;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
UART_Send("ADC channel configuration failed!\n");
return 0;
}
HAL_ADC_Start(&hadc1);
if (HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY) != HAL_OK) {
UART_Send("ADC polling failed!\n");
return 0;
}
uint32_t value = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
return value;
}
// Humidity Monitoring Task
void SurveillanceHumidite_Task(void *pvParameters) {
while (1) {
uint32_t humiditeZone1 = Read_ADC_Value(CAPTEUR_ZONE_1_CHANNEL); // Zone 1
uint32_t humiditeZone2 = Read_ADC_Value(CAPTEUR_ZONE_2_CHANNEL); // Zone 2
xSemaphoreTake(mutexSeuilHumidite, portMAX_DELAY);
int seuil = seuilHumidite;
xSemaphoreGive(mutexSeuilHumidite);
if (humiditeZone1 < seuil) {
int zone = 1;
if (xQueueSend(queueVannes, &zone, portMAX_DELAY) != pdPASS) {
UART_Send("Queue full, unable to send zone");
}
}
if (humiditeZone2 < seuil) {
int zone = 2;
xQueueSend(queueVannes, &zone, portMAX_DELAY);
}
UART_Send("SurveillanceHumidite_Task executed\n");
vTaskDelay(pdMS_TO_TICKS(5000)); // 5 seconds delay
}
}
// Valve Activation Task
void ActivationVannes_Task(void *pvParameters) {
while (1) {
int zone;
if (xQueueReceive(queueVannes, &zone, portMAX_DELAY)) {
uint16_t ledPin = (zone == 1) ? VANNE_1_PIN : VANNE_2_PIN;
HAL_GPIO_WritePin(GPIOA, ledPin, GPIO_PIN_SET);
UART_Send("Valve activated for zone\n");
vTaskDelay(pdMS_TO_TICKS(10000)); // Keep valve open for 10s
HAL_GPIO_WritePin(GPIOA, ledPin, GPIO_PIN_RESET);
}
}
}
// Emergency Management Task
void GestionUrgence_Task(void *pvParameters) {
while (1) {
if (HAL_GPIO_ReadPin(GPIOA, BOUTON_URGENCE_PIN) == GPIO_PIN_RESET) {
xSemaphoreGive(semaphoreUrgence);
}
if (xSemaphoreTake(semaphoreUrgence, 0)) {
HAL_GPIO_WritePin(GPIOA, LED_URGENCE_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, VANNE_1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, VANNE_2_PIN, GPIO_PIN_RESET);
UART_Send("Emergency stop activated!\n");
}
vTaskDelay(pdMS_TO_TICKS(100));
}
}
// Threshold Adjustment Task
void AjustementSeuil_Task(void *pvParameters) {
while (1) {
uint32_t nouvelleValeur = Read_ADC_Value(POTENTIOMETRE_CHANNEL) / 10; // Map to 0-100
static uint32_t previousValue = 0;
if (nouvelleValeur == previousValue) {
vTaskDelay(pdMS_TO_TICKS(2000)); // Skip processing if unchanged
continue;
}
previousValue = nouvelleValeur;
xSemaphoreTake(mutexSeuilHumidite, portMAX_DELAY);
seuilHumidite = nouvelleValeur;
xSemaphoreGive(mutexSeuilHumidite);
UART_Send("Threshold adjusted\n");
vTaskDelay(pdMS_TO_TICKS(2000)); // 2 seconds delay
}
}
// Main Function
int main(void) {
HAL_Init();
MX_GPIO_Init();
MX_ADC1_Init();
// Initialize shared resources
queueVannes = xQueueCreate(5, sizeof(int));
semaphoreUrgence = xSemaphoreCreateBinary();
mutexSeuilHumidite = xSemaphoreCreateMutex();
// Create tasks
xTaskCreate(SurveillanceHumidite_Task, "SurveillanceHumidite", 256, NULL, 2, NULL);
xTaskCreate(ActivationVannes_Task, "ActivationVannes", 256, NULL, 2, NULL);
xTaskCreate(GestionUrgence_Task, "GestionUrgence", 256, NULL, 3, NULL);
xTaskCreate(AjustementSeuil_Task, "AjustementSeuil", 256, NULL, 1, NULL);
// Start the scheduler
vTaskStartScheduler();
// Infinite loop (should never reach here)
while (1) {
}
}
void loop(){}