Getting Started with FreeRTOS for ESP32 with ESP-IDF 4.x

<rawat.s>
4 min readDec 21, 2020

--

.

บทความนี้เป็นการเขียนบันทึกขั้นตอนการติดตั้งและใช้งานซอฟต์แวร์ที่เกี่ยวข้องกับการเขียนโค้ดภาษา C ร่วมกับ FreeRTOS สำหรับบอร์ดไมโครคอนโทรลเลอร์ ESP32 โดยใช้ระบบปฏิบัติการ Linux เช่น Ubuntu หรือ Raspbian OS ในการทำงาน (Host Computer)

ESP32 Software Development based on Espressif’s ESP-IDF (Source: Espressif)

ซอฟต์แวร์ที่จะต้องติดตั้งคือ ESP-IDF 4.x (IoT Development Framework for the ESP32 and ESP32-S Series of SoCs) ของบริษัท Espressif ซึ่งเวอร์ชันปัจจุบันที่ได้ลองใช้คือ ESP-IDF 4.3 รองรับชิป ESP32 หลายรุ่น เช่น ESP32 (เวอร์ชันแรก) และ ESP32-S Series (ESP32-S2 และ ESP32-S3) เป็นต้น

ข้อสังเกต: ถ้าต้องการเขียนโค้ดด้วยภาษา C/C++ สำหรับ ESP32 เราก็อาจเลือกใช้งาน Arduino IDE ร่วมกับ Arduino Core for ESP32 ซึ่งมาพร้อมกับ FreeRTOS หรือ IDE ตัวเลือกอื่น เช่น VSCODE หรือ PlatformIO ได้เลย สามารถใช้คำสั่งต่าง ๆ ของ Arduino API ได้ ไม่จำเป็นต้องใช้คำสั่งต่าง ๆ ใน C API ของ ESP-IDF

จากเอกสารออนไลน์ [FreeRTOS-ESP32 API]ระบุไว้ว่า

ESP-IDF FreeRTOS is based on the Xtensa port of FreeRTOS v10.2.0.

หน้าตัวอย่างของเอกสารออนไลน์สำหรับการใช้งาน FreeRTOS-ESP32

.

ในบทความนี้เราจะใช้บอร์ด ESP32 ที่มีหน่วยความจำ Flash 4MB ราคาไม่แพง พอจะหาซื้อมาใช้งานได้

สำหรับระบบปฏิบัติการอื่น สามารถศึกษาขั้นตอนการติดตั้งได้จาก https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/

ขั้นตอนแรก: ติดตั้ง ESP-IDF เวอร์ชัน 4.x

.

ในตัวอย่างการทำคำสั่งต่อไปนี้ เราจะเลือกไดเรกทอรีสำหรับการติดตั้งโปรแกรมต่าง ๆ ที่เกี่ยวข้องไว้ใน $HOME/esp/esp-idf ของผู้ใช้งาน

ให้ทำคำสั่งตามลำดับต่อไปนี้

## install the ESP-IDF 4.3# set the ESPIDF path and export as a variable environment
$ export ESPIDF=$HOME/esp/esp-idf
# make a new directory for the ESPIDF path
$ mkdir -p $ESPIDF && cd $ESPIDF
# download the necessary software repository from github
$ git clone https://github.com/espressif/esp-idf.git $ESPIDF
# download and install all submodules
$ git submodule update --init --recursive

ก่อนทำขั้นตอนถัดไป แนะนำให้แก้ไขการเลือกใช้คำสั่ง Python Interpreter โดยเปลี่ยนจาก python (Python 2.7.x) ให้เป็น python3 (เช่น Python 3.7.x)

ใช้คำสั่ง nano เพื่อแก้ไขไฟล์ ./tools/idf_tools.py หรือจะใช้ Editor อื่นแทนก็ได้

$ nano ./tools/idf_tools.py

แก้ไขที่บรรทัดแรก เปลี่ยนจาก

#!/usr/bin/env python

ให้เป็น

#!/usr/bin/env python3

จากนั้นทำคำสั่งต่อไปนี้ เพื่อดาวน์โหลดและติดตั้งโปรแกรมต่าง ๆ ที่เกี่ยวข้อง

$ ./install.sh
ตัวอย่างข้อความเอาต์พุตขณะทำคำสั่ง ./install.sh

เมื่อทำมาถึงขั้นตอนนี้แล้ว เราจะสร้าง Python Virtual Environment เอาไว้ใช้งานสำหรับ ESP-IDF Tools

