Cài ESP-IDF trên Windows và dự án đầu tiên: idf.py, app_main, menuconfig, nạp và xem nhật ký

Cài ESP-IDF trên Windows bằng bộ cài hoặc tiện ích VS Code, cấu trúc dự án, các lệnh idf.py, dự án đầu tiên với app_main và ESP_LOGI, tệp nạp và địa chỉ, so với Arduino.

ESP-IDF là bộ công cụ lập trình chính thức của Espressif cho ESP32. Gói esp32 của Arduino thực ra được dựng trên ESP-IDF, nên mọi thứ chạy trong Arduino đều có gốc ở đây. Dùng ESP-IDF trực tiếp giúp cấu hình được mọi chi tiết của chip (bộ nhớ, Wi-Fi, bảo mật, tiết kiệm điện), dùng được tính năng mới ngay khi ra mắt, và đọc được tài liệu, ví dụ của hãng mà không phải "dịch" sang Arduino. Bài này hướng dẫn cài ESP-IDF trên Windows, cấu trúc một dự án, các lệnh idf.py hay dùng, và dự án đầu tiên: in thông tin chip, nháy đèn.

1. Cài ESP-IDF trên Windows

Có hai cách, chọn một:

  • Bộ cài cho Windows (ESP-IDF Tools Installer) tải từ trang tài liệu của Espressif: chọn bản ổn định mới nhất của nhánh 5.x; bộ cài tự cài Python, Git, trình biên dịch và tạo lối tắt ESP-IDF Command Prompt (hoặc PowerShell).
  • Tiện ích ESP-IDF cho VS Code: cài tiện ích, chạy trình cài đặt có hướng dẫn trong VS Code; tiện ích có sẵn nút build, flash, monitor và menuconfig.

Lưu ý quan trọng trên máy Windows dùng tiếng Việt: đặt thư mục cài ESP-IDF và thư mục dự án ở đường dẫn ngắn, không dấu cách, không dấu tiếng Việt, ví dụ C:\esp\idf_den_nhay. Đường dẫn kiểu C:\Users\Tên\Tài liệu\... là nguyên nhân rất hay gặp của lỗi biên dịch khó hiểu.

2. Cấu trúc dự án và các lệnh idf.py

Cây thư mục IDF_DEN_NHAY gồm CMakeLists.txt, thư mục main có CMakeLists.txt và main.c, sdkconfig, build; năm lệnh idf.py create-project, set-target esp32, menuconfig, build, flash monitor
Cấu trúc tối thiểu của dự án trong bài và năm lệnh hay dùng nhất (hình minh họa).

Một dự án ESP-IDF gồm tệp CMakeLists.txt ở gốc (ba dòng, đặt tên dự án) và ít nhất một thành phần main có CMakeLists.txt riêng khai báo các tệp mã nguồn:

# PYWORLD.VN - Tệp CMake gốc của dự án ESP-IDF: ba dòng này gần như giống hệt ở mọi dự án
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(idf_den_nhay)
# PYWORLD.VN - Thành phần "main": khai báo các tệp mã nguồn và thư mục chứa tệp .h
idf_component_register(SRCS "main.c"
                       INCLUDE_DIRS ".")

Các lệnh gõ trong ESP-IDF Command Prompt, tại thư mục dự án:

  • idf.py set-target esp32: chọn dòng chip (esp32, esp32s3, esp32c3, esp32c6…). Chạy một lần khi tạo dự án hoặc khi đổi chip.
  • idf.py menuconfig: mở trình cấu hình dạng chữ, đổi dung lượng flash, mức nhật ký, Wi-Fi, FreeRTOS… Kết quả lưu vào tệp sdkconfig.
  • idf.py build: biên dịch. Lần đầu mất vài phút vì biên dịch toàn bộ các thành phần của ESP-IDF.
  • idf.py -p COM5 flash monitor: nạp qua cổng COM5 rồi mở cửa sổ nhật ký; thoát bằng Ctrl + ].

3. Dự án đầu tiên

Khác với Arduino, chương trình ESP-IDF không có setup() và loop(): mọi thứ bắt đầu ở hàm app_main(), và bản thân hàm này chạy trong một task FreeRTOS. Muốn lặp mãi thì tự viết vòng lặp, và nhớ vTaskDelay() để nhường CPU.

// PYWORLD.VN - Dự án ESP-IDF đầu tiên: in thông tin chip rồi nháy đèn GPIO2 mỗi 500 ms, ghi nhật ký bằng ESP_LOGI
// Không có setup()/loop(): chương trình bắt đầu ở app_main(), bản thân app_main là một task FreeRTOS
// Biên dịch và nạp bằng: idf.py set-target esp32, idf.py build, idf.py -p COMx flash monitor

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "esp_chip_info.h"
#include "esp_flash.h"

#define CHAN_DEN GPIO_NUM_2

static const char *TAG = "DEN";          // nhãn đứng đầu mỗi dòng nhật ký

