ArduinoEmbeded SystemESP32

มาลองใช้ FreeRTOS ทำไฟกระพริบบน Node32s แบบเทพๆ กันดีกว่า

By December 15, 2016 January 3rd, 2019 No Comments

กลับมากันอีกแล้วครับ สำหรับบทความนี้ เราจะมาแนะนำให้รู้จัก FreeRTOS หนึ่งในความสามารถใหม่ ที่มากับ ESP32 เนื่องจาก CPU ตัวใหม่ใน ESP32 เป็นแบบ Dual Core และ ประสิทธิ์ภาพความเร็วถึง 240 MHz ผมสงสัยว่าเราจะใช้ความสามารถมาได้เต็มที่ได้อย่างไงนะ ปกติ เคยเขียนแต่โปรแกรม หนึ่ง Core ทำมันทุกอย่าง

ทาง Espressif ได้เตรียมตัวเรื่องนี้มาไว้อย่างเดียวเลยที่เดียว เขาได้เละ core sdk เดิม มาเป็น core ใหม่ ที่มาพร้อมกับ FreeRTOS เลย ซึ่งทำให้เราเปิด Task การทำงาน ขนานกันไปได้เลย ซึ่งการเขียนโปรแกรมแบบ  FreeRTOS ทำให้ใช้ความสามารถของ ESP32 ได้ดียิ่งขึ้น แต่อาจจะแลกมากับความซับซ้อนของการคิดโปรแกรม

FreeRTOS คือออะไร

FreeRTOS เป็นระบบปฏิบัติการสําหรับอุปกรณ์ Embeded ใช้ได้ในหลากหลายไมโครคอนโทรเลอร์ และยังเป็นโปรเจคโอเพ่นซอร์สอีกด้วย (Open Source) ถูกออกแบบมาให้สามารถใช้งานได้ง่ายและมีขนาดค่อนข้างเล็ก ภายใน เคอร์เนลของระบบประกอบด้วยไฟล์ภาษาซีเพียง 3-4 ไฟล์เท่านั้น รวมทั้งมีตัวอยางการออกแบบและการใช้งานให้ศึกษา ซึ่งใครสนใจ FreeRTOS เป็นอย่างไง ลองหาอ่านในเน็ทจะมีข้อมูลเยอะครับ เนื่องจากมีคนนำไปใช้ในไมโครคอนโทรลเลอร์ตระกูลอื่นก่อนจะมาอยู่บน esp32

โดยรวมสรุปความสามารถเด่นของ FreeRTOS ไว้ดังนี้

  1. มีโครงสร้างที่เล็กและง่ายต่อการใช้งาน
  2. การจัดการเวลาต่างๆ สามารถเลือกตั้งค่าได้ ทั้งแบบ Preemptive หรือ Cooperation operation
  3. ควบคุมทาสก์(Task)และสแต็ก(Stack) ได้ง่าย

ซึ่งทาง Espressif นำ FreeRTOS มาใส่ใน ESP-IDF หรือ ชุดพัฒนาของ ESP32 จึงทำให้ใน arduino esp32 มีความสามารถของ FreeRTOS มาด้วยเลย ซึ่งวิธีใช้ ไม่ได้ยากอะไรครับ ลองดู ตัวอย่างโค๊ดนี้ไปลองกันเลยครับ  ใครอยากรู้ลึกๆ FreeRTOS ใช้งานอย่างไง แนะนำให้เข้าไปอ่านที่เวปของ FreeRTOS

สำหรับบอร์ดที่ทางเราใช้เป็น Node32s ครับ ที่ภูมิใจ ไทยทำ และ ตอนนี้มีจำหน่ายแล้ว ที่ Gravitech Thai

ตัวอย่างนี้ ทางผมเปิด 2 Task สำหรับทำไฟกระพริบ ที่ความเร็วไม่เท่ากันครับ

#define BUILDIN_LED 2
#define ledPIN1 23
#define ledPIN2 22

// ----------------------------------------------------------------------------------
void first_task(void *pvParameter){
  /* Configure the IOMUX register for pad BLINK_GPIO (some pads are
     muxed to GPIO on reset already, but some default to other
     functions and need to be switched to GPIO. Consult the
     Technical Reference for a list of pads and their default
     functions.)
  */
  pinMode(ledPIN1,OUTPUT);

  while(true) {
    digitalWrite(ledPIN1, HIGH);
    vTaskDelay(50 / portTICK_RATE_MS);
    digitalWrite(ledPIN1, LOW);
    vTaskDelay(50 / portTICK_RATE_MS);
  }
}

// ----------------------------------------------------------------------------------
void second_task(void *pvParameter){
  /* Configure the IOMUX register for pad BLINK_GPIO (some pads are
     muxed to GPIO on reset already, but some default to other
     functions and need to be switched to GPIO. Consult the
     Technical Reference for a list of pads and their default
     functions.)
  */
  pinMode(ledPIN2,OUTPUT);

  while(true) {
    digitalWrite(ledPIN2, HIGH);
    vTaskDelay(500 / portTICK_RATE_MS);
    digitalWrite(ledPIN2, LOW);
    vTaskDelay(500 / portTICK_RATE_MS);
  }
}

void setup() {
  
  pinMode(BUILDIN_LED,OUTPUT);

  // xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask)
  //first thread blinky in 50ms
  xTaskCreate(&first_task, "first_task", 1024, NULL, 5, NULL);
  //second thread blinky in 500ms
  xTaskCreate(&second_task,"second_task",1024, NULL, 5, NULL);
  
}


// the loop function runs over and over again forever
void loop() {
  digitalWrite(BUILDIN_LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(250);              // wait for a second
  digitalWrite(BUILDIN_LED, LOW);    // turn the LED off by making the voltage LOW
  delay(250);              // wait for a second
}

 

หรือ เข้าไปดูที่ gist

Leave a Reply