#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "stm32c0xx_hal.h"
#include <stdio.h>
ADC_HandleTypeDef hadc;
UART_HandleTypeDef huart;
QueueHandle_t sensorQueue;
SemaphoreHandle_t emergencySemaphore;
SemaphoreHandle_t thresholdMutex;
uint16_t humidityThreshold = 2000; // Valeur initiale arbitraire
typedef struct {
int zone;
uint16_t value;
} SensorData;
void sendUART(const char* message) {
HAL_UART_Transmit(&huart, (uint8_t*)message, strlen(message), HAL_MAX_DELAY);
}
uint16_t readADC(uint32_t channel) {
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = channel;
sConfig.Rank = ADC_REGULAR_RANK_1;
HAL_ADC_ConfigChannel(&hadc, &sConfig);
HAL_ADC_Start(&hadc);
HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY);
return HAL_ADC_GetValue(&hadc);
}
// Tâche de lecture des capteurs (PA0, PA1)
void Task_ReadHumidity(void* params) {
SensorData data;
while (1) {
for (int i = 0; i < 2; i++) {
data.zone = i;
data.value = readADC(i == 0 ? ADC_CHANNEL_0 : ADC_CHANNEL_1);
xSemaphoreTake(thresholdMutex, portMAX_DELAY);
uint16_t localThreshold = humidityThreshold;
xSemaphoreGive(thresholdMutex);
if (data.value < localThreshold) {
xQueueSend(sensorQueue, &data, portMAX_DELAY);
}
char msg[64];
sprintf(msg, "Capteur Zone %d: %d\n", i + 1, data.value);
sendUART(msg);
}
vTaskDelay(pdMS_TO_TICKS(5000));
}
}
// Tâche d’arrosage
void Task_WateringControl(void* params) {
SensorData received;
while (1) {
if (xQueueReceive(sensorQueue, &received, portMAX_DELAY) == pdPASS) {
if (xSemaphoreTake(emergencySemaphore, 0) == pdPASS) continue;
int ledPin = received.zone == 0 ? GPIO_PIN_4 : GPIO_PIN_5;
HAL_GPIO_WritePin(GPIOA, ledPin, GPIO_PIN_SET);
char msg[64];
sprintf(msg, "Vanne %d activée\n", received.zone + 1);
sendUART(msg);
vTaskDelay(pdMS_TO_TICKS(10000)); // 10 sec
HAL_GPIO_WritePin(GPIOA, ledPin, GPIO_PIN_RESET);
sprintf(msg, "Vanne %d désactivée\n", received.zone + 1);
sendUART(msg);
}
}
}
// Tâche d’urgence
void Task_Emergency(void* params) {
while (1) {
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_3) == GPIO_PIN_SET) {
sendUART("** Arrêt d'urgence déclenché **\n");
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4 | GPIO_PIN_5, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
xSemaphoreGive(emergencySemaphore);
vTaskDelay(pdMS_TO_TICKS(2000)); // Anti-rebond
}
vTaskDelay(pdMS_TO_TICKS(200));
}
}
// Tâche de mise à jour du seuil
void Task_UpdateThreshold(void* params) {
while (1) {
uint16_t newValue = readADC(ADC_CHANNEL_2);
xSemaphoreTake(thresholdMutex, portMAX_DELAY);
humidityThreshold = newValue;
xSemaphoreGive(thresholdMutex);
char msg[64];
sprintf(msg, "Nouveau seuil humidité : %d\n", newValue);
sendUART(msg);
vTaskDelay(pdMS_TO_TICKS(2000));
}
}
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_ADC_Init(void);
void MX_USART_Init(void);
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC_Init();
MX_USART_Init();
sensorQueue = xQueueCreate(10, sizeof(SensorData));
emergencySemaphore = xSemaphoreCreateBinary();
thresholdMutex = xSemaphoreCreateMutex();
xTaskCreate(Task_ReadHumidity, "ReadHumidity", 128, NULL, 2, NULL);
xTaskCreate(Task_WateringControl, "Watering", 128, NULL, 2, NULL);
xTaskCreate(Task_Emergency, "Emergency", 128, NULL, 3, NULL);
xTaskCreate(Task_UpdateThreshold, "Threshold", 128, NULL, 1, NULL);
vTaskStartScheduler();
while (1) {}
}
// À adapter selon le simulateur Wokwi (ou init CubeMX pour vrai projet)
void MX_GPIO_Init(void) {
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
// LED vanne
GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Bouton
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void MX_ADC_Init(void) {
__HAL_RCC_ADC_CLK_ENABLE();
hadc.Instance = ADC1;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.ScanConvMode = ADC_SCAN_DISABLE;
HAL_ADC_Init(&hadc);
}
void MX_USART_Init(void) {
__HAL_RCC_USART2_CLK_ENABLE();
huart.Instance = USART2;
huart.Init.BaudRate = 9600;
huart.Init.WordLength = UART_WORDLENGTH_8B;
huart.Init.StopBits = UART_STOPBITS_1;
huart.Init.Parity = UART_PARITY_NONE;
huart.Init.Mode = UART_MODE_TX_RX;
huart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
HAL_UART_Init(&huart);
}
nucleo:PD0
nucleo:PD2
nucleo:VDD
nucleo:PA14
nucleo:PA13
nucleo:PC6
nucleo:GND.1
nucleo:PC13
nucleo:PC14
nucleo:PF0
nucleo:PF1
nucleo:PB11
nucleo:PA2
nucleo:PD1
nucleo:PD2.2
nucleo:E5V
nucleo:GND.2
nucleo:IOREF.1
nucleo:NRST.1
nucleo:3V3.1
nucleo:5V.1
nucleo:GND.3
nucleo:GND.4
nucleo:VIN.1
nucleo:PA0
nucleo:PA1
nucleo:PA4
nucleo:PB1
nucleo:PA11
nucleo:PA12
nucleo:IOREF.2
nucleo:NRST.2
nucleo:3V3.2
nucleo:5V.2
nucleo:GND.5
nucleo:GND.6
nucleo:VIN.2
nucleo:A0
nucleo:A1
nucleo:A2
nucleo:A3
nucleo:A4
nucleo:A5
nucleo:5V.3
nucleo:PA3
nucleo:PC15
nucleo:PB12.1
nucleo:PB12.2
nucleo:PB2
nucleo:GND.7
nucleo:PF3
nucleo:PA8
nucleo:PB15
nucleo:PB14
nucleo:PB13
nucleo:AGND
nucleo:PB0.1
nucleo:PD3
nucleo:PB8
nucleo:PB9
nucleo:AVDD.1
nucleo:GND.8
nucleo:PA5
nucleo:PA6
nucleo:PA7
nucleo:PB0.2
nucleo:PC7
nucleo:PA9
nucleo:PA15
nucleo:PB5
nucleo:PB4
nucleo:PB10
nucleo:PB3
nucleo:PA10
nucleo:PB6
nucleo:PB7
nucleo:D15
nucleo:D14
nucleo:AVDD.2
nucleo:GND.9
nucleo:D13
nucleo:D12
nucleo:D11
nucleo:D10
nucleo:D9
nucleo:D8
nucleo:D7
nucleo:D6
nucleo:D5
nucleo:D4
nucleo:D3
nucleo:D2
nucleo:D1
nucleo:D0
led4:A
led4:C
led3:A
led3:C
led1:A
led1:C