본문 바로가기
아두이노 코딩

아두이노 코딩 코드 : Arduino IDE를 사용한 ESP32 듀얼 코어 프로그래밍 소스

by 49분전 2020. 2. 22.

아두이노 코딩 코드 : Arduino IDE를 사용한 ESP32 듀얼 코어 프로그래밍 소스

 

ESP 모듈은 ESP8266, ESP-12E 등과 같은 Wi-Fi 기능으로 인기가 높습니다. 이 모든 것은 Wi-Fi 기능을 갖춘 강력한 마이크로컨트롤러 모듈입니다. 이전의 ESP 모듈보다 더 강력하고 다재다능한 ESP 모듈이 하나 더 있습니다. 그 이름은 ESP32입니다. Bluetooth와 Wi-Fi 연결이 있으며, 이미 ESP32의 BLE 기능을 설명했으며, 많은 IoT 프로젝트에서 ESP32를 사용했습니다. 하지만 ESP32가 듀얼 코어 마이크로컨트롤러라는 사실을 아는 사람은 거의 없습니다.

 

ESP32에는 두 개의 32비트 텐실리카 Xtensa LX6 마이크로프로세서가 있어 강력한 듀얼 코어(core0 및 core1) 마이크로컨트롤러입니다. 싱글 코어 및 듀얼 코어 두 가지 모델로 제공됩니다. 하지만 가격 차이가 크지 않아 듀얼코어 모델이 더 인기가 좋습니다.

ESP32는 Arduino IDE, Espressif IDF, Lua RTOS 등을 사용하여 프로그래밍할 수 있습니다. Arduino IDE를 사용하여 프로그래밍하는 동안 Core0은 이미 RF 통신용으로 프로그래밍되어 있으므로 Core1에서만 코드가 실행됩니다. 이 튜토리얼에서는 ESP32의 두 코어를 모두 사용하여 두 가지 작업을 동시에 수행하는 방법을 보여드리겠습니다. 여기서 첫 번째 작업은 온보드 LED를 깜박이는 것이고 두 번째 작업은 DHT11 센서에서 온도 데이터를 가져오는 것입니다.

먼저 단일 코어에 비해 멀티 코어 프로세서의 장점을 살펴보겠습니다.

 

멀티 코어 프로세서의 장점입니다.

멀티 코어 프로세서는 두 개 이상의 프로세스가 동시에 작동할 때 유용합니다.
작업이 서로 다른 코어에 분산되면 속도가 증가하고 여러 프로세스를 동시에 완료할 수 있습니다.
코어가 유휴 모드일 때 그 시간에 사용되지 않는 주변 장치를 차단하는 데 사용될 수 있기 때문에 전력 소비를 줄일 수 있습니다.
듀얼 코어 프로세서는 한 번에 하나씩 처리하는 대신 한 번에 두 개씩 처리할 수 있기 때문에 단일 코어 프로세서보다 다른 스레드 간 전환 빈도가 낮아야 합니다.

ESP32와 FreeRTOS입니다.

ESP32 보드에 이미 FreeRTOS 펌웨어가 설치되어 있습니다. FreeRTOS는 멀티태스킹에 매우 유용한 오픈 소스 실시간 운영 체제입니다. RTOS는 리소스를 관리하고 시스템 성능을 극대화하는 데 도움이 됩니다. FreeRTOS에는 다양한 용도로 사용되는 여러 API 기능이 있으며, 이러한 API를 사용하여 태스크를 생성하여 다른 코어에서 실행할 수 있습니다.

FreeRTOS API의 전체 문서는 여기에서 확인할 수 있습니다. 우리는 코드에 있는 몇 가지 API를 사용하여 두 코어에서 모두 실행되는 멀티태스킹 애플리케이션을 구축하려고 합니다.

 

ESP32 코어 ID를 찾습니다.

여기서는 Arduino IDE를 사용하여 코드를 ESP32에 업로드하겠습니다. 코드가 실행되고 있는 Core ID를 알기 위해 API 기능이 있습니다.

 

xPortGetCoreID()

 

이 기능은 Void setup() 및 Void 루프() 함수에서 호출하여 이러한 기능이 실행되는 코어 ID를 알 수 있습니다.

아래 스케치를 업로드하여 이 API를 테스트할 수 있습니다.

 

void setup() {
  Serial.begin(115200);
  Serial.print("setup() function running on core: ");
  Serial.println(xPortGetCoreID());
}
void loop() {
  Serial.print("loop() function running on core: ");
  Serial.println(xPortGetCoreID());
}

 

위의 스케치를 업로드한 후 시리얼 모니터를 열면 아래와 같이 core1에서 두 기능이 모두 실행되고 있음을 알 수 있습니다.

위의 관찰을 통해 기본 Arduino 스케치는 항상 core1에서 실행된다고 결론을 내릴 수 있습니다.

 

ESP32 듀얼 코어 프로그래밍입니다.