void app_main(void)
{
    esp_chip_info_t chip;
    esp_chip_info(&chip);
    uint32_t dungLuongFlash = 0;
    esp_flash_get_size(NULL, &dungLuongFlash);
    ESP_LOGI(TAG, "Chip %s, %d nhan, flash %lu MB", CONFIG_IDF_TARGET, chip.cores, (unsigned long)(dungLuongFlash >> 20));

    gpio_reset_pin(CHAN_DEN);            // đưa chân về trạng thái mặc định rồi đặt làm ngõ ra
    gpio_set_direction(CHAN_DEN, GPIO_MODE_OUTPUT);

    int muc = 0;
    for (int lan = 1;; lan++) {
        muc = !muc;
        gpio_set_level(CHAN_DEN, muc);
        ESP_LOGI(TAG, "Den %s, lan %d", muc ? "bat" : "tat", lan);
        vTaskDelay(pdMS_TO_TICKS(500));  // nhường CPU 500 ms cho task khác
    }
}
  • ESP_LOGI(TAG, …) in một dòng nhật ký mức thông tin, có thời gian và nhãn; tương tự có ESP_LOGW (cảnh báo), ESP_LOGE (lỗi). Mức nào được in ra chỉnh trong menuconfig.
  • gpio_reset_pin(), gpio_set_direction(), gpio_set_level() thay cho pinMode(), digitalWrite() của Arduino.
  • CONFIG_IDF_TARGET là hằng do set-target sinh ra, chứa tên chip đang biên dịch.

4. Lệnh flash nạp những gì

Thanh bộ nhớ flash: bootloader.bin nạp ở 0x1000, partition-table.bin ở 0x8000, vùng nvs và phy, idf_den_nhay.bin ở 0x10000
Ba tệp nhị phân và địa chỉ nạp với bảng phân vùng mặc định của ESP-IDF cho ESP32 (hình minh họa).

idf.py build tạo ba tệp: bootloader, bảng phân vùng và chương trình; idf.py flash nạp mỗi tệp vào đúng địa chỉ. Bảng phân vùng mặc định của ESP-IDF chỉ có một ô ứng dụng 1 MB, khác bảng mặc định của Arduino; đổi trong menuconfig (mục Partition Table) khi cần OTA hoặc hệ thống file.

5. Kết quả mong đợi

Cửa sổ idf.py monitor: I (312) DEN: Chip esp32, 2 nhan, flash 4 MB; sau đó các dòng Den bat, Den tat, lan 1 tới lan 6 cách nhau 500 ms
Mỗi dòng: mức (I = thông tin), thời gian từ lúc khởi động (ms), nhãn, nội dung (mốc thời gian là ví dụ).

Trước các dòng của chương trình, monitor còn in nhật ký khởi động của bootloader và hệ thống (phiên bản ESP-IDF, bảng phân vùng, bộ nhớ): đọc các dòng này giúp biết chip khởi động thế nào khi gặp lỗi.

6. Khi nào dùng Arduino, khi nào dùng ESP-IDF

Arduino (gói esp32)ESP-IDF
Bắt đầuRất nhanh, nhiều ví dụ, nhiều thư viện cảm biếnCài đặt lâu hơn, phải hiểu CMake, menuconfig
Cấu hình chipTheo bộ cấu hình dựng sẵnĐổi được mọi tùy chọn trong menuconfig
Tính năng mới của chipCó sau một thời gianCó ngay khi Espressif phát hành
Hợp vớiHọc tập, nguyên mẫu, dự án vừa và nhỏSản phẩm, dự án cần tối ưu điện, bộ nhớ, bảo mật

Hai cách không loại trừ nhau: trong chương trình Arduino vẫn gọi được hầu hết hàm của ESP-IDF (như các bài FreeRTOS, watchdog, bảng phân vùng trong loạt ESP32 nâng cao đã làm), và trong dự án ESP-IDF có thể thêm Arduino làm một thành phần.

7. Xử lý lỗi thường gặp

Hiện tượngNguyên nhân thường gặpCách xử lý
"idf.py is not recognized"Gõ lệnh trong cửa sổ Command Prompt thườngMở ESP-IDF Command Prompt (biến môi trường đã đặt sẵn)
Lỗi CMake khó hiểu, không tìm thấy tệpĐường dẫn có dấu cách hoặc dấu tiếng ViệtChuyển dự án về thư mục kiểu C:\esp\...
Nạp báo "Failed to connect"Sai cổng COM; bo không tự vào chế độ nạpKiểm tra cổng; giữ nút BOOT khi bắt đầu nạp
"Detected size(4096k) larger than the size in the binary image header(2048k)"Cấu hình flash mặc định 2 MBĐổi Flash size thành 4 MB trong menuconfig (Serial flasher config)
Nhật ký ra ký tự lạTốc độ monitor khác cấu hìnhGiữ mặc định 115200; dùng idf.py monitor thay vì phần mềm khác

