การติดตั้งและใช้งาน ESP-IDF สำหรับ WSL / Ubuntu#


ESP-IDF สำหรับการเขียนโค้ด ESP32 ด้วยภาษา C/C++#

ขั้นตอนการติดตั้ง ESP-IDF (Espressif IoT Development Framework) ของบริษัท Espressif สำหรับ WSL2 - Ubuntu (ทดลองใช้กับ Ubuntu 22.04 LTS) ในเครื่องคอมพิวเตอร์ที่มีระบบปฏิบัติการ Windows 10 มีดังนี้

รูป: ESP-IDF ซอฟต์แวร์สำหรับการเขียนโปรแกรม C/C++ เพื่อใช้งานกับ ESP32 SoCs (Source: Espressif)

รูป: ตารางแสดงความสัมพันธ์ระหว่างเวอร์ชันของ ESP-IDF และการใช้งานร่วมกับชิปของ Espressif ในแต่ละรุ่น (ESP-IDF Github Repository)

ในขณะที่เขียนบทความนี้เวอร์ชัน EDF-IDF ล่าสุดคือ v5.0 เป็น Stable Version

1) เริ่มต้นด้วยการเปิดใช้งาน Linux Terminal ของ WSL - Ubuntu แล้วทำคำสั่งต่อไปนี้ เพื่อติดตั้งซอฟต์แวร์ ซึ่งมีหลายแพ็คเกจที่จำเป็นสำหรับการทำงานของ ESP-IDF

# install software packages required before using the ESP-IDF
$ sudo apt install git wget flex bison gperf \
  python3 python3-pip python3-setuptools python3-venv \
  cmake ninja-build ccache \
  libffi-dev libssl-dev dfu-util libusb-1.0-0

 

รูป: ตัวอย่างการทำคำสั่งเพื่อติดตั้งซอฟต์แวร์ใน Ubuntu

ตรวจสอบเวอร์ชันของ Python 3 (ในตัวอย่างนี้ จะเห็นได้ว่าเป็น Python v3.10.6)

# check the version of Python3
$ python3 --version
Python 3.10.6

 

2) สร้างไดเรกทอรีใหม่สำหรับการติดตั้ง ESP-IDF ที่มีชื่อว่า ~/esp อยู่ในไดเรกทอรีของผู้ใช้ จากนั้นดาวน์โหลดไฟล์ของ ESP-IDF มาจาก Github เก็บไว้ใน ~/esp/esp-idf

# create a new directory named 'esp' under the user's home directory
$ mkdir -p ~/esp && cd ~/esp
# clone the esp-idf (master branch) repo from github
$ git clone --recursive git://github.com/espressif/esp-idf
# change directory to '~/esp/esp-idf'
$ cd ~/esp/esp-idf
# update submodules (optional)
$ git submodule update --init --recursive

รูป: ตัวอย่างการทำคำสั่งเพื่อดาวน์โหลด ESP-IDF มาจาก Github

3) ถัดไปจะต้องดาวน์โหลดและติดตั้งไฟล์ที่เป็นโปรแกรมสำหรับการคอมไพล์โค้ด (เช่น โปรแกรมที่ทำหน้าที่เป็น C/C++ Toolchains) ซึ่งแตกต่างกันไปตามชิป SoC ที่ใช้ เช่น ESP32, ESP32-S2, ESP32-S3 และ ESP32-C3

# Install tools for all supported targets:
#  all = (esp32 esp32s2 esp32c3, esp32s3)
$ export IDF_GITHUB_ASSETS="dl.espressif.com/github_assets"
$ ./install.sh all

รายการไฟล์ที่จะต้องมีการดาวน์โหลดมาเพื่อใช้เป็นเครื่องมือสำหรับ ESP-IDF (v5.0) และได้ติดตั้งไว้ใน ~/.espressif/tools) มีตัวอย่างดังนี้

  • xtensa-esp32-elf-gcc8_4_0-esp-2021r2-patch3-linux-amd64.tar.gz
  • xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-patch3-linux-amd64.tar.gz
  • xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-linux-amd64.tar.gz
  • riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch3-linux-amd64.tar.gz
  • binutils-esp32ulp-linux-amd64-2.28.51-esp-20191205.tar.gz
  • binutils-esp32s2ulp-linux-amd64-2.28.51-esp-20191205.tar.gz
  • openocd-esp32-linux-amd64-0.11.0-esp32-20211220.tar.gz

ทุกครั้งที่จะใช้งาน ESP-IDF (เช่น การทำคำสั่ง idf.py) จะต้องมีการทำคำสั่งต่อไปนี้ก่อน เพื่อให้สามารถเรียกใช้คำสั่งต่าง ๆ ของ ESP-IDF Tools ได้

