#include <stm32c0xx_hal.h>
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include <semphr.h>
#include <stdio.h>
// Définition des pins GPIO
#define HUMIDITY_SENSOR1_PIN GPIO_PIN_0 // Capteur Humidité 1 sur PA0
#define HUMIDITY_SENSOR2_PIN GPIO_PIN_1 // Capteur Humidité 2 sur PA1
#define VALVE1_PIN GPIO_PIN_5 // LED simule vanne 1 sur PA5
#define VALVE2_PIN GPIO_PIN_6 // LED simule vanne 2 sur PA6
#define EMERGENCY_BUTTON_PIN GPIO_PIN_4 // Bouton d'arrêt d'urgence sur PA4
#define POTENTIOMETER_PIN GPIO_PIN_3 // Potentiomètre sur PB3
#define EMERGENCY_LED_PIN GPIO_PIN_7 // LED rouge pour arrêt d'urgence
// Variables globales
SemaphoreHandle_t emergencySemaphore;
SemaphoreHandle_t humidityThresholdMutex;
QueueHandle_t humidityQueue;
uint8_t humidityThreshold = 50; // Seuil d'humidité initial à 50%
// Prototypes des fonctions
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);
// Fonction principale
int main(void) {
HAL_Init();
SystemClock_Config();
GPIO_Init();
// Création des sémaphores et des queues
emergencySemaphore = xSemaphoreCreateBinary();
humidityQueue = xQueueCreate(10, sizeof(uint8_t));
humidityThresholdMutex = xSemaphoreCreateMutex();
if (humidityThresholdMutex == NULL || humidityQueue == NULL || emergencySemaphore == NULL) {
LogEvent("Erreur lors de la création des ressources FreeRTOS !");
while (1);
}
// Création des tâches
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);
// Démarrage du scheduler
vTaskStartScheduler();
// Si le scheduler échoue
while (1) {}
}
// Initialisation des GPIO
void GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
// Configurer les pins des capteurs d'humidité et du bouton
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);
// Configurer les LEDs (vannes + LED d'urgence) en sortie
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);
// Configurer le potentiomètre
GPIO_InitStruct.Pin = POTENTIOMETER_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
// Tâche de lecture des capteurs d'humidité
void ReadHumidityTask(void *pvParameters) {
uint8_t humidity1, humidity2;
while (1) {
// Simulation des valeurs des capteurs d'humidité
humidity1 = (uint8_t)(HAL_GPIO_ReadPin(GPIOA, HUMIDITY_SENSOR1_PIN) ? 45 : 55); // Valeur simulée
humidity2 = (uint8_t)(HAL_GPIO_ReadPin(GPIOA, HUMIDITY_SENSOR2_PIN) ? 40 : 60); // Valeur simulée
// Lire le seuil d'humidité protégé par un mutex
xSemaphoreTake(humidityThresholdMutex, portMAX_DELAY);
uint8_t currentThreshold = humidityThreshold;
xSemaphoreGive(humidityThresholdMutex);
// Envoyer dans la queue si l'humidité est en dessous du seuil
if (humidity1 < currentThreshold) {
uint8_t zone = 1;
xQueueSend(humidityQueue, &zone, portMAX_DELAY);
}
if (humidity2 < currentThreshold) {
uint8_t zone = 2;
xQueueSend(humidityQueue, &zone, portMAX_DELAY);
}
vTaskDelay(pdMS_TO_TICKS(5000)); // Lire toutes les 5 secondes
}
}
// Tâche de contrôle des vannes
void ValveControlTask(void *pvParameters) {
uint8_t zone;
while (1) {
// Attendre une zone dans la queue
if (xQueueReceive(humidityQueue, &zone, portMAX_DELAY) == pdTRUE) {
if (zone == 1) {
HAL_GPIO_WritePin(GPIOA, VALVE1_PIN, GPIO_PIN_SET); // Activer vanne 1
LogEvent("Vanne 1 activée.");
vTaskDelay(pdMS_TO_TICKS(10000)); // 10 secondes
HAL_GPIO_WritePin(GPIOA, VALVE1_PIN, GPIO_PIN_RESET); // Désactiver vanne 1
LogEvent("Vanne 1 désactivée.");
} else if (zone == 2) {
HAL_GPIO_WritePin(GPIOA, VALVE2_PIN, GPIO_PIN_SET); // Activer vanne 2
LogEvent("Vanne 2 activée.");
vTaskDelay(pdMS_TO_TICKS(10000)); // 10 secondes
HAL_GPIO_WritePin(GPIOA, VALVE2_PIN, GPIO_PIN_RESET); // Désactiver vanne 2
LogEvent("Vanne 2 désactivée.");
}
}
}
}
// Tâche de gestion de l'arrêt d'urgence
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); // Fermer toutes les vannes
HAL_GPIO_WritePin(GPIOA, EMERGENCY_LED_PIN, GPIO_PIN_SET); // Activer LED d'urgence
LogEvent("Arrêt d'urgence activé !");
xSemaphoreGive(emergencySemaphore); // Signaler l'événement critique
}
vTaskDelay(pdMS_TO_TICKS(50)); // Anti-rebond
}
}
// Tâche pour lire et ajuster le seuil d'humidité
void PotentiometerTask(void *pvParameters) {
while (1) {
uint8_t potentiometerValue = HAL_GPIO_ReadPin(GPIOB, POTENTIOMETER_PIN) ? 60 : 40; // Valeur simulée
// Mettre à jour le seuil d'humidité
if (xSemaphoreTake(humidityThresholdMutex, portMAX_DELAY) == pdTRUE) {
humidityThreshold = potentiometerValue;
xSemaphoreGive(humidityThresholdMutex);
LogEvent("Seuil d'humidité mis à jour.");
}
vTaskDelay(pdMS_TO_TICKS(5000)); // Mise à jour toutes les 5 secondes
}
}
// Fonction pour journaliser les événements
void LogEvent(const char* event) {
printf("%s\n", event);
}
// Configuration du système (Simulation)
void SystemClock_Config(void) {
// Simuler la configuration du système (vide pour ce projet)
}
void loop(){
};