2018년 12월 3일 월요일

ESP32의 Dual Core를 활용하자.

1. ESP32와 ESP8266의 차이는?

 ESP32는 ESP8266과 많은 차이를 보인다.  그중 가장 으뜸을 꼽으라 하면 듀얼코어와 싱글코어의 차이라고 하겠다.  ESP32는 듀얼코어이다. !!

2. 음 듀얼코어라고? 난 안쓰는데?

 사실 이미 쓰고 있다. 느끼지 못할 뿐이다.  Arduino IDE로 프로그램을 만들어서 실행중이라면 이미 2개의 코어를 모두 쓰고 있다. 다만 모르고 있을 뿐이다.
일반적으로
  Core 0 : 무선 통신과 같은  ESP32 본연의 기능이 실행됨
  Core 1 : 컴파일된 Arduino 코드가 실행됨

3. 알아서 듀얼 코어를 잘 사용하는데 왜?

 사실 간단하게 온도나 측정하거나 LED나 껏다가 켜는 등의 별거 아닌것들을 하는 경우 큰 의미가 없다. 온도나 측정하는데 ESP32는 오버 스펙이다.  각설하고, ESP32의 코어 하나로 수행하기에 벅찬 작업을 하는 듀얼 코어를 사용한다.  ESP32의 Core 0은 무선 통신과 같은 작업을 수행하기에 상대적으로 널널하다. 즉 대부분 쉬고 있다. 이를 활용하면 ESP32의 기능을 극대화 할 수 있다.  또는 Core 0을 이용하여 Core 1의 패닉 상태를 조사하고, 필요시 리부팅을 할 수 있다.

4. 사용 예제는?

크게 어렵지 않은 예제 코드를 아래에 기록해 본다.  예제는 코어 2개에서 각각의 analogRead를 수행하는 예제이다.

/* -----------------------------------------------
   ESP32 Dual Core tester
  ----------------------------------------------- */

//-----------------------------------------------
// global functions
//-----------------------------------------------
void Task1(void * parameter)
{
  while (true) {
    unsigned long start = micros();
    // very long task..
    for ( uint32_t i = 0; i < 1000; i++) {
      analogRead(33);
    }
    Serial.printf("Task 1 done  (on Core : %d)  Elps = %d  µs \n", xPortGetCoreID(), micros() - start);
    delay(100);
  }
}
void Task2(void * parameter)
{
  while (true) {
    unsigned long start = micros();
    // very long task..
    for ( uint32_t i = 0; i < 1000; i++) {
      analogRead(35);
    }
    //workLoad();
    Serial.printf("Task 2 done  (on Core : %d)  Elps = %d  µs \n", xPortGetCoreID(), micros() - start);
    delay(100);
  }
}
TaskHandle_t TaskA, TaskB;

//-----------------------------------------------
// setup functions
//-----------------------------------------------
void setup() {
  Serial.begin(115200);
  delay(100);

  xTaskCreatePinnedToCore(
    Task1,                  /* pvTaskCode */
    "Workload1",            /* pcName */
    1000,                   /* usStackDepth */
    NULL,                   /* pvParameters */
    1,                      /* uxPriority */
    &TaskA,                 /* pxCreatedTask */
    0);                     /* xCoreID */

  xTaskCreatePinnedToCore(
    Task2,
    "Workload2",
    1000,
    NULL,
    1,
    &TaskB,
    1);
}

//-----------------------------------------------
// loop functions
//-----------------------------------------------
void loop() {
  // This task will run in the core 1
  unsigned long start = micros();
  for ( uint32_t i = 0; i < 1000; i++) {
    // do nothing
  }
  Serial.printf("Task 0 done  (on Core : %d)  Elps = %d  µs \n", xPortGetCoreID(), micros() - start);
  delay(10) ;
}



위의 예제를 실행 시키면 아래와 같은 출력을 볼 수 있다.

Task 0 done  (on Core : 1)  Elps = 0  µs 
Task 0 done  (on Core : 1)  Elps = 2  µs 
Task 1 done  (on Core : 0)  Elps = 12450  µs 
Task 2 done  (on Core : 1)  Elps = 12380  µs 
Task 0 done  (on Core : 1)  Elps = 0  µs 
Task 0 done  (on Core : 1)  Elps = 0  µs 
Task 0 done  (on Core : 1)  Elps = 0  µs 
Task 0 done  (on Core : 1)  Elps = 0  µs 
Task 0 done  (on Core : 1)  Elps = 0  µs 




댓글 없음:

댓글 쓰기

파워뱅크를 만들어 보자

- 방전률이 높은 배터리를 이용하는 작업은 화재, 폭발의 위험이 있습니다. 충분한 지식을 가지고 있더라도, 잠깐의 부주의로 사고가 발생할 수 있습니다. 사고는 본인의 책임입니다.  소재로 시작된 만들기 일전에 어머님의 전동휠체어 배터리를 만들어서 교체...