Arduino IDE는 ESP32용 FreeRTOS 및 FreeRTOS API를 지원하므로 두 코어에서 독립적으로 실행할 수 있는 태스크를 생성할 수 있습니다. 이 작업은 깜박임 리드, 온도 전송 등과 같은 보드 작업을 수행하는 코드 조각입니다.

아래 기능은 두 코어에서 모두 실행할 수 있는 태스크를 생성하는 데 사용됩니다. 이 함수에서는 우선 순위, 코어 ID 등과 같은 인수를 제공해야 합니다.

이제 다음 단계에 따라 태스크 및 태스크 기능을 생성합니다.



1. 먼저, Void setup 기능에서 작업을 작성합니다. 여기서는 0.5초마다 LED를 깜박이는 작업과 2초마다 온도를 판독하는 작업 등 두 가지 작업을 만듭니다.

 

xTaskCreatePinnedToCore() 함수는 7개의 인수를 사용합니다.

태스크를 구현할 기능 이름(태스크1)입니다.
작업에 지정된 모든 이름("태스크1" 등)입니다.
태스크에 할당된 스택 크기(1단어=2바이트)입니다.
작업 입력 매개 변수(NULL일 수 있습니다)
태스크의 우선 순위( 0이(가) 가장 낮은 우선 순위입니다)
작업 핸들(NULL일 수 있습니다)
작업이 실행될 코어 ID(0 또는 1)입니다.
이제 xTaskCreatePinnedToCore() 함수의 모든 인수를 제공하여 리드를 깜박일 Task1을 생성합니다.

xTaskCreatePinnedToCore(Task1code, "Task1", 10000, NULL, 1, NULL,  0); 

 

마찬가지로 Task2에 대한 Task2를 생성하고 7번째 인수에 코어 ID 1을 만듭니다.

 

xTaskCreatePinnedToCore(Task2code, "Task2", 10000, NULL, 1, NULL,  1); 

작업의 복잡성에 따라 우선 순위 및 스택 크기를 변경할 수 있습니다.

2. 이제 Task1code와 Task2code 기능을 구현하겠습니다. 이러한 기능에는 필요한 작업에 대한 코드가 포함됩니다. 우리의 경우, 첫 번째 작업이 시작 부분을 깜박이고 다른 작업은 온도를 가져옵니다. 따라서 Void setup 기능을 벗어나 각 작업에 대해 두 개의 개별 기능을 만듭니다.

0.5초 후에 온보드에서 깜박이는 Task1code 기능은 다음과 같이 구현됩니다.

 

Void Task1code( void * parameter) {
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
for(;;) {//infinite loop
digitalWrite(led, HIGH);
delay(500);
digitalWrite(led, LOW);
​​delay(500);
}
}

 

마찬가지로 온도를 가져오는 Task2code 기능을 구현합니다.

 

void Task2code( void * pvParameters ){
  Serial.print("Task2 running on core ");
  Serial.println(xPortGetCoreID());
  for(;;){
    float t = dht.readTemperature();
     Serial.print("Temperature: ");
     Serial.print(t);
   delay(2000);
  }
}

 

3. 여기서 무효 루프 기능은 비어 있습니다. 이미 알고 있듯이, 루프 및 설정 기능은 core1에서 실행되므로 void 루프 기능에서도 core1 태스크를 구현할 수 있습니다.

이제 코딩 부분이 끝났으니 도구 메뉴에서 ESP32 보드를 선택하여 Arduino IDE를 사용하여 코드를 업로드하기만 하면 됩니다. DHT11 센서를 ESP32의 핀 D13에 연결했는지 확인합니다.

이제 다음과 같이 직렬 모니터 또는 Arduino IDE에서 결과를 모니터링할 수 있습니다.

실시간 시스템과 같은 복잡한 애플리케이션은 ESP32의 듀얼 코어를 사용하여 여러 작업을 동시에 실행하여 구축할 수 있습니다.

아래에 전체 코드 소스가 나와 있습니다.

 

Code

 

#include "DHT.h"
#define DHTPIN 13
#define DHTTYPE DHT11 
const int led = 2;  
DHT dht(DHTPIN, DHTTYPE);
void setup() {
  Serial.begin(115200); 
  pinMode(led, OUTPUT);
dht.begin();
xTaskCreatePinnedToCore(Task1code, "Task1", 10000, NULL, 1, NULL,  1); 
  delay(500); 
xTaskCreatePinnedToCore(Task1code, "Task1", 10000, NULL, 1, NULL,  0); 
    delay(500); 
}
void Task1code( void * pvParameters ){
  Serial.print("Task1 running on core ");
  Serial.println(xPortGetCoreID());
  for(;;){
    digitalWrite(led, HIGH);
    delay(300);
    digitalWrite(led, LOW);
    delay(300);
  } 
}
void Task2code( void * pvParameters ){
  Serial.print("Task2 running on core ");
  Serial.println(xPortGetCoreID());
  for(;;){
      float h = dht.readHumidity();
    float t = dht.readTemperature();
     float f = dht.readTemperature(true);
      Serial.print("Temperature: ");
     Serial.print(t);
   Serial.print(" *C \n ");
     if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
    delay(2000);
  }
}
void loop() {
}

댓글