#include <Arduino.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE 0
#else
#define ARDUINO_RUNNING_CORE 1
#endif
#ifndef LED_BUILTIN
#define LED_BUILTIN 13
#endif
// LCD I2C 16x2
LiquidCrystal_I2C lcd(0x27, 16, 2); // Nếu không được, thử đổi 0x3F
// Chân kết nối
const int ledPin1 = 33;
const int ledPin2 = 25;
const int buttonPin = 32;
// Trạng thái LED
volatile bool led1State = LOW;
volatile bool led2State = LOW;
// Trạng thái nút
volatile bool buttonPressed = false;
// Mutex
SemaphoreHandle_t lcdMutex;
SemaphoreHandle_t ledMutex;
// Hàm cập nhật LCD
void updateLCD() {
if (xSemaphoreTake(lcdMutex, portMAX_DELAY) == pdTRUE) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("LED1: ");
lcd.print(led1State ? "ON " : "OFF");
lcd.setCursor(0, 1);
lcd.print("LED2: ");
lcd.print(led2State ? "ON " : "OFF");
xSemaphoreGive(lcdMutex);
}
}
// Task nháy LED1 bình thường
void TaskBlinkLED1(void *pvParameters) {
(void) pvParameters;
pinMode(ledPin1, OUTPUT);
while (1) {
if (!buttonPressed) { // Nếu không giữ nút
digitalWrite(ledPin1, HIGH);
led1State = HIGH;
updateLCD();
vTaskDelay(pdMS_TO_TICKS(2000));
digitalWrite(ledPin1, LOW);
led1State = LOW;
updateLCD();
vTaskDelay(pdMS_TO_TICKS(3000));
} else {
vTaskDelay(pdMS_TO_TICKS(100)); // Nếu đang giữ nút thì LED không tự nhấp nháy
}
}
}
// Task nháy LED2 bình thường
void TaskBlinkLED2(void *pvParameters) {
(void) pvParameters;
pinMode(ledPin2, OUTPUT);
while (1) {
if (!buttonPressed) { // Nếu không giữ nút
digitalWrite(ledPin2, HIGH);
led2State = HIGH;
updateLCD();
vTaskDelay(pdMS_TO_TICKS(2500));
digitalWrite(ledPin2, LOW);
led2State = LOW;
updateLCD();
vTaskDelay(pdMS_TO_TICKS(500));
} else {
vTaskDelay(pdMS_TO_TICKS(100));
}
}
}
// Task đọc nút và điều khiển LED khi giữ
void TaskButtonControl(void *pvParameters) {
(void) pvParameters;
pinMode(buttonPin, INPUT_PULLUP);
while (1) {
int currentButtonState = digitalRead(buttonPin);
if (currentButtonState == LOW) { // Nút đang nhấn
buttonPressed = true;
if (xSemaphoreTake(ledMutex, portMAX_DELAY) == pdTRUE) {
digitalWrite(ledPin1, HIGH);
digitalWrite(ledPin2, LOW);
led1State = HIGH;
led2State = LOW;
updateLCD();
xSemaphoreGive(ledMutex);
}
// Đợi 500ms rồi đổi trạng thái luân phiên
vTaskDelay(pdMS_TO_TICKS(500));
while (digitalRead(buttonPin) == LOW) { // Giữ nút liên tục
if (xSemaphoreTake(ledMutex, portMAX_DELAY) == pdTRUE) {
led1State = !led1State;
led2State = !led2State;
digitalWrite(ledPin1, led1State);
digitalWrite(ledPin2, led2State);
updateLCD();
xSemaphoreGive(ledMutex);
}
vTaskDelay(pdMS_TO_TICKS(500)); // Đổi trạng thái mỗi 500ms
}
} else {
buttonPressed = false;
vTaskDelay(pdMS_TO_TICKS(100)); // Thả nút, delay nhỏ
}
}
}
void setup() {
Serial.begin(115200);
Serial.println("ESP32 FreeRTOS LED + Button + LCD");
Wire.begin();
lcd.init();
lcd.backlight();
lcd.print("Initializing...");
// Tạo mutex
lcdMutex = xSemaphoreCreateMutex();
ledMutex = xSemaphoreCreateMutex();
// Tạo task
xTaskCreatePinnedToCore(TaskBlinkLED1, "TaskBlinkLED1", 2048, NULL, 1, NULL, ARDUINO_RUNNING_CORE);
xTaskCreatePinnedToCore(TaskBlinkLED2, "TaskBlinkLED2", 2048, NULL, 1, NULL, ARDUINO_RUNNING_CORE);
xTaskCreatePinnedToCore(TaskButtonControl, "TaskButtonControl", 2048, NULL, 2, NULL, ARDUINO_RUNNING_CORE);
vTaskDelay(pdMS_TO_TICKS(1000));
updateLCD();
}
void loop() {
// Không làm gì ở loop
}