# Set up the environment variables for ESP-IDF tools
$ . $HOME/esp/esp-idf/export.sh

ลองทำคำสั่ง idf.py เพื่อตรวจสอบเวอร์ชันของ ESP-IDF

$ idf.py --version

 

ในกรณีที่ต้องการติดตั้งและใช้งาน ESP-IDF มากกว่าหนึ่งเวอร์ชัน ให้ตั้งชื่อไดเรกทรอรีย่อยตามเวอร์ชันที่ใช้งาน เช่น มีเวอร์ชัน v4.4.1 และ v5.0 ในตัวอย่างนี้ ดังนั้นภายในไดเรกทอรี ~/esp จะมีไดเรกทอรีดังนี้

~/esp/esp-idf-v5.0
~/esp/esp-idf-v4.4.1

แล้วสร้าง Soft link (เหมือนการใช้ Shortcut) โดยใช้ชื่อ esp-idf เพื่อระบุว่า จะเลือกใช้เวอร์ชันใด เช่น

$ ln -s ./esp-idf-v4.4.1 esp-idf

ตัวอย่างขั้นตอนการติดตั้ง ESP-IDF v4.4.1 และตั้งค่าเพื่อเรียกใช้งาน

# change the current working directory to ~/esp
$ cd ~/esp
# clone the ESP-IDF v4.4.1 (not the master branch)
$ git clone -b v4.4.1 --recursive https://github.com/espressif/esp-idf.git
# rename the 'esp-idf' subdirectory to 'esp-idf-v4.4.1'
$ mv ./esp-idf ./esp-idf-v4.4.1
# create a soft link named 'esp-idf'
$ ln -s ./esp-idf-v4.4.1 esp-idf
# install Espressif tools and other software (Python3 packages)
$ export IDF_GITHUB_ASSETS="dl.espressif.com/github_assets"
$ cd ~/esp/esp-idf
$ ./install.sh all

ลองใช้คำสั่ง idf.py ซึ่งเป็นของเวอร์ชัน ESP-IDF v4.4.1

# export the ESP-IDF path for 'idf.py' 
$ . $HOME/esp/esp-idf/export.sh
# show the ESP-IDF version (=> ESP-IDF v4.4.1)
$ idf.py --version

หรือถ้าจะเปลี่ยนจากเวอร์ชัน v4.4.1 เป็น v4.4.3 ซึ่งใหม่กว่า ก็ให้ทำคำสั่งในลักษณะเดียวกัน

 


การสร้างโปรเจกต์จากตัวอย่างสำหรับ ESP32#

ถัดไปเป็นการทดลองคอมไพล์โปรเจกต์ตัวอย่างที่มีชื่อว่า hello_world ซึ่งมีอยู่ใน ~/esp/esp-idf/examples

# make a new directory '~/esp/projects'
$ mkdir -p ~/esp/projects && cd ~/esp/projects 
# copy the hello_world project example to '~/esp/projects'
$ cp -r $IDF_PATH/examples/get-started/hello_world .
# change working directory to './hello_world'
$ cd ./hello_world

แสดงรายการตัวเลือกสำหรับชิปเป้าหมาย และให้เลือกชิปเป้าหมายเป็น ESP32 สำหรับตัวอย่างนี้

# list all avaialble targets
$ idf.py --list-targets
# set the target such as esp32 | esp32s2 | esp32s3 | esp32c3
# choose esp32 as the build target
$ idf.py set-target esp32

รูป: ตัวอย่างการทำคำสั่ง idf.py --list-targets และ idf.py set-target esp32

 

ก่อนทำขั้นตอน Build Target และหากต้องการแก้ไขการตั้งค่าสำหรับโปรเจกต์ (Project configuration / customization) เช่น

  • การกำหนดขนาดของ Flash Size และการแบ่ง Flash Partitions
  • การกำหนดความถี่ของซีพียูในการทำงาน (Component config -> ESP32-specific -> CPU Frequency)
  • การกำหนดค่า FreeRTOS Tick Rate (Component config -> ESP32-specific -> FreeRTOS)

ก็ให้ทำคำสั่งต่อไปนี้ โดยจะเข้าสู่เมนูแบบกราฟิกที่เรียกว่า menuconfig

# start menuconfig
$ idf.py menuconfig

เมื่อมีการแก้ไขแล้วให้บันทึกการเปลี่ยนแปลง ซึ่งจะถูกเก็บลงในไฟล์ ./sdkconfig ในไดเรกทอรีของโปรเจกต์

รูป: รายการตัวเลือกใน menuconfig

รูป: ตัวอย่างการตั้งค่าความถี่สำหรับซีพียู (CPU Frequency) สูงสุด 240 MHz สำหรับ ESP32

รูป: ตัวอย่างการทำคำสั่ง idf.py menuconfig และ idf.py build

