Bỏ qua, đến nội dung chính
Nastrotek
Bài viếtFirmwareMới

TinyML trên ESP32: Chạy AI ngay tại thiết bị

Cách mình chạy một model nhận diện người ngay trên ESP32 bằng TensorFlow Lite Micro và ESP-NN, từ giới hạn bộ nhớ đến cách thử ví dụ person_detection.

Chia sẻ

LinkedInFacebookX
Camera-equipped ESP32-S3 prototype running person detection locally on a workbench

Nếu mới nghe đến TinyML, bạn có thể hình dung đơn giản thế này: một model nhỏ chạy thẳng trên vi điều khiển, tự đưa ra kết quả mà không phải gửi dữ liệu lên server. Với ESP32, đây đã là một bài thử khá gần gũi: Espressif có sẵn component, model mẫu và project để mình build trực tiếp bằng ESP-IDF.

Trong bài này, mình dùng person_detection làm ví dụ. Camera chụp một khung hình, ESP32 trả về hai điểm số personno_person, và toàn bộ quá trình diễn ra tại thiết bị.

Bộ thử nghiệm TinyML gồm board ESP32-S3, camera và màn hình trạng thái trên bàn làm việc.

Một demo TinyML đúng nghĩa: camera lấy ảnh, ESP32-S3 tự chạy model và trả kết quả ngay tại bàn — không cần gửi khung hình lên server.

TinyML hữu ích khi nào?

Mình thường nghĩ đến TinyML khi thiết bị chỉ cần nhận ra một tín hiệu hẹp nhưng rõ ràng: có người trong khung hình, nghe thấy một từ khóa, hoặc phát hiện một trạng thái bất thường từ cảm biến.

Cách làm này có ba lợi ích dễ thấy:

  • Phản hồi nhanh: không phải chờ một vòng gửi dữ liệu lên server rồi nhận kết quả về.
  • Vẫn chạy khi mất mạng: hợp với cảm biến dùng pin hoặc thiết bị ở nơi kết nối chập chờn.
  • Giữ dữ liệu riêng tư hơn: ảnh và âm thanh thô không cần rời khỏi thiết bị.

Đổi lại, model phải nhỏ và bài toán phải gọn. person_detection chỉ trả lời “có người hay không”, chứ không nhận diện người đó là ai. TinyML cũng không thay thế cloud AI; nó phù hợp hơn với vai trò của một bộ lọc hoặc trigger luôn sẵn sàng.

Sơ đồ bốn bước xử lý TinyML trên ESP32, từ camera đến kết quả cục bộ.

Mỗi khung hình đi qua tiền xử lý, model TFLM và ESP-NN rồi mới tạo ra kết quả. Dữ liệu ảnh thô vẫn nằm trên thiết bị.

Phần khó nhất thường là bộ nhớ

ESP32 có SRAM tính bằng hàng trăm kilobyte, không phải gigabyte. Vì vậy, model thường được quantize về int8 để giảm dung lượng flash, RAM trung gian và lượng phép tính khi inference.

TensorFlow Lite Micro (TFLM) dùng một vùng nhớ được cấp trước gọi là tensor arena. Model, tensor đầu vào/đầu ra và các tensor trung gian phải vừa trong vùng này. Arena quá nhỏ thì khởi tạo interpreter thất bại; đặt quá lớn lại lấy mất SRAM của frame buffer camera, Wi-Fi và phần còn lại của firmware.

Model person detection trong ví dụ của Espressif khoảng 250 KB và đã được quantize int8. Con số đó mới là kích thước model, chưa phải là toàn bộ RAM mà ứng dụng cần. Khi ước lượng phần cứng, bạn vẫn phải cộng thêm tensor arena, frame buffer, stack của task và các component khác.

Bộ công cụ: TFLM + ESP-NN

esp-tflite-micro đóng gói TFLM cho ESP-IDF và tích hợp ESP-NN. ESP-NN cung cấp các kernel tối ưu cho convolution, depthwise convolution và những phép toán neural network phổ biến; trên ESP32-S3 và ESP32-P4, thư viện tự chọn phần cài đặt assembly tối ưu.

README hiện tại của project ghi rằng hỗ trợ ESP-IDF từ release/v4.4 trở lên; manifest component hiện yêu cầu ESP-IDF >=5.0. Nếu bắt đầu project mới, mình sẽ chọn một bản ESP-IDF 5.x ổn định thay vì bám vào mức tối thiểu.

Thêm component vào project có sẵn:

idf.py add-dependency "esp-tflite-micro"

Hoặc lấy thẳng ví dụ gần nhất:

idf.py create-project-from-example "esp-tflite-micro:person_detection"

Repo còn có hello_world để kiểm tra toolchain và micro_speech để thử nhận từ khóa từ âm thanh.

Chạy thử person_detection

