091
[C/C++] ESP32에서 RTOS 사용하여 3가지 작업 유연하게 처리하기 본문
01. RTOS(Real-Time Operating System)
- RTOS : 실시간 운영체제로, 여러 개의 작업을 스케쥴링을 통해 동시에 실행되도록 관리해줌. loop() 내부에서 너무 다양한 기능을 구현하다보면 버벅이거나 응답이 느려지므로 RTOS를 이용하여 여러 작업을 동시에 처리하는 시스템으로 만들어줌
-> ESP32에는 FreeRTOS가 기본적으로 내장되어있고 Task를 적절히 Core 0 또는 Core 1에 배치해줌
- ESP32의 듀얼 코어 구조 : ESP32에는 Core 0과 Core 1로 두개의 코어가 있음. 코어는 명령을 실제로 처리하는 CPU의 뇌처럼 생각하면 편함 -> Core 0은 시스템 전용으로 WiFi, 블루투스, 백그라운드 OS 작업을 하고, Core 1은 사용자 전용으로, setup(), loop(), 그리고 기본 Task들을 실행함
=> 이후에 배우는 Task의 경우 기본적으로 Core 1에서 실행되지만 고정함수(xTaskCreatePinnedToCore)를 통해 명시적으로 핀을 할당할 수 있음
- RTOS 사용 :
• 다중 센서 데이터 읽기 + 디스플레이 + 제어
• 즉시 반응해야하는 시스템
• 명확한 작업 분담
• LCD 깜빡임 및 UART 반응 속도 문제 해결
02. RTOS 사용하여 3가지 작업 유연하게 처리하기
- 하드웨어 :
-> 이전 글에서 사용됐던 스위치 하드웨어와 완전히 일치 : 관련설명글 ->
(2025.04.09 - [Programming Language/C&C++] - [C/C++] ESP32에서 3가지 작업(LCD,Switch,UART) 반복처리하기)
- 소프트웨어 :
#include <Wire.h> // Include the I2C communication library
#include "LCD1602_Display.h" // Include the LCD1602_Display class
#define LED_PIN 4
#define SWITCH_PIN 5
#define PASSWORD "S113003391"
LCD1602_Display lcd(0x27, 16, 2); // Create LCD object with I2C address 0x27
bool userMode = false;
bool romoteMode = false;
String lastText = ""; // 상태 변경 전 마지막 화면 텍스트를 저장
void setup() {
Serial.begin(115200); // Initialize Serial Monitor
Wire.begin(21, 22); // Initialize I2C communication (SDA=21, SCL=22)
lcd.init(); // Initialize the LCD display
lcd.displayText("Secure", 0, 0); // 초기 메시지 표시
xTaskCreate(Task1, "LCD", 2048, NULL, 1, NULL);
xTaskCreate(Task2, "GPIO", 2048, NULL, 1, NULL);
xTaskCreate(Task3, "UART", 2048, NULL, 1, NULL);
}
void loop() {
// Nothing here, tasks are handled in the background
}
void Task1(void *pvParameters) { // LCD
while (1) {
String displayText = "";
if (userMode) {
if (!romoteMode) {
displayText = "Local Control";
} else {
displayText = "Remote Control";
}
} else {
displayText = "Secure";
}
// 상태가 변경될 때만 텍스트 업데이트
if (displayText != lastText) {
lcd.clearScreen(); // 화면 지우지 않고 텍스트만 바꿈
lcd.displayText(displayText, 0, 0);
lastText = displayText; // 마지막 텍스트 상태 저장
}
delay(500); // 너무 자주 업데이트 하지 않도록 잠시 대기
vTaskDelay(100/ portTICK_PERIOD_MS);
}
}
void Task2(void *pvParameters) { // GPIO 스위치
pinMode(LED_PIN, OUTPUT);
pinMode(SWITCH_PIN, INPUT);
while (1) {
if (userMode && !romoteMode) { // Local Mode
int switchState = digitalRead(SWITCH_PIN);
digitalWrite(LED_PIN, switchState); // 스위치 상태에 따라 LED 상태 제어
delay(1000); // 1초 대기
}
vTaskDelay(100/ portTICK_PERIOD_MS);
}
}
void Task3(void *pvParameters) { // UART 입력 기반 -> 비밀번호, ON/OFF
while (1) {
if (Serial.available()) {
String input = Serial.readStringUntil('\n');
input.trim();
if (!userMode) {
if (input == PASSWORD) {
userMode = true;
} else {
Serial.println("Wrong Password");
}
} else {
if (input == "LMode") {
romoteMode = false;
} else if (input == "RMode") {
romoteMode = true;
} else {
Serial.println("Please Type LMode or RMode");
}
if (romoteMode) { // Remote Mode
if (input == "ON") digitalWrite(LED_PIN, HIGH);
else if (input == "OFF") digitalWrite(LED_PIN, LOW);
}
}
}
vTaskDelay(100/ portTICK_PERIOD_MS);
}
}
- 이전 글에서 구현했던 세가지 기능을 Task1,2,3으로 나누어 구현해주었음, Task1은 LCD 화면에 어떤 식으로 뜰지 구현해주고, Task2는 GPIO는 스위치의 ON/OFF에 따라 LED 불빛을 조절해줌, 두 장치 간 데이터를 TX(송신)과 RX(수신) 라인을 통해 전송하는 방식인 UART는 입력 기반으로 Serial로 ON, OFF를 받아야하므로 여기서 RMode를 구현해줌
- 태스크와 관련되 함수들 :
• xTaskCreate(Task1, "LCD", 2048, NULL, 1, NULL); : 태스크를 등록하는 함수
xTaskCreate(실행 함수의 이름, 태스크 이름, 스택 사이즈, 태스크에 넘길 매개변수, 우선순위, 태스크 핸들 저장할 포인터)
• void Task1(void *pvParameters) { ... } : FreeRTOS의 본체로, while(1) 안에 반복할 함수를 넣어주면 됨
• vTaskDelay(100 / portTICK_PERIOD_MS); : Task를 정한 시간만큼 쉬게 해주는 함수로, Task들은 CPU를 번갈아가며 쓰는 멀티태스킹 시스템인데, 각 테스크가 무한 루프(while(1))을 돌면서 너무 오랫동안 CPU를 독점하고 있으면 안되기 때문에 시간을 정해 일시적으로 쉬게 만들어줌
-> portTICK_PERIOD_MS : FreeRTOS에서 1틱(Tick)이 몇 밀리 초인지 나타내는 상수로, RTOS 내부적으로 시간 Tick 단위로 관리하고, 밀리초 단위로 쉬고 싶을 때 정확한 계산을 위해 사용되는 상수( 1Tick = 1ms, 10ms 처럼 FreeRTOSConfig.h에 FreeRTOS 설정값인 configTICK_RATE_HZ로 선언, configTICK_RATE_HZ가 1000일 경우 1Tick = 1ms/ 100일 경우 1Tick = 10ms임)
void Task1(void *pvParameters) {
while (1) {
// LCD 상태 체크해서 화면에 보여줌
vTaskDelay(100 / portTICK_PERIOD_MS); // 잠시 쉬었다가 다음 루프
}
}
'Programming Language > C&C++' 카테고리의 다른 글
[C/C++] ESP32와 DHT11 연결해서 온도에 따라 LED ON/OFF 하기 (0) | 2025.05.19 |
---|---|
[C/C++] ESP32와 MFRC522 연결해서 카드로 LED ON/OFF 하기 (0) | 2025.05.13 |
[C/C++] ESP32에서 3가지 작업(LCD,Switch,UART) 반복처리하기 (0) | 2025.04.09 |
[C/C++] ESP32에서 EEPROM 저장하기 (0) | 2025.04.08 |
[C/C++] LCD에 원하는 글자를 출력하기 (4) | 2025.03.24 |