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.
Nói "Hi ESP" rồi "turn on the light", đèn sáng: không cần Wi-Fi, không gửi âm thanh lên máy chủ nào. ESP32-S3 đủ sức tự nhận từ đánh thức và các câu lệnh giọng nói nhờ thư viện ESP_SR của Espressif, có sẵn trong gói ESP32 cho Arduino IDE. Bài này giải thích cách ESP_SR hoạt động, phần cứng cần có, cách nối micro I2S INMP441, cài đặt Arduino IDE cho đúng phân vùng bộ nhớ, chương trình bật tắt đèn, quạt bằng giọng nói và các lỗi hay gặp.
1. ESP_SR làm được gì
- Từ đánh thức (wake word): mô hình đóng gói sẵn nghe câu "Hi ESP".
- Lệnh giọng nói: tới vài chục câu lệnh do bạn tự viết bằng chữ (tiếng Anh), không phải thu âm huấn luyện.
- Chạy hoàn toàn trên chip: phản hồi nhanh, không phụ thuộc mạng, không lộ âm thanh trong nhà ra ngoài.
Giới hạn: mô hình lệnh có sẵn trong gói là tiếng Anh, từ đánh thức cố định "Hi ESP". Chỉ chạy trên dòng ESP32-S3 (và P4), không chạy trên ESP32 DevKit V1 thường.
2. Phần cứng cần có
- Bo ESP32-S3 có Flash 16 MB và PSRAM (ví dụ loại ghi N16R8). Mô hình giọng nói chiếm vài MB Flash và cần PSRAM khi chạy.
- Micro I2S INMP441 (cách hoạt động của loại micro này có trong bài INMP441 thuộc loạt module).
- Một LED với điện trở 330 Ω, một module relay cho quạt, breadboard, dây cắm.
3. Cách hoạt động

ESP_SR đọc âm thanh 16 kHz từ micro, xử lý đầu vào (lọc ồn), đưa qua mô hình WakeNet để nghe từ đánh thức. Khi nghe thấy, chương trình chuyển sang chế độ nghe lệnh: mô hình MultiNet so tiếng nói với danh sách câu lệnh. Mỗi lần nhận ra một câu, ESP_SR gọi hàm sự kiện của bạn kèm số thứ tự lệnh.

4. Nối dây

Chân L/R của INMP441 nối GND để micro gửi tiếng ở kênh trái. Đặt micro xa quạt, relay và mạch nguồn xung; tiếng ồn làm giảm khả năng nhận lệnh.
5. Cài đặt Arduino IDE

