#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Инициализация LCD
LiquidCrystal_I2C LCD(0x27, 16, 2);
// Очереди для передачи данных
QueueHandle_t displayQueue;
QueueHandle_t ledControlQueue;
char displayBuffer[128];
// Пин для кнопки
const int buttonPin = 2;
int buttonState = 0;
int lastButtonState = 0;
int countdownValue = 10;
// Пины для светодиодов
const int ledPins[] = { 13, 32, 14, 15 };
// Тип данных для очереди управления светодиодами
struct LedControlData {
int duration; // Время, на которое нужно включить светодиоды
};
// Задача для обработки кнопки
void TaskProcessButton(void *pvParameters) {
while (true) {
buttonState = digitalRead(buttonPin);
if (buttonState == LOW && lastButtonState == HIGH) {
countdownValue--;
if (countdownValue < 0) {
countdownValue = 10;
// Отправляем сообщение о включении светодиодов на 10 секунд
LedControlData data = { 10 }; // Светодиоды горят 10 секунд
xQueueSend(ledControlQueue, &data, portMAX_DELAY);
// Отправляем сообщение для отображения на экране
snprintf(displayBuffer, sizeof(displayBuffer), "LEDs ON: %d s", 10);
xQueueSend(displayQueue, &displayBuffer, portMAX_DELAY);
} else {
// Отправляем текущее значение счётчика для отображения
snprintf(displayBuffer, sizeof(displayBuffer), "Count: %d", countdownValue);
xQueueSend(displayQueue, &displayBuffer, portMAX_DELAY);
}
delay(200); // Антидребезг
}
lastButtonState = buttonState;
vTaskDelay(pdMS_TO_TICKS(100));
}
}
// Задача для управления светодиодами
void TaskLedControl(void *pvParameters) {
LedControlData data;
while (true) {
if (xQueueReceive(ledControlQueue, &data, portMAX_DELAY)) {
// Включаем светодиоды
for (int i = 0; i < 4; i++) {
digitalWrite(ledPins[i], HIGH);
}
// Обратный отсчёт для светодиодов
for (int i = data.duration; i > 0; i--) {
snprintf(displayBuffer, sizeof(displayBuffer), "LEDs ON: %d s", i);
xQueueSend(displayQueue, &displayBuffer, portMAX_DELAY);
vTaskDelay(pdMS_TO_TICKS(1000)); // Ждём 1 секунду
}
// Выключаем светодиоды
for (int i = 0; i < 4; i++) {
digitalWrite(ledPins[i], LOW);
}
// Отправляем сообщение для экрана, что светодиоды выключены
snprintf(displayBuffer, sizeof(displayBuffer), "LEDs OFF");
xQueueSend(displayQueue, &displayBuffer, portMAX_DELAY);
}
}
}
// Задача для отображения данных на LCD
void TaskDisplayData(void *pvParameters) {
while (true) {
if (xQueueReceive(displayQueue, &displayBuffer, portMAX_DELAY)) {
LCD.clear();
LCD.setCursor(0, 0);
LCD.print("Tap button!");
LCD.setCursor(0, 1);
LCD.print(displayBuffer);
}
vTaskDelay(pdMS_TO_TICKS(500)); // Обновление экрана раз в 0.5 секунды
}
}
void setup() {
Serial.begin(115200);
LCD.init();
LCD.backlight();
pinMode(buttonPin, INPUT_PULLUP);
for (int i = 0; i < 4; i++) {
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], LOW);
}
// Инициализация очередей
displayQueue = xQueueCreate(5, sizeof(char[128]));
ledControlQueue = xQueueCreate(5, sizeof(LedControlData));
// Создание задач
xTaskCreate(TaskProcessButton, "ProcessButton", 2048, NULL, 1, NULL);
xTaskCreate(TaskDisplayData, "DisplayData", 2048, NULL, 1, NULL);
xTaskCreate(TaskLedControl, "LedControl", 2048, NULL, 1, NULL);
}
void loop() {
// Пусто, так как используются задачи
}