#include <stm32c0xx_hal.h> // Bibliothèque STM32 HAL
#include <FreeRTOS.h> // Bibliothèque FreeRTOS
#include <semphr.h> // Bibliothèque pour les sémaphores
#include <task.h> // Bibliothèque pour la gestion des tâches
#include <queue.h> // Bibliothèque pour les files
#include <stdio.h> // Pour la journalisation (printf)
// Définition des pins GPIO
#define VANNE_PIN_1 GPIO_PIN_5 // Pin pour la vanne 1
#define VANNE_PIN_2 GPIO_PIN_6 // Pin pour la vanne 2
#define URGENCE_BUTTON GPIO_PIN_4 // Pin pour le bouton d'arrêt d'urgence
#define POTENTIOMETER_PIN GPIO_PIN_3 // Pin pour le potentiomètre
#define HUMIDITY_PIN_1 ADC_CHANNEL_0 // Pin pour le capteur d'humidité 1
#define HUMIDITY_PIN_2 ADC_CHANNEL_1 // Pin pour le capteur d'humidité 2
#define URGENCE_LED_PIN GPIO_PIN_7 // Pin pour la LED d'urgence
// Variables globales
QueueHandle_t humidityQueue; // Queue pour la communication
SemaphoreHandle_t semaphoreUrgence; // Sémaphore pour gérer les événements critiques
SemaphoreHandle_t mutexSeuil; // Mutex pour protéger l'accès au seuil d'humidité
uint8_t humidityThreshold = 50; // Seuil d'humidité à 50%
// Prototypes des fonctions
void SystemClock_Config(void); // Configuration de l'horloge du système
void GPIO_Init(void); // Initialisation des GPIO
void TacheCapteurHumidite(void *pvParameters); // Tâche pour lire les capteurs d'humidité
void TacheControleVannes(void *pvParameters); // Tâche pour contrôler les vannes
void TacheGestionUrgence(void *pvParameters); // Tâche pour surveiller le bouton d'urgence
void TacheAjustementSeuil(void *pvParameters); // Tâche pour lire le potentiomètre et ajuster le seuil
void TacheJournalisation(const char* event); // Fonction pour journaliser les événements
// Fonction principale
int main(void) {
HAL_Init();
SystemClock_Config();
GPIO_Init(); // Initialiser les GPIO pour la communication avec les périphériques
// Création des FreeFTOS
semaphoreUrgence = xSemaphoreCreateBinary(); // Sémaphore pour la gestion des événements d'urgence
humidityQueue = xQueueCreate(5, sizeof(uint8_t)); // Queue pour envoyer les données d'humidité entre les tâches
mutexSeuil = xSemaphoreCreateMutex(); // Mutex pour protéger l'accès à la variable du seuil d'humidité
// Vérification des mécanismes
if (mutexSeuil == NULL || humidityQueue == NULL || semaphoreUrgence == NULL) {
// Si l'une des ressources n'a pas pu être créée, journaliser une erreur et arrêter l'exécution
TacheJournalisation("Erreur : Échec de la création des mécanismes FreeRTOS");
while (1); // Arrêt en cas d'erreur critique
}
// Création des tâches
xTaskCreate(TacheCapteurHumidite, "Capteurs", 128, NULL, 1, NULL); // Tâche pour lire les capteurs d'humidité
xTaskCreate(TacheControleVannes, "Vannes", 128, NULL, 2, NULL); // Tâche pour contrôler les vannes
xTaskCreate(TacheGestionUrgence, "Urgence", 128, NULL, 3, NULL); // Tâche pour surveiller le bouton d'urgence
xTaskCreate(TacheAjustementSeuil, "Seuil", 128, NULL, 1, NULL); // Tâche pour ajuster le seuil d'humidité via le potentiomètre
// Démarrage du scheduler FreeRTOS
vTaskStartScheduler();
// Si le scheduler échoue
while (1) {}
}
// Fonction d'initialisation des GPIO
void GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0}; // Structure pour configurer les GPIO
__HAL_RCC_GPIOA_CLK_ENABLE(); // Activer l'horloge pour le port GPIOA
__HAL_RCC_GPIOB_CLK_ENABLE(); // Activer l'horloge pour le port GPIOB
// Configurer les pins des capteurs d'humidité et du bouton d'urgence en entrée
GPIO_InitStruct.Pin = HUMIDITY_PIN_1 | HUMIDITY_PIN_2 | URGENCE_BUTTON; // Pins configurés
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // Mode d'entrée pour lire les capteurs et le bouton
GPIO_InitStruct.Pull = GPIO_NOPULL; // Pas de résistance interne
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Initialiser les GPIOA avec cette configuration
// Configurer les LEDs (vannes + LED d'urgence) en sortie
GPIO_InitStruct.Pin = VANNE_PIN_1 | VANNE_PIN_2 | URGENCE_LED_PIN; // Pins des LEDs
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // Mode sortie en push-pull
GPIO_InitStruct.Pull = GPIO_NOPULL; // Pas de résistance interne
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Appliquer la configuration sur le port GPIOA
// Configurer le potentiomètre
GPIO_InitStruct.Pin = POTENTIOMETER_PIN; // Pin du potentiomètre
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // Mode d'entrée pour lire la valeur
GPIO_InitStruct.Pull = GPIO_NOPULL; // Pas de résistance interne
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // Initialiser les GPIOB avec cette configuration
}
// Implémentation des tâches
// Tâche de lecture des capteurs d'humidité
void TacheCapteurHumidite(void *pvParameters) {
uint8_t humidity1, humidity2;
while (1) {
// Lire les valeurs des capteurs d'humidité
humidity1 = HAL_GPIO_ReadPin(GPIOA, HUMIDITY_PIN_1) ? 45 : 55;
humidity2 = HAL_GPIO_ReadPin(GPIOA, HUMIDITY_PIN_2) ? 40 : 60;
// Lire et protéger l'accès au seuil d'humidité avec un mutex
xSemaphoreTake(mutexSeuil, portMAX_DELAY); // Prendre le mutex pour lire la variable seuil
uint8_t currentThreshold = humidityThreshold; // Prendre le mutex pour lire la variable seuil
xSemaphoreGive(mutexSeuil); // Libérer le mutex une fois la lecture effectuée
// Vérifier si l'humidité est inférieure au seuil et envoyer les informations via la queue
if (humidity1 < currentThreshold) {
uint8_t zone = 1; // Zone 1
xQueueSend(humidityQueue, &zone, portMAX_DELAY); // Envoyer la zone dans la queue
}
if (humidity2 < currentThreshold) {
uint8_t zone = 2; // Zone 2
xQueueSend(humidityQueue, &zone, portMAX_DELAY); // Envoyer la zone dans la queue
}
vTaskDelay(pdMS_TO_TICKS(2000)); // Attente de 2secondes avant de lire à nouveau
}
}
// Tâche de contrôle des vannes
void TacheControleVannes(void *pvParameters) {
uint8_t zone;
while (1) {
// Attendre de recevoir une donnée de la queue
if (xQueueReceive(humidityQueue, &zone, portMAX_DELAY) == pdTRUE) {
if (zone == 1) {
// Si la zone 1 est concernée, activer la vanne 1
HAL_GPIO_WritePin(GPIOA, VANNE_PIN_1, GPIO_PIN_SET);
TacheJournalisation("Vanne 1 activée.");
vTaskDelay(pdMS_TO_TICKS(10000)); // Maintenir la vanne ouverte pendant 10 secondes
HAL_GPIO_WritePin(GPIOA, VANNE_PIN_1, GPIO_PIN_RESET); // Désactiver la vanne 1
TacheJournalisation("Vanne 1 désactivée.");
} else if (zone == 2) {
// Si la zone 2 est concernée, activer la vanne 2
HAL_GPIO_WritePin(GPIOA, VANNE_PIN_2, GPIO_PIN_SET);
TacheJournalisation("Vanne 2 activée.");
vTaskDelay(pdMS_TO_TICKS(10000)); // Maintenir la vanne ouverte pendant 10 secondes
HAL_GPIO_WritePin(GPIOA, VANNE_PIN_2, GPIO_PIN_RESET);
TacheJournalisation("Vanne 2 désactivée."); // Désactiver la vanne 2
}
}
}
}
// Tâche de gestion de l'arrêt d'urgence
void TacheGestionUrgence(void *pvParameters) {
while (1) {
if (HAL_GPIO_ReadPin(GPIOA, URGENCE_BUTTON) == GPIO_PIN_SET) {
// Si le bouton d'urgence est pressé, fermer toutes les vannes et allumer la LED d'urgence
HAL_GPIO_WritePin(GPIOA, VANNE_PIN_1 | VANNE_PIN_2, GPIO_PIN_RESET); // Fermer les vannes
HAL_GPIO_WritePin(GPIOA, URGENCE_LED_PIN, GPIO_PIN_SET); // Allumer la LED d'urgence
TacheJournalisation("Urgence détectée !");
xSemaphoreGive(semaphoreUrgence); // Libérer le sémaphore d'urgence
}
vTaskDelay(pdMS_TO_TICKS(50)); // Anti-rebond pour éviter les activations multiples
}
}
uint32_t ReadPotentiometerValue() {
HAL_ADC_Start(&hadc1); // Start ADC conversion
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); // Wait for conversion
uint32_t value = HAL_ADC_GetValue(&hadc1); // Get ADC value
HAL_ADC_Stop(&hadc1);
return value;
}
// Tâche pour ajuster le seuil d'humidité via le potentiomètre
void TacheAjustementSeuil(void *pvParameters) {
while (1) {
uint32_t rawValue = ReadPotentiometerValue(); // 0 to 4095
uint8_t potentiometerValue = (uint8_t)((rawValue * 100) / 4095); // Convert to 0-100%
if (xSemaphoreTake(mutexSeuil, portMAX_DELAY) == pdTRUE) {
humidityThreshold = potentiometerValue;
xSemaphoreGive(mutexSeuil);
TacheJournalisation("Seuil d'humidité mis à jour.");
}
vTaskDelay(pdMS_TO_TICKS(5000));
}
}
// Fonction pour journaliser les événements
void TacheJournalisation(const char* event) {
printf("%s\n", event); // Imprimer les événements pour le suivi
}
// Configuration du système (Simulation)
void SystemClock_Config(void) {
// Aucun code de configuration réel ici
}
void loop() {
//vide
}