Kỳ Vọng vs Thực Tế
Trước khi đi vào kỹ thuật, cần nói thẳng về giới hạn:
ESP32-S3 KHÔNG thể:
- Chạy mô hình YOLO detect đối tượng real-time ở 30 fps
- Chạy LLM, GPT, hoặc bất kỳ mô hình ngôn ngữ nào
- Thay thế GPU hoặc NPU chuyên dụng
- Làm Computer Vision phức tạp từ camera HD
ESP32-S3 CÓ THỂ:
- Wake word detection (ví dụ: “Hey Siri” style, nhưng model nhỏ)
- Phân loại cử chỉ/activity đơn giản từ accelerometer
- Phát hiện anomaly trong chuỗi cảm biến
- FFT và signal processing cho audio/vibration
- Keyword spotting trong audio 16 KHz
- Image classification với model nhỏ (< 100 KB)
Hiểu đúng giới hạn giúp bạn chọn đúng bài toán cho ESP32-S3.
SIMD: Vector Instructions Trên Xtensa LX7
Xtensa LX7 trong ESP32-S3 có PIE (Processor Instruction Extensions) — tập lệnh SIMD 128-bit. Thay vì xử lý 1 float mỗi lệnh, SIMD xử lý 4 float (hoặc 8 int16) cùng lúc.
Không SIMD: for (i=0; i<N; i++) result[i] = a[i] * b[i];
→ N lần nhân, N chu kỳ
Với SIMD: Xử lý 4 phần tử/lệnh → N/4 chu kỳ
→ ~4× nhanh hơn cho dot product
Bạn không cần viết assembly để dùng SIMD — Espressif đã wrap vào 2 thư viện:
ESP-DSP: Signal Processing
ESP-DSP là thư viện tối ưu cho Xtensa LX7, dùng SIMD bên dưới:
#include "esp_dsp.h"
// FFT 512 điểm trên 16000 Hz audio
const int N = 512;
__attribute__((aligned(16))) float fft_input[N * 2]; // Complex: real + imag interleaved
__attribute__((aligned(16))) float fft_output[N];
void performFFT(int16_t* audioSamples) {
// Convert int16 samples → float complex (imag = 0)
for (int i = 0; i < N; i++) {
fft_input[i * 2] = audioSamples[i] / 32768.0f; // Real part
fft_input[i * 2 + 1] = 0.0f; // Imaginary part
}
// FFT forward transform
dsps_fft2r_fc32(fft_input, N);
// Bit-reverse
dsps_bit_rev_fc32(fft_input, N);
// Convert complex → magnitude
dsps_cplx2reC_fc32(fft_input, N);
// Tính magnitude của từng frequency bin
for (int i = 0; i < N / 2; i++) {
fft_output[i] = sqrtf(fft_input[i * 2] * fft_input[i * 2] +
fft_input[i * 2 + 1] * fft_input[i * 2 + 1]);
}
// fft_output[i] = magnitude tại frequency (i * 16000 / N) Hz
// Ví dụ: fft_output[8] = magnitude tại 250 Hz
}
Dot product — core operation của neural network:
// Dot product tối ưu SIMD: a[] . b[] với N phần tử
float dotProduct(float* a, float* b, int N) {
float result = 0.0f;
dsps_dotprod_f32(a, b, &result, N); // SIMD-optimized
return result;
}
Benchmark thực tế ESP32-S3 vs ESP32 (LX6) cho FFT 512:
- ESP32 (LX6): ~4.5 ms
- ESP32-S3 (LX7, không SIMD): ~2.8 ms
- ESP32-S3 (LX7 + dsps_fft2r): ~0.6 ms — 7.5× nhanh hơn!
ESP-NN: Neural Network Inference
ESP-NN cung cấp các operator tối ưu SIMD cho neural network inference — kernel của TFLite Micro dùng ESP-NN bên dưới khi chạy trên ESP32-S3.
#include "esp_nn.h"
// Depthwise convolution (quan trọng trong MobileNet, EfficientNet)
esp_nn_depthwise_conv_s8(
input_data, // int8 input
input_dims, // {batch, height, width, channels}
filter_data, // int8 weights
filter_dims,
bias_data, // int32 bias
output_data, // int8 output
output_dims,
padding,
stride,
dilation,
activation // RELU, RELU6, NONE
);
Thực tế bạn không gọi ESP-NN trực tiếp — TFLite Micro tự detect và dùng khi chạy trên ESP32-S3.
TFLite Micro: Chạy Model AI
TensorFlow Lite for Microcontrollers là cách phổ biến nhất để chạy model AI trên ESP32-S3:
#include "tensorflow/lite/micro/all_ops_resolver.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/schema/schema_generated.h"
// Model data (array từ file .tflite đã convert)
extern const uint8_t model_data[];
extern const int model_data_len;
// Arena memory cho inference (trong PSRAM nếu model lớn)
const int kArenaSize = 128 * 1024; // 128 KB
uint8_t* arena = (uint8_t*)ps_malloc(kArenaSize);
tflite::AllOpsResolver resolver;
const tflite::Model* model;
tflite::MicroInterpreter* interpreter;
TfLiteTensor* input;
TfLiteTensor* output;
void setupAI() {
model = tflite::GetModel(model_data);
static tflite::MicroInterpreter static_interpreter(
model, resolver, arena, kArenaSize);
interpreter = &static_interpreter;
interpreter->AllocateTensors();
input = interpreter->input(0);
output = interpreter->output(0);
Serial.printf("Input shape: [%d, %d, %d, %d]\n",
input->dims->data[0], input->dims->data[1],
input->dims->data[2], input->dims->data[3]);
}
void runInference(float* inputData, int inputSize) {
// Copy data vào input tensor
memcpy(input->data.f, inputData, inputSize * sizeof(float));
// Chạy inference
uint32_t t0 = millis();
interpreter->Invoke();
uint32_t inferenceMs = millis() - t0;
// Đọc kết quả
int numOutputs = output->dims->data[1];
Serial.printf("Inference: %lu ms, outputs: %d\n", inferenceMs, numOutputs);
for (int i = 0; i < numOutputs; i++) {
Serial.printf(" Class %d: %.2f\n", i, output->data.f[i]);
}
}
Model Size Guide
| Model | Size | RAM cần | Use Case | Tốc độ |
|---|---|---|---|---|
| MobileNetV1 0.25 (96×96) | ~100 KB | ~200 KB | Phân loại ảnh đơn giản | ~150 ms |
| Keyword Spotting LSTM | ~20 KB | ~50 KB | Wake word 1–5 từ | ~30 ms |
| Gesture from IMU | ~8 KB | ~20 KB | 5–10 cử chỉ | ~5 ms |
| Anomaly Detection | ~4 KB | ~10 KB | Vibration, sensor | ~2 ms |
| Digit Recognition | ~16 KB | ~40 KB | 28×28 greyscale | ~20 ms |
Quy tắc thực tế: Model phải đủ nhỏ để fit vào PSRAM + chạy trong vài chục ms. Model > 2 MB hoặc cần > 10 ms thường không thực tế cho embedded real-time.
Ví Dụ Thực Tế: Phát Hiện Anomaly Cảm Biến
Autoencoder nhỏ phát hiện anomaly trong chuỗi sensor — không cần label data:
// Input: 10 readings gần nhất từ accelerometer
// Output: reconstruction error — cao = anomaly
float sensorBuffer[10];
int bufferIndex = 0;
void updateSensorBuffer(float newReading) {
sensorBuffer[bufferIndex] = newReading;
bufferIndex = (bufferIndex + 1) % 10;
if (bufferIndex == 0) { // Buffer đầy → chạy inference
float error = runAutoencoderInference(sensorBuffer);
if (error > ANOMALY_THRESHOLD) {
Serial.printf("ANOMALY detected! Error: %.3f\n", error);
// Gửi alert, log event, v.v.
}
}
}
Tổng Kết
| Công Cụ | Dùng Cho | Điểm Mạnh |
|---|---|---|
| ESP-DSP | FFT, filter, dot product | SIMD tối ưu, tích hợp ESP-IDF |
| ESP-NN | Neural net operators | Kernel của TFLite, không gọi trực tiếp |
| TFLite Micro | Inference model .tflite | Phổ biến, nhiều model pretrained |
| Edge Impulse | Model training + deployment | Platform tích hợp, xuất code |
Bài tiếp theo: Bài 9 — Project Thực Tế: Camera + LCD + Dual-Core Trên ESP32-S3 — Kết hợp camera OV2640, LCD ST7789, Dual-Core FreeRTOS và PSRAM vào một project hoàn chỉnh.
📚 Series: Sức Mạnh ESP32-S3 Dual-Core
⬅️ Bài trước: S3 Dual-Core – Bài 7: USB OTG – Device, Host, CDC, HID


