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 




댓글 없음:

댓글 쓰기

3단 6핀 스위치로 DC 모터의 회전 방향을 바꾸어 보자

1. 필요는 연구의 어머니 항상 느끼는 부분이다. 필요하지 않으면 연구하지 않으며, 필요하면 연구한다. DC 모터를 조건에 따라서 정방향 또는 역방향으로 회전시켜야 하는 필요가 생겼다. 처음에는 MCU 및 Relay Switch를 이용하는 방법을 생각...