Điều quan trọng nhất là chọn đúng Partition Scheme "ESP SR 16M": khi upload, Arduino IDE tự nạp thêm file mô hình vào phân vùng riêng. Bo dùng PSRAM loại khác (QSPI) thì chọn mục PSRAM tương ứng.
6. Chương trình
Chương trình chỉ dùng thư viện ESP_I2S và ESP_SR có sẵn trong gói ESP32. Danh sách lệnh là các câu tiếng Anh; một lệnh có thể có nhiều cách nói (ví dụ "Turn on the light" và "Light on" cùng là bật đèn).
// PYWORLD.VN - Nhận lệnh giọng nói không cần Internet trên ESP32-S3 bằng thư viện ESP_SR có sẵn trong gói esp32
// PYWORLD.VN - Nói "Hi ESP" để đánh thức, rồi nói lệnh tiếng Anh: "turn on the light", "turn off the fan"...
// PYWORLD.VN - Micro INMP441: SCK GPIO4, WS GPIO5, SD GPIO6, L/R nối GND; LED GPIO10, relay quạt GPIO11
#include <Arduino.h>
#include "ESP_I2S.h"
#include "ESP_SR.h"
const int CHAN_SCK = 4;
const int CHAN_WS = 5;
const int CHAN_SD = 6;
const int CHAN_DEN = 10;
const int CHAN_QUAT = 11;
const bool RELAY_KICH_MUC_THAP = true;
const uint32_t TAN_SO_MAU = 16000; // ESP_SR cần âm thanh 16 kHz, 16 bit
I2SClass i2s;
enum { LENH_BAT_DEN, LENH_TAT_DEN, LENH_BAT_QUAT, LENH_TAT_QUAT };
// Mỗi lệnh có thể có nhiều câu nói khác nhau (tiếng Anh, theo mô hình lệnh đóng gói sẵn)
static const sr_cmd_t DANH_SACH_LENH[] = {
{LENH_BAT_DEN, "Turn on the light"},
{LENH_BAT_DEN, "Light on"},
{LENH_TAT_DEN, "Turn off the light"},
{LENH_TAT_DEN, "Light off"},
{LENH_BAT_QUAT, "Turn on the fan"},
{LENH_BAT_QUAT, "Start fan"},
{LENH_TAT_QUAT, "Turn off the fan"},
{LENH_TAT_QUAT, "Stop fan"},
};
void datQuat(bool bat) {
digitalWrite(CHAN_QUAT, (bat != RELAY_KICH_MUC_THAP) ? HIGH : LOW);
}
void khiNghe(sr_event_t suKien, int maLenh, int maCau) {
switch (suKien) {
case SR_EVENT_WAKEWORD:
Serial.println("Nghe thay 'Hi ESP': cho lenh...");
ESP_SR.setMode(SR_MODE_COMMAND); // micro đơn: chuyển ngay sang nghe lệnh
break;
case SR_EVENT_TIMEOUT:
Serial.println("Het thoi gian cho lenh, quay ve cho tu danh thuc");
ESP_SR.setMode(SR_MODE_WAKEWORD);
break;
case SR_EVENT_COMMAND:
Serial.printf("Lenh %d, cau %d: ", maLenh, maCau);
switch (maLenh) {
case LENH_BAT_DEN: digitalWrite(CHAN_DEN, HIGH); Serial.println("bat den"); break;
case LENH_TAT_DEN: digitalWrite(CHAN_DEN, LOW); Serial.println("tat den"); break;
case LENH_BAT_QUAT: datQuat(true); Serial.println("bat quat"); break;
case LENH_TAT_QUAT: datQuat(false); Serial.println("tat quat"); break;
default: Serial.println("khong ro"); break;
}
ESP_SR.setMode(SR_MODE_COMMAND); // cho nói tiếp lệnh khác trước khi hết thời gian chờ
break;
default:
break;
}
}
void setup() {
Serial.begin(115200);
pinMode(CHAN_DEN, OUTPUT);
digitalWrite(CHAN_DEN, LOW);
pinMode(CHAN_QUAT, OUTPUT);
datQuat(false);
i2s.setTimeout(1000);
i2s.setPins(CHAN_SCK, CHAN_WS, -1, CHAN_SD);
// INMP441 gửi mẫu 24 bit trong khe 32 bit: nhận 32 bit rồi đổi xuống 16 bit cho ESP_SR
i2s.begin(I2S_MODE_STD, TAN_SO_MAU, I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_MONO, I2S_STD_SLOT_LEFT);
i2s.configureRX(TAN_SO_MAU, I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_MONO, I2S_RX_TRANSFORM_32_TO_16);
ESP_SR.onEvent(khiNghe);
ESP_SR.begin(i2s, DANH_SACH_LENH, sizeof(DANH_SACH_LENH) / sizeof(sr_cmd_t), SR_CHANNELS_MONO, SR_MODE_WAKEWORD, "M");
Serial.println("San sang: noi 'Hi ESP'");
}
void loop() {
delay(100); // việc nhận dạng chạy trong tác vụ riêng của ESP_SR
}
- INMP441 gửi mẫu 24 bit trong khe 32 bit;
configureRX(…, I2S_RX_TRANSFORM_32_TO_16)đổi xuống 16 bit đúng định dạng ESP_SR cần. - Sau mỗi lệnh, chương trình gọi lại
setMode(SR_MODE_COMMAND)để có thể nói tiếp lệnh khác mà không phải nói lại "Hi ESP"; im lặng một lúc thì quay về chờ từ đánh thức. - Muốn thêm lệnh: thêm một số vào
enum, thêm câu vàoDANH_SACH_LENHvà một nhánh trongswitch.

7. Mẹo để nhận lệnh tốt hơn
- Nói rõ, tốc độ vừa phải, cách micro khoảng 0,5–2 m; phòng ồn thì lại gần hơn.
- Chọn câu lệnh khác nhau rõ rệt về âm (tránh hai lệnh chỉ khác một từ ngắn).
- Thêm vài cách nói cho cùng một lệnh để người dùng không phải nhớ đúng một câu.
- Dùng hai micro (định dạng "MM") giúp lọc ồn tốt hơn ở nơi nhiều tạp âm.
- Relay đóng cắt tải lớn (quạt, đèn 220 V) phải là module có cách ly và do người có chuyên môn đấu phía điện lưới.
8. Lỗi hay gặp
| Hiện tượng | Nguyên nhân thường gặp | Cách xử lý |
|---|---|---|
| Báo không tìm thấy mô hình | Chọn sai Partition Scheme, Flash 8 MB | Chọn "ESP SR 16M", bo Flash 16 MB |
| Lỗi thiếu bộ nhớ khi khởi động | Chưa bật PSRAM hoặc chọn sai loại | Chọn OPI PSRAM (N16R8) hoặc QSPI tùy bo |
| Không bao giờ nghe "Hi ESP" | Sai chân I2S, L/R không nối GND, micro lỗi | Kiểm tra dây; in thử mức âm thanh như bài INMP441 |
| Nhận nhầm lệnh | Câu lệnh giống nhau, phòng ồn | Đổi câu khác biệt hơn, giảm ồn |
| Serial Monitor không hiện gì | Cắm cổng USB gốc mà chưa bật USB CDC On Boot | Bật mục đó, hoặc cắm cổng USB-UART |
| Reset khi relay đóng | Nguồn yếu, nhiễu cuộn relay | Nguồn riêng cho relay; xem bài relay làm ESP32 bị reset |
9. Xem thêm
- Các bài cùng loạt AI trên vi điều khiển: TinyML là gì, Edge Impulse, loa trợ lý AI trên ESP32-S3; bài micro I2S INMP441 trong loạt module, bài chọn ESP32-S3, C3, C6 trong loạt ESP32 nâng cao.
Xem thêm