#include <stm32c0xx_hal.h>
#include <FreeRTOS.h>
#include <semphr.h>
#include <task.h>
#include <queue.h>
#include <stdio.h>
volatile uint8_t urgenceActive = 0; // 0 = normal, 1 = urgence
QueueHandle_t QueueHumidite;
SemaphoreHandle_t SemUrgence; // Sémaphore pour les urgences
SemaphoreHandle_t Mutex; // Mutex pour protéger l'accès au seuil d'humidité
uint8_t SeuilHumidite = 50; // Seuil d'humidité à 50%
void GPIO_Init(void); // Initialisation des GPIO
void ValeursHumidite(void *pvParameters); // Tâche pour lire les capteurs d'humidité
void ActivationVannes(void *pvParameters); // Tâche pour contrôler les vannes
void ArretUrgence(void *pvParameters); // Tâche pour surveiller le bouton d'urgence
void AjustSeuil(void *pvParameters); // Tâche ajuster le seuil d'humidité
void Journalisation(const char* event); // Fonction pour journaliser les événements
// Fonction principale
int main(void) {
HAL_Init();
GPIO_Init();
SemUrgence = xSemaphoreCreateBinary(); // Sémaphore pour la gestion des événements d'urgence
QueueHumidite = xQueueCreate(5, sizeof(uint8_t)); // Queue pour envoyer les données d'humidité entre les tâches
Mutex = xSemaphoreCreateMutex(); // Mutex pour protéger l'accès à la variable du seuil d'humidité
if (Mutex == NULL || QueueHumidite == NULL || SemUrgence == NULL) {
Journalisation("Erreur lors de la creation des ressources");
while (1); // Arrêt en cas d'erreur critique
}
// Création des tâches
xTaskCreate(ValeursHumidite, "Capteurs", 128, NULL, 1, NULL); // Tâche pour lire les capteurs d'humidité
xTaskCreate(ActivationVannes, "Vannes", 128, NULL, 2, NULL); // Tâche pour contrôler les vannes
xTaskCreate(ArretUrgence, "Urgence", 128, NULL, 3, NULL); // Tâche pour surveiller le bouton d'urgence
xTaskCreate(AjustSeuil, "Seuil", 128, NULL, 1, NULL); // Tâche pour ajuster le seuil d'humidité via le potentiomètre
// Démarrage du FreeRTOS
vTaskStartScheduler();
}
void GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = ADC_CHANNEL_0 | ADC_CHANNEL_1 | GPIO_PIN_4;
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 = GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7; // Pins des LEDs
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Configuration de potentiomètre
GPIO_InitStruct.Pin = GPIO_PIN_3; // Pin du potentiomètre
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void ValeursHumidite(void *pvParameters) {
uint8_t humidite1,humidite2;
while (1) {
humidite1 = 120 ;
humidite2 = 120 ;// Lire les capteurs d'humidité (exemple de valeurs simulées)
// Lire le seuil actuel avec protection par mutex
xSemaphoreTake(Mutex, portMAX_DELAY);
uint8_t seuil = SeuilHumidite;
xSemaphoreGive(Mutex);
// Vérifier et envoyer dans la queue si humidité est inférieure au seuil
if (!urgenceActive && humidite1 < seuil) {
uint8_t zone = 1;
xQueueSend(QueueHumidite, &zone, portMAX_DELAY);
}
if (!urgenceActive && humidite2 < seuil) {
uint8_t zone = 2;
xQueueSend(QueueHumidite, &zone, portMAX_DELAY);
}
// Attente avant la prochaine mesure
vTaskDelay(pdMS_TO_TICKS(15000));
}
}
// Tâche de contrôle des vannes
void ActivationVannes(void *pvParameters) {
uint8_t zone;
while (1) {
// Attendre de recevoir une donnée de la queue
if (xQueueReceive(QueueHumidite, &zone, portMAX_DELAY) == pdTRUE) {
if (zone == 1 && urgenceActive == 0) {
// Si la zone 1 est concernée, activer la vanne 1
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5
, GPIO_PIN_SET);
Journalisation("Vanne 1 activée.\n");
vTaskDelay(pdMS_TO_TICKS(10000)); // Maintenir la vanne ouverte pendant 10 secondes
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5
, GPIO_PIN_RESET); // Désactiver la vanne 1
Journalisation("Vanne 1 désactivée.\n");
}
if (zone == 2 && urgenceActive == 0) {
// Si la zone 2 est concernée, activer la vanne 2
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6
, GPIO_PIN_SET);
Journalisation("Vanne 2 activée.\n");
vTaskDelay(pdMS_TO_TICKS(10000)); // Maintenir la vanne ouverte pendant 10 secondes
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6
, GPIO_PIN_RESET);
Journalisation("Vanne 2 désactivée.\n"); // Désactiver la vanne 2
}
}
}
}
// Tâche de gestion de l'arrêt d'urgence
void ArretUrgence(void *pvParameters) {
uint8_t previousButtonState = 0;
while (1) {
uint8_t currentButtonState = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4);
// Detect rising edge (button pressed)
if (currentButtonState == GPIO_PIN_SET && previousButtonState == GPIO_PIN_RESET) {
urgenceActive = !urgenceActive; // Toggle state
if (urgenceActive) {
// Activer l'urgence
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5 | GPIO_PIN_6, GPIO_PIN_RESET); // Fermer les vannes
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET); // LED ON
Journalisation("Urgence détectée !\n");
xSemaphoreGive(SemUrgence);
} else {
// Désactiver l'urgence
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET); // LED OFF
Journalisation("Urgence désactivée.\n");
}
}
previousButtonState = currentButtonState;
vTaskDelay(pdMS_TO_TICKS(20)); // Anti-rebond
}
}
void adc_init(void) {
RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
RCC->APBENR2 |= RCC_APBENR2_ADCEN;
GPIOA->MODER |= (3 << (0 * 2)); // PA0 analog
if ((ADC1->CR & ADC_CR_ADEN) != 0) {
ADC1->CR &= ~ADC_CR_ADEN;
}
ADC1->CR |= ADC_CR_ADCAL;
while (ADC1->CR & ADC_CR_ADCAL);
ADC1->CR |= ADC_CR_ADEN;
while (!(ADC1->ISR & ADC_ISR_ADRDY));
}
uint16_t read_adc(void) {
ADC1->CHSELR = ADC_CHSELR_CHSEL0; // PA0 = Channel 0
ADC1->CR |= ADC_CR_ADSTART;
while (!(ADC1->ISR & ADC_ISR_EOC));
return ADC1->DR;
}
// Tâche pour ajuster le seuil d'humidité via le potentiomètre
void AjustSeuil(void *pvParameters) {
while (1) {
uint8_t potentiometerValue = read_adc();
// Accéder et mettre à jour le seuil d'humidité en utilisant un mutex
if (urgenceActive == 0 &&xSemaphoreTake(Mutex, portMAX_DELAY) == pdTRUE ) {
SeuilHumidite = potentiometerValue; // Mise à jour du seuil
xSemaphoreGive(Mutex); // Libération du mutex
Journalisation("Seuil d'humidité mis à jour: ");
printf("%u\n", potentiometerValue);
}
vTaskDelay(pdMS_TO_TICKS(5000)); // Mise à jour toutes les 5 secondes
}
}
// Fonction pour journaliser les événements
void Journalisation(const char* event) {
printf("%s\r", event); // Imprimer les événements pour le suivi
}
void loop() {
//vide
}