#include <stm32c0xx_hal.h>
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include <semphr.h>
#include <stdio.h>
// Définition des broches matérielles
#define CAPTEUR_ZONE1_PIN GPIO_PIN_0 // Capteur Zone 1 sur PA0
#define CAPTEUR_ZONE2_PIN GPIO_PIN_1 // Capteur Zone 2 sur PA1
#define LED_VANNE1_PIN GPIO_PIN_5 // LED Vanne Zone 1 sur PA5
#define LED_VANNE2_PIN GPIO_PIN_6 // LED Vanne Zone 2 sur PA6
#define BOUTON_URGENCE_PIN GPIO_PIN_4 // Bouton d'arrêt d'urgence sur PB4
#define POTENTIOMETRE_PIN GPIO_PIN_3 // Potentiomètre sur PA3
#define LED_URGENCE_PIN GPIO_PIN_7 // LED d'urgence sur PA7
// Variables globales
QueueHandle_t fileCapteurs;
SemaphoreHandle_t semaphoreUrgence;
SemaphoreHandle_t verrouSeuil;
uint8_t seuilHumidite = 50; // Seuil par défaut
// Prototypes des fonctions
void ConfigurerHorloge(void);
void InitialiserGPIO(void);
void TacheSurveillanceHumidite(void *params);
void TacheControleVannes(void *params);
void TacheGestionUrgence(void *params);
void TacheAjustementSeuil(void *params);
void LoggerEvenement(const char *evenement);
// Fonction principale
void setup() {
HAL_Init();
ConfigurerHorloge();
InitialiserGPIO();
// Création des objets FreeRTOS
fileCapteurs = xQueueCreate(10, sizeof(uint8_t));
semaphoreUrgence = xSemaphoreCreateBinary();
verrouSeuil = xSemaphoreCreateMutex();
if (fileCapteurs == NULL || semaphoreUrgence == NULL || verrouSeuil == NULL) {
LoggerEvenement("Erreur : Échec de la création des ressources FreeRTOS !");
while (1);
}
// Création des tâches
xTaskCreate(TacheSurveillanceHumidite, "SurveillanceHumidite", 128, NULL, 1, NULL);
xTaskCreate(TacheControleVannes, "ControleVannes", 128, NULL, 2, NULL);
xTaskCreate(TacheGestionUrgence, "GestionUrgence", 128, NULL, 3, NULL);
xTaskCreate(TacheAjustementSeuil, "AjustementSeuil", 128, NULL, 1, NULL);
// Démarrage du scheduler
vTaskStartScheduler();
// Si le scheduler échoue
while (1) {}
}
void InitialiserGPIO(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
// Configurer les broches des capteurs et du bouton
GPIO_InitStruct.Pin = CAPTEUR_ZONE1_PIN | CAPTEUR_ZONE2_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = BOUTON_URGENCE_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// Configurer les LEDs en sortie
GPIO_InitStruct.Pin = LED_VANNE1_PIN | LED_VANNE2_PIN | LED_URGENCE_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Configurer le potentiomètre
GPIO_InitStruct.Pin = POTENTIOMETRE_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
// Tâche : Surveillance de l'humidité
void TacheSurveillanceHumidite(void *params) {
while (1) {
if (uxSemaphoreGetCount(semaphoreUrgence) > 0) {
vTaskDelay(pdMS_TO_TICKS(100)); // Suspendre en état d'urgence
continue;
}
uint8_t humiditeZone1 = HAL_GPIO_ReadPin(GPIOA, CAPTEUR_ZONE1_PIN) ? 45 : 55;
uint8_t humiditeZone2 = HAL_GPIO_ReadPin(GPIOA, CAPTEUR_ZONE2_PIN) ? 40 : 60;
xSemaphoreTake(verrouSeuil, portMAX_DELAY);
uint8_t seuilActuel = seuilHumidite;
xSemaphoreGive(verrouSeuil);
if (humiditeZone1 < seuilActuel) {
uint8_t zone = 1;
xQueueSend(fileCapteurs, &zone, portMAX_DELAY);
}
if (humiditeZone2 < seuilActuel) {
uint8_t zone = 2;
xQueueSend(fileCapteurs, &zone, portMAX_DELAY);
}
vTaskDelay(pdMS_TO_TICKS(5000));
}
}
// Tâche : Contrôle des vannes
void TacheControleVannes(void *params) {
uint8_t zone;
while (1) {
if (uxSemaphoreGetCount(semaphoreUrgence) > 0) {
HAL_GPIO_WritePin(GPIOA, LED_VANNE1_PIN | LED_VANNE2_PIN, GPIO_PIN_RESET); // Fermer toutes les vannes
vTaskDelay(pdMS_TO_TICKS(100)); // Suspendre en état d'urgence
continue;
}
if (xQueueReceive(fileCapteurs, &zone, portMAX_DELAY) == pdTRUE) {
if (zone == 1) {
HAL_GPIO_WritePin(GPIOA, LED_VANNE1_PIN, GPIO_PIN_SET);
LoggerEvenement("Vanne Zone 1 activée");
vTaskDelay(pdMS_TO_TICKS(10000));
HAL_GPIO_WritePin(GPIOA, LED_VANNE1_PIN, GPIO_PIN_RESET);
LoggerEvenement("Vanne Zone 1 désactivée");
} else if (zone == 2) {
HAL_GPIO_WritePin(GPIOA, LED_VANNE2_PIN, GPIO_PIN_SET);
LoggerEvenement("Vanne Zone 2 activée");
vTaskDelay(pdMS_TO_TICKS(10000));
HAL_GPIO_WritePin(GPIOA, LED_VANNE2_PIN, GPIO_PIN_RESET);
LoggerEvenement("Vanne Zone 2 désactivée");
}
}
}
}
// Tâche : Gestion de l'arrêt d'urgence
void TacheGestionUrgence(void *params) {
while (1) {
if (HAL_GPIO_ReadPin(GPIOB, BOUTON_URGENCE_PIN) == GPIO_PIN_SET) {
HAL_GPIO_WritePin(GPIOA, LED_VANNE1_PIN | LED_VANNE2_PIN, GPIO_PIN_RESET); // Fermer toutes les vannes
HAL_GPIO_WritePin(GPIOA, LED_URGENCE_PIN, GPIO_PIN_SET); // Allumer LED d'urgence
LoggerEvenement("Arrêt d'urgence déclenché !");
xSemaphoreGive(semaphoreUrgence); // Signaler l'événement critique
while (HAL_GPIO_ReadPin(GPIOB, BOUTON_URGENCE_PIN) == GPIO_PIN_SET) {
vTaskDelay(pdMS_TO_TICKS(50)); // Maintenir l'état d'urgence
}
HAL_GPIO_WritePin(GPIOA, LED_URGENCE_PIN, GPIO_PIN_RESET); // Éteindre LED d'urgence
xSemaphoreTake(semaphoreUrgence, 0); // Réinitialiser l'état d'urgence
}
vTaskDelay(pdMS_TO_TICKS(50)); // Anti-rebond
}
}
// Tâche : Ajustement du seuil d'humidité
void TacheAjustementSeuil(void *params) {
while (1) {
if (uxSemaphoreGetCount(semaphoreUrgence) > 0) {
vTaskDelay(pdMS_TO_TICKS(100)); // Suspendre en état d'urgence
continue;
}
uint8_t nouveauSeuil = HAL_GPIO_ReadPin(GPIOA, POTENTIOMETRE_PIN) ? 60 : 40; // Simuler lecture
if (xSemaphoreTake(verrouSeuil, portMAX_DELAY) == pdTRUE) {
seuilHumidite = nouveauSeuil;
xSemaphoreGive(verrouSeuil);
LoggerEvenement("Seuil d'humidité mis à jour");
}
vTaskDelay(pdMS_TO_TICKS(5000));
}
}
// Fonction : Journalisation des événements
void LoggerEvenement(const char *evenement) {
printf("%s\n", evenement);
}
void ConfigurerHorloge(void) {
// Simulation de la configuration de l'horloge (vide pour ce projet)
}
void loop() {
// Vide : FreeRTOS gère les tâches.
}