#include <stm32c0xx_hal.h> // Inclusion de la bibliothèque HAL pour STM32
#include <task.h> // Inclusion pour la gestion des tâches FreeRTOS
#include <FreeRTOS.h> // Inclusion de la bibliothèque FreeRTOS pour les fonctionnalités RTOS
#include <stdio.h> // Inclusion pour les fonctions d'entrée/sortie standard
#include <semphr.h> // Inclusion pour la gestion des sémaphores FreeRTOS
#include <queue.h> // Inclusion pour la gestion des queues FreeRTOS
// Définition des pins GPIO
define HUMIDITY_SENSOR1_PIN ADC_CHANNEL_0 // Pin pour le capteur d'humidité 1 (connecté sur le canal ADC 0, entrée analogique)
#define HUMIDITY_SENSOR2_PIN ADC_CHANNEL_1 // Pin pour le capteur d'humidité 2 (connecté sur le canal ADC 1, entrée analogique)
#define VALVE1_PIN GPIO_PIN_5 // Pin pour la vanne 1 simulée par une LED sur PA5
#define VALVE2_PIN GPIO_PIN_6 // Pin pour la vanne 2 simulée par une LED sur PA6
#define semaphoreUrgence_PIN GPIO_PIN_4 // Pin pour le bouton d'arrêt d'urgence sur PA4
#define POTENTIOMETER_PIN GPIO_PIN_3 // Pin pour le potentiomètre sur PB3
#define EMERGENCY_LED_PIN GPIO_PIN_7 // Pin pour la LED rouge signalant un arrêt d'urgence
// Déclarations globales
QueueHandle_t queueArrosage;
SemaphoreHandle_t semaphoreUrgence; //sémaphore binaire pour gérer les urgences
SemaphoreHandle_t mutexSeuil; // mutex pour protéger l'accés au seuil d'humidité
volatile int seuilHumidite = 50; // Seuil d'humidité par défaut 50%
// Prototypes des tâches
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(); // Initialisation de la bibliothèque HAL
SystemClock_Config(); // Configuration de l'horloge du système
GPIO_Init(); // Initialisation des GPIO
// Création des mécanismes FreeRTOS
queueArrosage = xQueueCreate(5, sizeof(int)); // Queue pour 5 messages
semaphoreUrgence = xSemaphoreCreateBinary();
mutexSeuil = xSemaphoreCreateMutex();
//vérification des mécanismes
if (queueArrosage == NULL || semaphoreUrgence == NULL || mutexSeuil == NULL) {
pinMode(A2, INPUT); // Potentiomètre pour ajuster le seuil
LogEvent("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);
xTaskCreate(TacheControleVannes, "Vannes", 128, NULL, 1, NULL);
xTaskCreate(TacheGestionUrgence, "Urgence", 128, NULL, 2, NULL);
xTaskCreate(TacheAjustementSeuil, "Seuil", 128, NULL, 1, NULL);
xTaskCreate(TacheJournalisation, "Log", 128, NULL, 1, NULL);
// Démarrage du gestionnaire de tâches FreeRTOS
vTaskStartScheduler();
}
// 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
GPIO_InitStruct.Pin = HUMIDITY_SENSOR1_PIN | HUMIDITY_SENSOR2_PIN | semaphoreUrgence_PIN; // 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 (ni pull-up, ni pull-down)
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Appliquer la configuration sur le port GPIOA
// Configurer les LEDs (vannes + LED d'urgence) en sortie
GPIO_InitStruct.Pin = VALVE1_PIN | VALVE2_PIN | EMERGENCY_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); // Appliquer la configuration sur le port GPIOB
}
void loop() {
// Pas besoin de code ici, tout est géré par FreeRTOS
}
// Implémentation des tâches
// Tâche de lecture des capteurs d'humidité
void TacheCapteurHumidite(void *pvParameters) {
for (;;) {
int humidite1 = analogRead(A0); // Lire capteur 1
int humidite2 = analogRead(A1); // Lire capteur 2
xSemaphoreTake(mutexSeuil, portMAX_DELAY);
int seuilActuel = seuilHumidite; //lire le seuil actuel
xSemaphoreGive(mutexSeuil);
// Vérifier si les capteurs détectent une humidité insuffisante
if (humidite1 < seuilActuel) xQueueSend(queueArrosage, &humidite1, portMAX_DELAY);
if (humidite2 < seuilActuel) xQueueSend(queueArrosage, &humidite2, portMAX_DELAY);
vTaskDelay(pdMS_TO_TICKS(5000)); // Pause de 5 secondes
}
}
// Tâche de contrôle des vannes
void TacheControleVannes(void *pvParameters) {
int humidite;
for (;;) {
if (xQueueReceive(queueArrosage, &humidite, portMAX_DELAY) == pdTRUE) {
Serial.print("Contrôle des vannes, humidité détectée : ");
Serial.println(humidite);
digitalWrite(9, HIGH); // Active vanne 1
digitalWrite(10, HIGH); // Active vanne 2
vTaskDelay(pdMS_TO_TICKS(1000)); // Maintient les vannes ouvertes 1 seconde
digitalWrite(9, LOW);
digitalWrite(10, LOW);
}
}
}
// Tâche de gestion de l'arrêt d'urgence
void TacheGestionUrgence(void *pvParameters) {
for (;;) {
if (digitalRead(2) == LOW) { // Bouton poussoir appuyé
xSemaphoreGive(semaphoreUrgence);
}
if (xSemaphoreTake(semaphoreUrgence, 0) == pdTRUE) {
Serial.println("Urgence détectée !");
digitalWrite(11, HIGH); // Allume la LED d'urgence
vTaskDelay(pdMS_TO_TICKS(5000)); // Gère l'urgence pendant 5 secondes
digitalWrite(11, LOW); // Éteint la LED d'urgence
}
vTaskDelay(pdMS_TO_TICKS(100)); // Vérification périodique
}
}
void TacheAjustementSeuil(void *pvParameters) {
for (;;) {
int potValue = analogRead(A2);
int newSeuil = map(potValue, 0, 1023, 10, 90); // Mappe la plage [0-1023] à [10-90]
xSemaphoreTake(mutexSeuil, portMAX_DELAY);
seuilHumidite = newSeuil;
xSemaphoreGive(mutexSeuil);
Serial.print("Seuil ajusté à : ");
Serial.println(newSeuil);
vTaskDelay(pdMS_TO_TICKS(1000)); // Mise à jour chaque seconde
}
}
void TacheJournalisation(void *pvParameters) {
for (;;) {
xSemaphoreTake(mutexSeuil, portMAX_DELAY);
int seuilActuel = seuilHumidite; // Lire le seuil actuel
xSemaphoreGive(mutexSeuil);
Serial.print("Seuil d'humidité actuel : ");
Serial.println(seuilActuel);
vTaskDelay(pdMS_TO_TICKS(5000)); // Journalisation toutes les 5 secondes
}
}