Ví dụ hỗ trợ các board như ESP32-DevKitC kèm camera, ESP-EYE, ESP32-S3-EYE, ESP32-S3-Korvo-2 và ESP32-S2-Kaluga. Kaluga chỉ đạt khoảng 1–2 FPS theo tài liệu của ví dụ, nên phù hợp để thử ý tưởng hơn là làm mốc hiệu năng.

Nếu chưa có camera, bạn vẫn có thể kiểm tra pipeline bằng 10 ảnh nhúng sẵn. Bật chế độ CLI trong main/esp_main.h:

#define CLI_ONLY_INFERENCE 1

Sau đó build, flash và mở monitor:

idf.py set-target esp32s3
idf.py build
idf.py --port /dev/ttyUSB0 flash monitor

Trên Windows, thay /dev/ttyUSB0 bằng cổng COMx của board. Trong monitor, chạy:

detect_image 0

Bạn có thể đổi số từ 0 đến 9. Log sẽ in ra điểm personno_person. Mình thích làm bước này trước vì nó xác nhận toolchain, model và inference đã ổn; sau đó, nếu camera không chạy, phạm vi tìm lỗi chỉ còn wiring, pin map và driver.

Người làm đang điều chỉnh camera gắn với board ESP32-S3 trong lúc thử person detection.

Mình thường kiểm tra model bằng ảnh mẫu trước, sau đó mới nối camera thật. Cách này giúp tách lỗi model khỏi lỗi dây nối và driver.

Benchmark: Vì sao ESP32-S3 đáng chọn hơn?

Espressif công bố thời gian chạy invoke() của cùng ví dụ khi bật ESP-NN và dùng bộ nhớ internal:

ChipKhông có ESP-NNCó ESP-NN
ESP324084 ms380 ms
ESP32-C33355 ms426 ms
ESP32-S32300 ms54 ms
ESP32-P41395 ms73 ms

Với cùng model, ESP32-S3 chạy nhanh hơn ESP32 thường khoảng bảy lần khi đều bật ESP-NN. Khác biệt lớn không chỉ đến từ xung nhịp; ESP-NN có implementation assembly tối ưu cho S3, còn ESP32 và C3 dùng generic tối ưu.

Nếu camera cần phản hồi vài lần mỗi giây, mình sẽ ưu tiên ESP32-S3. ESP32 thường vẫn đủ cho tác vụ chạy thưa, chẳng hạn vài giây kiểm tra một lần, nhưng nên benchmark trước khi chốt PCB. Số liệu ESP32-P4 cũng cần đọc cùng ghi chú của Espressif rằng phần tối ưu cho chip này vẫn đang được hoàn thiện.

Board ESP32-S3 nối camera và thiết bị đo để kiểm tra độ trễ inference.

Benchmark nên được đo lại trên đúng phần cứng cuối cùng, khi camera, bộ nhớ và các tác vụ khác cùng hoạt động.

Những chỗ mình sẽ kiểm tra trước khi chốt phần cứng

  • Đo tensor arena bằng model thật. Đừng lấy kích thước file .tflite làm ngân sách RAM cuối cùng.
  • Ưu tiên internal RAM cho đường chạy nóng. Nếu tensor hoặc frame buffer phải dùng PSRAM, độ trễ thực tế có thể cao hơn bảng benchmark.
  • **Kiểm tra pin map theo đúng board.Camera chạy trên dev kit chưa có nghĩa là sẽ chạy ngay trên PCB tùy chỉnh.
  • Thử trong vỏ thật và ánh sáng thật. Góc camera, bóng của thành vỏ và khoảng cách đến chủ thể ảnh hưởng trực tiếp đến kết quả.
  • Đo lại khi mọi thứ cùng chạy. Camera, Wi-Fi, màn hình và các task khác có thể thay đổi cả bộ nhớ lẫn độ trễ.

Kết luận

TinyML trên ESP32 không quá xa vời: bạn có thể chạy demo đầu tiên trong một buổi nếu ESP-IDF đã sẵn sàng. Phần cần đầu tư không nằm ở lệnh build, mà ở việc giữ bài toán đủ hẹp, tính đúng ngân sách bộ nhớ và thử trong điều kiện sản phẩm thật.

Nếu bắt đầu từ con số không, mình sẽ chọn ESP32-S3, chạy 10 ảnh mẫu trước, nối camera sau, rồi mới thay model của riêng mình. Trình tự đó tiết kiệm khá nhiều thời gian dò lỗi.

Tài liệu tham khảo

Chia sẻ

LinkedInFacebookX

Tiếp tục khám phá

Đọc tiếp

Bài viết liên quan

Xem thêm trong Bài viết

Nastrotek sử dụng cookie để phân tích truy cập và cá nhân hóa quảng cáo, giúp hiểu cách website được sử dụng. Bạn có thể chấp nhận hoặc từ chối các cookie không thiết yếu.