# build the target
$ idf.py build

ตัวอย่างการทำคำสั่ง tree เพื่อแสดงรายการไฟล์ภายในไดเรกทอรีของโปรเจกต์

$ tree -L 2
.
├── CMakeLists.txt
├── README.md
├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── app-flash_args
│   ├── bootloader
│   ├── bootloader-flash_args
│   ├── bootloader-prefix
│   ├── build.ninja
│   ├── cmake_install.cmake
│   ├── compile_commands.json
│   ├── config
│   ├── config.env
│   ├── esp-idf
│   ├── flash_app_args
│   ├── flash_args
│   ├── flash_args.in
│   ├── flash_bootloader_args
│   ├── flash_project_args
│   ├── flasher_args.json
│   ├── hello_world.bin
│   ├── hello_world.elf
│   ├── hello_world.map
│   ├── kconfigs.in
│   ├── kconfigs_projbuild.in
│   ├── ldgen_libraries
│   ├── ldgen_libraries.in
│   ├── partition-table-flash_args
│   ├── partition_table
│   ├── project_description.json
│   ├── project_elf_src_esp32.c
│   ├── rules.ninja
│   └── x509_crt_bundle.S
├── example_test.py
├── main
│   ├── CMakeLists.txt
│   └── hello_world_main.c
├── sdkconfig
├── sdkconfig.ci
└── sdkconfig.old

8 directories, 33 files

หากใช้ระบบปฏิบัติการ Linux เช่น Ubuntu ตามปรกติ (ไม่ได้ใช้ผ่าน WSL ใน Windows) ให้ทำคำสั่งต่อไปนี้ เพื่อทำขั้นตอน ESP32 Flashing (เขียนไฟล์ .bin ไปยังหน่วยความจำแฟลชบนบอร์ด ESP32) และจะต้องระบุพอร์ตที่เชื่อมต่อกับบอร์ด ESP32 เช่น /dev/ttyUSB0

$ idf.py -p /dev/ttyUSB0 flash

หากมีปัญหาในการเขียนข้อมูลไปยังพอร์ตดังกล่าว ให้ทำคำสั่งดังนี้

## add the current user account to the 'dialout' group
$ sudo usermod -a -G dialout "$USER"
# show all groups the current user belongs to
$ id -Gn | grep dialout

แต่ถ้าใช้งาน WSL2 Ubuntu จะมองไม่เห็นพอร์ตอย่างเช่น /dev/ttyUSB0 เหมือนใน Linux ทั่วไป และให้ติดตั้ง idfx โดยเก็บไว้ที่ $HOME/.local/bin ดังนี้

# create a new path (if not exists)
$ mkdir -p $HOME/.local/bin
# install idfx - a tool for flashing ESP32 if using ESP-IDF on WSL
$ wget https://raw.githubusercontent.com/abobija/idfx/main/idfx \
  -O $HOME/.local/bin/idfx && chmod u+x $HOME/.local/bin/idfx
$ source ~/.profile

ถ้าต้องการจะทำขั้นตอน ESP32 Flashing โดยใช้คำสั่ง idfx ให้เชื่อมต่อบอร์ด ESP32 กับคอมพิวเตอร์ของผู้ใช้ผ่านทาง USB และจะต้องระบุชื่อของพอร์ตอนุกรมที่มองเห็นได้ในระบบ Windows

$ idfx flash <COM port>

รูป: ตัวอย่างการทำคำสั่ง idfx flash COM10

หากต้องการจะรับข้อความจากพอร์ตอนุกรมมจากบอร์ด ESP32 ให้ทำคำสั่ง idfx ตามตัวอย่างดังนี้

# start the serial monitor (press Ctrl-] to stop the monitor)
$ idfx monitor <COM port>

 

ข้อสังเกต:

  • เนื่องจาก ESP-IDF ตั้งแต่เวอร์ชัน 4.0 เป็นต้นมา ได้เลือกใช้ CMake เป็นตัวจัดการสำหรับขั้นตอนการคอมไพล์โค้ดในโปรเจกต์ ดังนั้นก็สามารถนำไปใช้กับ VS Code IDE ซึ่งจะต้องมีการติดตั้ง Extensions เช่น C/C++ Extension และ CMake Tools Extension เป็นต้น ซึ่งจะช่วยให้ผู้ใช้สามารถเขียนโค้ดและคอมไพล์โค้ดในโปรเจกต์ได้ยิ่งง่ายขึ้น
  • จากรูปตัวอย่างการใช้งาน VS Code IDE (ทำคำสั่ง code . ใน Bash Shell ภายในไดเรกทอรีของโปรเจกต์) จะเห็นได้ว่า เป็นการใช้งานแบบ Remote Connection กล่าวคือ VS Code IDE ทำงานเป็น Windows App แต่เชื่อมต่อไปยัง VS Code Server ที่รันอยู่ภายใต้ WSL2 / Ubuntu Linux ในเครื่องคอมพิวเตอร์เดียวกันของผู้ใช้

