Giới thiệu
Bài 14 trình bày một dự án thực tế với ESP32-S3-DevKitC N16R8 CAM: Camera an ninh mini. Thiết bị sẽ chụp ảnh (snapshot) khi xảy ra sự kiện, lưu vào thẻ microSD và có thể xem lại qua WiFi. Bài này tập trung vào tư duy thiết kế, độ ổn định và khả năng chạy lâu dài.
Mục tiêu bài học
Sau bài này, bạn sẽ:
- Hiểu mô hình camera an ninh chụp ảnh theo sự kiện
- Biết cách thiết kế luồng xử lý ít tốn bộ nhớ
- Xây dựng hệ thống snapshot ổn định, chạy 24/7
- Biết cách mở rộng thêm cảm biến hoặc AI sau này
Tổng quan dự án Camera an ninh mini
Khác với camera stream liên tục, camera an ninh mini chỉ chụp ảnh khi cần, ví dụ:
- Theo thời gian định kỳ (giả lập sự kiện)
- Theo nút bấm
- Theo tín hiệu ngoại vi (PIR, công tắc, UART, I2C)
Cách này giúp:
- Giảm tải PSRAM và heap
- Tiết kiệm điện
- Tăng độ ổn định khi chạy lâu
Kiến trúc tổng thể
Luồng hoạt động cơ bản:
- ESP32-S3 khởi động
- Khởi tạo camera + microSD
- Chờ sự kiện xảy ra
- Chụp ảnh
- Lưu file vào microSD
- Ghi log (nếu cần)
- Quay về chế độ chờ
Các loại sự kiện có thể áp dụng
Sự kiện giả lập (để test)
- Chụp ảnh mỗi 30 giây / 1 phút
Sự kiện bằng nút bấm
- Nhấn nút → chụp ảnh
Sự kiện bằng cảm biến
- PIR phát hiện chuyển động
- Công tắc cửa
- Tín hiệu từ MCU khác qua UART/I2C
Trong bài này, chúng ta dùng sự kiện giả lập bằng timer để dễ theo dõi và debug.
Quy ước đặt tên file và thư mục
Cấu trúc đề xuất:
/snapshots/
2025-01-01/
IMG_0001.jpg
IMG_0002.jpg
Quy ước tên file:
- Có tiền tố IMG_
- Tăng dần theo số thứ tự
- Tránh trùng tên và dễ duyệt
Khởi tạo camera (nhắc lại)
Sử dụng camera_config_t giống Bài 09 và Bài 10, ưu tiên:
- Frame size: SVGA hoặc VGA
- jpeg_quality: 12–15
- fb_count: 2 (nếu có PSRAM)
Code ví dụ hoàn chỉnh: Camera an ninh mini
#include <Arduino.h>
#include "esp_camera.h"
#include "FS.h"
#include "SD_MMC.h"
unsigned long lastShot = 0;
const unsigned long SNAP_INTERVAL = 30000; // 30 giây
int imageIndex = 0;
void setup() {
Serial.begin(115200);
// Khởi tạo SD
if (!SD_MMC.begin()) {
Serial.println("Không thể khởi tạo SD_MMC");
return;
}
// Khởi tạo camera (giả lập, cần map đúng GPIO thực tế)
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 2;
if (esp_camera_init(&config) != ESP_OK) {
Serial.println("Camera init thất bại");
return;
}
Serial.println("Camera an ninh mini sẵn sàng");
}
void loop() {
unsigned long now = millis();
if (now - lastShot >= SNAP_INTERVAL) {
lastShot = now;
takeSnapshot();
}
}
void takeSnapshot() {
camera_fb_t *fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Chụp ảnh thất bại");
return;
}
String path = "/snapshots/IMG_" + String(imageIndex++) + ".jpg";
File file = SD_MMC.open(path, FILE_WRITE);
if (!file) {
Serial.println("Không mở được file");
esp_camera_fb_return(fb);
return;
}
file.write(fb->buf, fb->len);
file.close();
Serial.println("Đã lưu: " + path);
esp_camera_fb_return(fb);
}
Lưu ý để chạy ổn định lâu dài
- Không chụp ảnh quá liên tục
- Giảm frame size nếu thấy reset
- Đảm bảo nguồn cấp ổn định (dòng đủ)
- Test camera độc lập trước khi kết hợp WiFi
Hướng mở rộng trong tương lai
- Kết hợp PIR để chụp theo chuyển động
- Gửi ảnh qua WiFi / MQTT
- Thêm AI nhận diện (người, vật thể)
- Kết hợp Xiaozhi AI


