#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "stm32c0xx_hal.h"
#include <stdio.h>
#include <stdbool.h>
// Definitions
#define HUMIDITY_THRESHOLD_DEFAULT 2000
#define VALVE_OPEN_DURATION 10000
// GPIO Pins
#define LED_ZONE1_PIN GPIO_PIN_5 // PA5
#define LED_ZONE2_PIN GPIO_PIN_6 // PA6
#define EMERGENCY_LED_PIN GPIO_PIN_7 // PA7
#define BUTTON_PIN GPIO_PIN_2 // PA2
// ADC Channels
#define HUMIDITY1_CHANNEL ADC_CHANNEL_0 // PA0
#define HUMIDITY2_CHANNEL ADC_CHANNEL_1 // PA1
#define THRESHOLD_CHANNEL ADC_CHANNEL_4 // PA4
typedef enum {
ZONE1,
ZONE2
} Zone;
QueueHandle_t humidityQueue;
SemaphoreHandle_t emergencySemaphore;
SemaphoreHandle_t thresholdMutex;
ADC_HandleTypeDef hadc1;
uint32_t humidityThreshold = HUMIDITY_THRESHOLD_DEFAULT;
bool emergencyState = false;
// Prototypes
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_ADC_Init(void);
uint32_t Read_ADC(uint32_t channel);
void Log(const char* msg);
// Tasks
void HumiditySensorTask(void *pvParameters) {
TickType_t lastWakeTime = xTaskGetTickCount();
for (;;) {
if (!emergencyState) {
uint32_t hum1 = Read_ADC(HUMIDITY1_CHANNEL);
uint32_t hum2 = Read_ADC(HUMIDITY2_CHANNEL);
xSemaphoreTake(thresholdMutex, portMAX_DELAY);
uint32_t threshold = humidityThreshold;
xSemaphoreGive(thresholdMutex);
if (hum1 < threshold) {
Zone zone = ZONE1;
xQueueSend(humidityQueue, &zone, 0);
}
if (hum2 < threshold) {
Zone zone = ZONE2;
xQueueSend(humidityQueue, &zone, 0);
}
}
vTaskDelayUntil(&lastWakeTime, pdMS_TO_TICKS(5000));
}
}
void ValveControlTask(void *pvParameters) {
Zone zone;
for (;;) {
if (xQueueReceive(humidityQueue, &zone, portMAX_DELAY) && !emergencyState) {
switch (zone) {
case ZONE1:
HAL_GPIO_WritePin(GPIOA, LED_ZONE1_PIN, GPIO_PIN_SET);
Log("Vanne zone 1 ouverte.");
vTaskDelay(pdMS_TO_TICKS(VALVE_OPEN_DURATION));
HAL_GPIO_WritePin(GPIOA, LED_ZONE1_PIN, GPIO_PIN_RESET);
Log("Vanne zone 1 fermee.");
break;
case ZONE2:
HAL_GPIO_WritePin(GPIOA, LED_ZONE2_PIN, GPIO_PIN_SET);
Log("Vanne zone 2 ouverte.");
vTaskDelay(pdMS_TO_TICKS(VALVE_OPEN_DURATION));
HAL_GPIO_WritePin(GPIOA, LED_ZONE2_PIN, GPIO_PIN_RESET);
Log("Vanne zone 2 fermee.");
break;
}
}
}
}
void EmergencyTask(void *pvParameters) {
for (;;) {
if (HAL_GPIO_ReadPin(GPIOA, BUTTON_PIN) == GPIO_PIN_RESET) { // Bouton pressé
emergencyState = true;
HAL_GPIO_WritePin(GPIOA, LED_ZONE1_PIN | LED_ZONE2_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, EMERGENCY_LED_PIN, GPIO_PIN_SET);
Log("Arrêt d'urgence activé !");
xSemaphoreGive(emergencySemaphore);
vTaskDelay(pdMS_TO_TICKS(1000)); // Anti-rebond
}
vTaskDelay(pdMS_TO_TICKS(200));
}
}
void ThresholdUpdateTask(void *pvParameters) {
TickType_t lastWakeTime = xTaskGetTickCount();
for (;;) {
uint32_t newThreshold = Read_ADC(THRESHOLD_CHANNEL);
xSemaphoreTake(thresholdMutex, portMAX_DELAY);
humidityThreshold = newThreshold;
xSemaphoreGive(thresholdMutex);
Log("Seuil d'humidité mis à jour.");
vTaskDelayUntil(&lastWakeTime, pdMS_TO_TICKS(3000));
}
}
// ADC Reading Function
uint32_t Read_ADC(uint32_t channel) {
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = channel;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
uint32_t val = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
return val;
}
void Log(const char* msg) {
printf("%s\n", msg);
}
void loop() {
// Fonction vide pour compatibilité
}
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC_Init();
humidityQueue = xQueueCreate(5, sizeof(Zone));
emergencySemaphore = xSemaphoreCreateBinary();
thresholdMutex = xSemaphoreCreateMutex();
xTaskCreate(HumiditySensorTask, "Humidite", 128, NULL, 2, NULL);
xTaskCreate(ValveControlTask, "Vannes", 128, NULL, 2, NULL);
xTaskCreate(EmergencyTask, "Urgence", 128, NULL, 3, NULL);
xTaskCreate(ThresholdUpdateTask, "Seuil", 128, NULL, 1, NULL);
vTaskStartScheduler();
while (1) {}
}
// Clock Configuration (à compléter selon besoin)
void SystemClock_Config(void) {
}
// GPIO Init
void MX_GPIO_Init(void) {
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
// LEDs
GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
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);
// Bouton
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
// ADC Init
void MX_ADC_Init(void) {
__HAL_RCC_ADC_CLK_ENABLE();
hadc1.Instance = ADC1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
HAL_ADC_Init(&hadc1);
}