# create Python 3 virtual environment 
$ python3 -m venv $ESPIDF/build-venv
# activate Python3 virtual environment
$ source $ESPIDF/build-venv/bin/activate
# export environment variables for ESPIDF tools
$ source $ESPIDF/export.sh
# update PIP
$ pip install --upgrade pip
# install required Python3 packages via PIP
$ pip install -r $ESPIDF/requirements.txt
# exit the current Python virtual environment
$ deactivate

.

คำสั่งสุดท้ายที่ได้ทำไปในขั้นตอนที่แล้ว เป็นการจบหรือออกจากการทำงาน Python Virtual Environment และถ้าเราจะเริ่มใช้งานใหม่อีกครั้ง ก็มีลำดับคำสั่งดังนี้

$ export ESPIDF=$HOME/esp/esp-idf
$ source $ESPIDF/build-venv/bin/activate
$ source $ESPIDF/export.sh

การสร้างโปรเจกต์ ESP32 Application

.

ถัดไปเราจะสร้างไดเรกทอรีเอาไว้สำหรับเก็บไฟล์โปรเจกต์ใหม่ เช่น

$ mkdir -p $HOME/esp32_freertos && cd $HOME/esp32_freertos

เราจะลองใช้ตัวอย่างโปรเจกต์ที่มีอยู่แล้ว คือ hello_world ที่มาพร้อมกับ ESP-IDF 4.x โดยสำเนาไฟล์ มาเป็นโปรเจกต์ใหม่ แล้วลองทำขั้นตอน Build ดูว่า สามารถคอมไพล์โค้ดได้หรือไม่ ถ้าทำได้สำเร็จ จะได้ไฟล์ .bin นำไปใช้ทดลองกับบอร์ด ESP32 ได้เลย

$ cp -r $IDF_PATH/examples/get-started/hello_world .
$ cd ./hello_world
$ idf.py set-target esp32
$ idf.py menuconfig

ในขั้นตอนการทำ MenuConfig ลองดูว่า มีการตั้งค่าในเมนูต่าง ๆ อย่างไรไว้แล้วบ้าง (สามารถกดคีย์ลูกศรหรือ Arrow Keys เลื่อนขึ้นหรือลง ไปทางซ้ายหรือขวาได้) เช่น ตรวจสอบดูว่า การตั้งค่าสำหรับขนาดของหน่วยความจำ Flash (Memory Size) เท่ากับ 4MB หรือไม่ ถ้ามีการเปลี่ยนแปลงการตั้งค่าใด ๆ อย่าลืมทำการบันทึก เช่น กดคีย์ S [Save] และจบการทำงานโดยกดคีย์ Q [Quit]

การตั้งค่า Flash Size 4 MB

จากนั้นทำคำสั่งต่อไปนี้ เพื่อคอมไพล์โค้ดทั้งหมดของโปรเจกต์

$ idf.py build

ถ้าทำได้สำเร็จ ลองทำคำสั่งต่อไปนี้ เพื่ออัปโหลดไฟล์ .bin ที่ได้ ไปยังบอร์ดทดลอง ให้เสียบสาย USB เชื่อมต่อกับบอร์ด ESP32 ก่อน โดยทั่วไปแล้ว จะมีชื่อของอุปกรณ์ (Device Name) ตรงกับ /dev/ttyUSB0 มีการเลือกใช้ค่า Baudrate เท่ากับ 460800

$ idf.py -p /dev/ttyUSB0 -b 460800 flash

ถ้าต้องการดูข้อความที่ถูกส่งออกทาง USB-to-Serial ของบอร์ด ESP32 เมื่อโปรแกรมตัวอย่างเริ่มทำงาน ให้ทำคำสั่งต่อไปนี้ ถ้าต้องจากจบการทำงานหรือออกจากหน้า Console ให้กดคีย์ Ctrl+]

$ idf.py -p /dev/ttyUSB0 monitor

# press Ctrl+] to quit the program

.

ตัวอย่างการสร้างทาสก์สำหรับ ESP32-FreeRTOS

.

ถัดไปเรามาลองสร้างโปรเจกต์และไฟล์ที่เกี่ยวข้องเพื่อใช้งาน FreeRTOS ในเบื้องต้น โดยเริ่มต้นด้วยการสร้างไดเรกทอรีใหม่ ดังนี้

$ mkdir -p esp32_freertos_demo && cd esp32_freertos_demo
$ mkdir -p main

