ESP32-CAM — циклическая съёмка с сохранением фото на SD-карту по дате и времени (NTP)
ESP32-CAM делает фотографию каждые N секунд, автоматически получает точное время через NTP-сервер и сохраняет снимки на microSD-карту с именем в формате «ДД.ММ.ГГГГ_ЧЧ-ММ-СС.jpg». Никаких внешних часов реального времени — только Wi-Fi и интернет. Идеальное решение для таймлапс-камер, фотоловушек, систем наблюдения и проектов умного дома своими руками.
Работает полностью автономно: подключается к Wi-Fi, синхронизирует время, фотографирует, сохраняет — и так по кругу.
Необходимые компоненты
- ESP32-CAM (AI-Thinker)
- MicroSD-карта (отформатирована в FAT32)
- Источник питания 5 В / 1–2 А
- Доступ к Wi-Fi с выходом в интернет
Подключение
- SD-карта вставляется в слот на плате
- Питание строго 5 В (3.3 В → нестабильная работа)
- GPIO0 на землю только при прошивке
Как это работает
- Подключение к Wi-Fi
- Синхронизация времени с NTP-сервером (pool.ntp.org)
- Каждые N секунд (по умолчанию 10 сек) — захват кадра
- Формирование имени: день.месяц.год_часы-минуты-секунды.jpg
- Запись JPEG на SD-карту в корень (можно в папку)
Пример кода
#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include "esp_camera.h"
#include "camera_pins.h"
#include <SD_MMC.h>
const char* ssid = "ВАША_СЕТЬ";
const char* password = "ВАШ_ПАРОЛЬ";
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 10800, 60000); // +3 часа, обновление раз в минуту
unsigned long previousMillis = 0;
const long interval = 10000; // интервал в мс (10 сек)
void setup() {
Serial.begin(115200);
// WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected");
// NTP
timeClient.begin();
// Камера AI-Thinker
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10;
config.fb_count = 1;
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed: 0x%x\n", err);
while(1);
}
// SD-карта
if (!SD_MMC.begin()) {
Serial.println("SD Card Mount Failed");
while(1);
}
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
timeClient.update();
String formattedTime = timeClient.getFormattedTime();
String date = String(timeClient.getDay()) + "." +
String(timeClient.getMonth() + 1) + "." +
String(timeClient.getYear()) + "_" +
formattedTime.substring(0,2) + "-" +
formattedTime.substring(3,5) + "-" +
formattedTime.substring(6,8);
String path = "/" + date + ".jpg";
camera_fb_t * fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
return;
}
File file = SD_MMC.open(path.c_str(), FILE_WRITE);
if (file) {
file.write(fb->buf, fb->len);
file.close();
Serial.printf("Saved: %s (%d bytes)\n", path.c_str(), fb->len);
} else {
Serial.println("Failed to open file");
}
esp_camera_fb_return(fb);
}
}
Настраивает NTP-клиент для получения текущего времени с учётом часового пояса (+3 часа).
Инициализирует камеру ESP32-CAM (AI-Thinker) с разрешением UXGA и JPEG-качеством 10.
Монтирует SD-карту через SD_MMC.
Каждые 10 секунд (interval = 10000) в loop():
обновляет время через NTP, формирует имя файла с датой и временем,
делает снимок с камеры,
сохраняет изображение на SD-карту,
выводит в Serial Monitor путь к файлу и его размер.
Особенности / возможные проблемы:
Не выполняется проверка, подключена ли камера к правильным GPIO-пинам (используется camera_pins.h, он должен содержать корректные определения).
Если Wi-Fi не подключается, ESP будет висеть в бесконечном цикле while (WiFi.status() != WL_CONNECTED).
Если SD-карта не смонтирована, программа останавливается навсегда (while(1)).
Формирование имени файла зависит от timeClient.getDay()/getMonth()/getYear(), которые могут быть не отформатированы (например, месяц с нуля).
Код предполагает, что на SD-карте достаточно места и файловая система поддерживает SD_MMC (обычно только SPIFFS или FAT).
Разбор кода
NTPClient получает время, формируем имя файла, esp_camera_fb_get() делает снимок, SD_MMC.open() + write() сохраняет в корень карты. Интервал меняется в переменной interval.
Преимущества
- Точное время без RTC-модуля
- Имя файла = дата и время (удобно для таймлапса)
- Полностью автономная работа
- Не занимает I2C (доступен для других датчиков)
- Легко менять интервал и папку сохранения
Применение
- Таймлапс-съёмка стройки/цветов/облаков
- Автоматическая фотодокументация процессов
- Фотоловушки с точной меткой времени
- Системы наблюдения с архивом по датам
- Любые проекты с периодической съёмкой
Заключение
ESP32-CAM + NTP + SD-карта — простое и надёжное решение для циклической съёмки с правильными именами файлов. Никаких внешних часов, никаких сложных схем. Прошейте скетч, вставьте SD-карту — и получайте фото каждые 10 секунд (или сколько захотите) с точной датой и временем!
FAQ — ESP32-CAM с циклической съёмкой и сохранением фото на SD-карту по времени NTP
Как ESP32-CAM получает точное время без RTC-модуля?
Устройство подключается к интернету через Wi-Fi и синхронизирует текущее время с NTP-сервером pool.ntp.org. Время обновляется автоматически и используется для формирования имени файла. RTC-модуль не требуется — достаточно стабильного интернет-соединения.
В каком формате сохраняются фотографии на SD-карту?
Снимки записываются в формате JPEG. Имя файла формируется автоматически в виде «ДД.ММ.ГГГГ_ЧЧ-ММ-СС.jpg», что позволяет легко сортировать и использовать фотографии для таймлапса или архивирования.
Нужна ли настройка часов или ручной ввод даты?
Нет. После подключения к Wi-Fi камера автоматически запрашивает время с NTP-сервера. Все дальнейшие снимки получают корректную дату и время без участия пользователя.
Какой интервал между фотографиями можно установить?
Интервал задаётся переменной interval в миллисекундах. В примере используется значение 10 секунд, но вы можете установить любую частоту — от нескольких миллисекунд до часов, в зависимости от задачи и скорости SD-карты.
Какие требования к SD-карте для ESP32-CAM?
Необходима microSD-карта, отформатированная в FAT32. Рекомендуется использовать карты от 4 ГБ и выше. Поддерживается SD_MMC-режим, при котором ESP32-CAM работает напрямую со слотом на плате без дополнительных модулей.
Почему питание должно быть строго 5 В?
ESP32-CAM потребляет значительные токи при работе Wi-Fi и камеры. Питание 3.3 В часто приводит к перезагрузкам, отсутствию инициализации камеры и ошибкам записи на SD-карту. Рекомендуется источник 5 В / 1–2 А для стабильной работы.
Куда сохраняются снимки на SD-карте?
По умолчанию фотографии записываются в корневую папку SD-карты. При необходимости в коде можно указать путь для сохранения файлов в отдельную папку — для удобной сортировки проекта или архива наблюдения.
Что будет, если Wi-Fi временно отключится?
Съёмка продолжится, но время перестанет обновляться. ESP32-CAM будет использовать последнее синхронизированное время до восстановления сети. После переподключения устройство автоматически повторно синхронизирует часы с NTP-сервером.
Какое разрешение фото используется при циклической съёмке?
По умолчанию применяется разрешение UXGA (1600×1200), обеспечивающее высокое качество снимков. При необходимости разрешение можно уменьшить для экономии места и увеличения скорости записи на SD-карту.