8. Xem thêm

  • ESP32 DevKit V1 30 chân, 38 chân và dây USB nạp code.
  • Bài PlatformIO trong cùng loạt công cụ: PlatformIO cũng hỗ trợ ESP-IDF (framework = espidf).
  • Các bài FreeRTOS, bảng phân vùng, watchdog trong loạt ESP32 nâng cao: phần lớn kiến thức dùng chung với ESP-IDF.

Tin tức liên quan

Mạch sạc pin 2S, 3S, 4S từ Type-C 5 V: chọn 1A, 2A, 4A, đấu dây và vì sao vẫn cần mạch bảo vệ BMS
Mạch sạc pin 2S, 3S, 4S từ Type-C 5 V: chọn 1A, 2A, 4A, đấu dây và vì sao vẫn cần mạch bảo vệ BMS

Mạch sạc tăng áp từ 5 V lên 8,4, 12,6, 16,8 V cho khối pin 2S, 3S, 4S: chân và cầu hàn, dòng sạc thực tế, nguồn cần dùng, đấu dây với mạch bảo vệ BMS và an toàn khi sạc.

Kiểm tra lỗi truyền dữ liệu: bit chẵn lẻ, checksum và CRC-16 của Modbus
Kiểm tra lỗi truyền dữ liệu: bit chẵn lẻ, checksum và CRC-16 của Modbus

So sánh bốn cách phát hiện lỗi truyền dữ liệu: bit chẵn lẻ, tổng kiểm tra, XOR và CRC. Giải thích từng bước thuật toán CRC-16 của Modbus và chương trình ESP32 cho thấy mã nào phát hiện được lỗi nào.

Đố toán nhanh trên OLED 4 nút với ESP32: trò chơi luyện tính nhẩm cho học sinh
Đố toán nhanh trên OLED 4 nút với ESP32: trò chơi luyện tính nhẩm cho học sinh

Làm máy đố toán nhanh bằng ESP32 và màn hình OLED kèm 4 nút: cộng trừ đến 20, bảng nhân 2–9, 4 đáp án cho 4 nút, đếm câu đúng và thời gian, cách tạo đáp án sai gần đúng.

Hiệu chuẩn load cell tại hiện trường: tải thật, mô phỏng mV/V, thế chỗ, ISO 376 và ASTM E74
Hiệu chuẩn load cell tại hiện trường: tải thật, mô phỏng mV/V, thế chỗ, ISO 376 và ASTM E74

Hiệu chuẩn hệ load cell tại hiện trường: chuỗi đo và nguồn sai số, tải thật so với mô phỏng mV/V, thế chỗ cho cân bồn, lưu ý lắp đặt, so sánh ISO 376 và ASTM E74.

Nhận lệnh giọng nói không cần Internet trên ESP32-S3 bằng ESP_SR: Hi ESP, micro INMP441, đèn, quạt
Nhận lệnh giọng nói không cần Internet trên ESP32-S3 bằng ESP_SR: Hi ESP, micro INMP441, đèn, quạt

Nhận lệnh giọng nói ngay trên ESP32-S3 bằng thư viện ESP_SR có sẵn: từ đánh thức Hi ESP, lệnh tiếng Anh tự viết, micro INMP441, cài đặt phân vùng ESP SR 16M, bật tắt đèn và quạt.

Trò chơi robot và người lập trình trên bảng ô vuông: 3 màn chơi kèm mẫu in
Trò chơi robot và người lập trình trên bảng ô vuông: 3 màn chơi kèm mẫu in

Trò chơi lập trình không cần máy tính cho trẻ 5–8 tuổi: thẻ lệnh tiến, quay, lặp lại trên bảng ô vuông; luật chơi, ba màn có lời giải, mẫu in và biến thể nâng cao.

1-Wire là gì: khe thời gian, mã ROM và cách đọc DS18B20 bằng ESP32
1-Wire là gì: khe thời gian, mã ROM và cách đọc DS18B20 bằng ESP32

Giải thích giao tiếp 1-Wire: một dây dữ liệu, điện trở kéo lên, bốn kiểu khe thời gian, mã ROM 64 bit và CRC. Kèm hai chương trình ESP32 tự viết giao thức để đọc mã ROM và nhiệt độ DS18B20.

Học lập trình từ nhỏ giúp trẻ phát triển tư duy thế nào? Đọc đúng bằng chứng từ các nghiên cứu
Học lập trình từ nhỏ giúp trẻ phát triển tư duy thế nào? Đọc đúng bằng chứng từ các nghiên cứu

Tóm tắt bằng chứng về việc học lập trình từ nhỏ giúp trẻ phát triển tư duy: tổng hợp 105 nghiên cứu, thí nghiệm với trẻ mẫu giáo và lớp 1, cách đọc con số và giới hạn.


Bình luận
Đã thêm vào giỏ hàng