จากนั้นจะต้องสร้างไฟล์ CMakeLists.txt สำหรับโปรเจกต์ และสร้างไฟล์ main/main.c และ main/CMakeLists.txt ตามโครงสร้างต่อไปนี้ (ไฟล์นอกเหนือจากนั้น จะถูกสร้างขึ้นโดยอัตโนมัติ)

- CMakeLists.txt
- Makefile
- sdkconfig
- main/
- CMakeLists.txt
- component.mk
- main.c

ไฟล์ ./CMakeLists.txt

cmake_minimum_required(VERSION 3.5)include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(freertos_demo)

ไฟล์ ./main/CMakeLists.txt

idf_component_register(SRCS "main.c")
set(COMPONENT_ADD_INCLUDEDIRS ".")
set(COMPONENT_REQUIRES freertos)

ไฟล์ ./main/main.c

#include <stdio.h>
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "sdkconfig.h"
#define LED_GPIO 2 // use built-in LED pinvoid blink_task(void *pvParameters); // forward declarationvoid app_main() {
xTaskCreate( &blink_task, "led_blink_task",
configMINIMAL_STACK_SIZE,
NULL, tskIDLE_PRIORITY+1, NULL );
}
void blink_task(void *pvParameters) { // task entry function
gpio_pad_select_gpio(LED_GPIO);
gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);
uint32_t state = 0;
while(1) { // endless loop
gpio_set_level(LED_GPIO, state); // update output
vTaskDelay( 500/portTICK_PERIOD_MS ); // delay 500msec
state ^= 1; // toggle state
}
vTaskDelete(NULL); // Let the task delete itself.
}

ข้อสังเกต: ฟังก์ชัน void app_main() {} เป็นฟังก์ชันหลักของ ESP32 Application Code ภายในมีการใช้คำสั่ง xTaskCreate() เพื่อสร้างทาสก์ของ FreeRTOS จำนวนหนึ่งทาสก์

อีกประการหนึ่งคือ การทำงานของ FreeRTOS Task Scheduler จะเริ่มทำงานโดยอัตโนมัติด้วยคำสั่ง vTaskStartScheduler() ก่อนที่จะมีการฟังก์ชัน app_main()

.

จากนั้นทำขั้นตอน Build ด้วยคำสั่งนี้ (เลือกชิปเป้าหมาย หรือ Target เป็น esp32)

$ idf.py set-target esp32$ idf.py build

ถ้าต้องการปรับเปลี่ยนการตั้งค่าสำหรับ FreeRTOS เช่น TICK Rate เท่ากับ 100 Hz (Default) เราสามารถเปลี่ยนให้เป็น 1000 Hz ได้ โดยทำคำสั่ง

$ idf.py menuconfig$ idf.py build

เลือกไปที่เมนู “Component config” แล้วไปที่เมนู “FreeRTOS” เปลี่ยนค่าให้เป็น 1000 (ค่าที่เลือกได้ต้องอยู่ในช่วง 100–1000) บันทึกการเปลี่ยนแปลง จากนั้นต้องทำคำสั่งเพื่อคอมไพล์โค้ดอีกครั้ง

การเปลี่ยนค่า Tick Rate (Hz)

เมื่อทำขั้นตอน Build แล้ว จะได้ไฟล์ .bin ดังนี้

./build/freertos_demo.bin

ถ้าต้องการทดสอบการทำงานของโค้ดตัวอย่างโดยใช้บอร์ด ESP32 ให้ทำคำสั่งต่อไปนี้ แล้วสังเกตการกระพริบที่ LED ของบอร์ด

$ idf.py -p /dev/ttyUSB0 -b 460800 flash

สรุป: เราได้เห็นขั้นตอนการติดตั้งโปรแกรมต่าง ๆ ที่เกี่ยวข้องกับการทดลองเขียนโค้ดภาษา C เพื่อใช้งาน FreeRTOS ร่วมกับบอร์ด ESP32 และลองสร้างและคอมไพล์โค้ดตัวอย่าง เพื่อนำไปทดลองกับฮาร์ดแวร์จริง

ข้อสังเกต: ในกรณีที่มีการเขียนโค้ดที่มีความซับซ้อน มีหลายไฟล์ในโปรเจกต์ ก็อาจจะเลือกใช้ IDE เช่น Eclipse IDE หรือ VSCode เพื่ออำนวยความสะดวกในการเขียนโค้ด

--

--

<rawat.s>
<rawat.s>

Written by <rawat.s>

I'm Thai and working in Bangkok/Thailand.

No responses yet