รูป: ตัวอย่างการเปิดไดเรกทอรีของโปรเจกต์เพื่อเขียนโค้ดใน VS Code IDE (ใช้งานผ่าน VS Code Server)

 


ให้ทำขั้นตอนตามลำดับดังนี้

1) สร้างโปรเจกต์ใหม่ที่มีชื่อว่า led_blink

$ cd ~/esp/projects/
$ idf.py create-project "led_blink"
$ cd ./led_blink

เมื่อสร้างโปรเจกต์แล้ว ในไดเรกทอรี led_blink มีโครงสร้างไฟล์ใหม่ดังนี้

$ tree -L 2
.
├── CMakeLists.txt
└── main
    ├── CMakeLists.txt
    └── led_blink.c

1 directory, 3 files

2) แก้ไขโค้ดในไฟล์ main/led_blink.c ตามตัวอย่างดังนี้

#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_system.h"
#include "esp_chip_info.h"
#include "esp_spi_flash.h"

#define LED_GPIO  (2) // onboard LED

void task_entry( void* pvParameters ) {
  int state = 0;
  gpio_reset_pin( LED_GPIO ); // reset pin to GPIO function
  gpio_set_direction( LED_GPIO, GPIO_MODE_OUTPUT ); // output direction

  for (;;) {
    gpio_set_level( LED_GPIO, state = !state );
    printf( "LED: %d, ticks: %d\n", state, xTaskGetTickCount() );
    fflush( stdout );
    vTaskDelay( 1000 / portTICK_PERIOD_MS );
  }
}

void app_main(void) {
  esp_chip_info_t chip_info;
  esp_chip_info( &chip_info );
  printf( "This is %s chip with %d CPU core(s), WiFi%s%s\n",
          CONFIG_IDF_TARGET, chip_info.cores,
          (chip_info.features & CHIP_FEATURE_BT)  ? "/BT"  : "",
          (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "" );
  printf( "silicon revision %d\n", chip_info.revision );
  printf( "SPI flash: %d MB (%s)\n",
          spi_flash_get_chip_size()/(1024*1024),
          (chip_info.features & CHIP_FEATURE_EMB_FLASH)
           ? "embedded" : "external");
  printf( "Minimum free heap size: %d bytes\n", 
           esp_get_minimum_free_heap_size() );

  printf( "FreeRTOS Kernel: %s\n", tskKERNEL_VERSION_NUMBER );
  vTaskDelay( 1000 / portTICK_PERIOD_MS );

  // create a new task
  if ( xTaskCreatePinnedToCore( task_entry, "led_task", 
         2048, NULL, 1, NULL, tskNO_AFFINITY ) != pdPASS )
  {
    printf("Cannot create a task!\n");
  }
  printf( "app_main: Core %d\n", xPortGetCoreID() );
  fflush(stdout);
}

3) ทำคำสั่งเพื่อเลือกชิปเป้าหมาย กำหนดค่าสำหรับโปรเจกต์ในไฟล์ sdkconfig และทำขั้นตอน Build target

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

4) นำไฟล์เอาต์พุตที่ได้ไปทดสอบกับบอร์ด ESP32

รูป: ตัวอย่างข้อความเอาต์พุตที่ถูกส่งออกมาจากบอร์ด ESP ทาง Serial

หากต้องการแก้ไขโค้ดใน VS Code IDE ก็ทำได้เช่นกัน

รูป: การเปิดโปรเจกต์ใน VS Code IDE (ทำคำสั่ง code . ในไดเรกทอรีของโปรเจกต์ led_blink) เพื่อลองแก้ไขโค้ดและทำขั้นตอน Build Target

 


แหล่งข้อมูลอ้างอิงและศึกษาเพิ่มเติม#


กล่าวสรุป#

บทความนี้นำเสนอขั้นตอนการติดตั้งและใช้งาน ESP-IDF v5.0 เพื่อใช้งานร่วมกับระบบปฏิบัติการ Ubuntu 22.04 LTS โดยใช้งานผ่าน WSL 2 (Windows Subsystem for Linux version 2) ในเครื่องคอมพิวเตอร์ที่มีระบบปฏิบัติการ Windows 10 (64-bit) และได้ทดลองสร้างโปรเจกต์ที่มีตัวอย่างโค้ดภาษา C/C++ สำหรับนำไปทดสอบการทำงานของบอร์ด ESP32 ในเบื้องต้น


This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Created: 2022-02-23 | Last Updated: 2023-01-27