ESP32-CAM — циклическая съёмка с сохранением фото на SD-карту по дате и времени (NTP)

ESP32-CAM делает фотографию каждые N секунд, автоматически получает точное время через NTP-сервер и сохраняет снимки на microSD-карту с именем в формате «ДД.ММ.ГГГГ_ЧЧ-ММ-СС.jpg». Никаких внешних часов реального времени — только Wi-Fi и интернет. Идеальное решение для таймлапс-камер, фотоловушек, систем наблюдения и проектов умного дома своими руками.

Работает полностью автономно: подключается к Wi-Fi, синхронизирует время, фотографирует, сохраняет — и так по кругу.

ESP32-CAM циклическая съёмка на SD-карту

Необходимые компоненты

  • ESP32-CAM (AI-Thinker)
  • MicroSD-карта (отформатирована в FAT32)
  • Источник питания 5 В / 1–2 А
  • Доступ к Wi-Fi с выходом в интернет

Подключение

  • SD-карта вставляется в слот на плате
  • Питание строго 5 В (3.3 В → нестабильная работа)
  • GPIO0 на землю только при прошивке

Как это работает

  1. Подключение к Wi-Fi
  2. Синхронизация времени с NTP-сервером (pool.ntp.org)
  3. Каждые N секунд (по умолчанию 10 сек) — захват кадра
  4. Формирование имени: день.месяц.год_часы-минуты-секунды.jpg
  5. Запись 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);
  }
}
Подключается к Wi-Fi с заданными ssid и password.
Настраивает 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-карту.

📁 Скачать примеры