ESP32-CAM: фото на MicroSD-карту с датой и временем (timestamp)

В этом уроке вы научитесь делать снимки с помощью ESP32-CAM и сохранять их на карту microSD. Мы будем включать текущую дату и время в имя файла. Использование даты и времени в имени файла полезно, потому что каждый снимок будет иметь уникальное имя, что означает отсутствие проблем с перезаписью существующих файлов; вы будете знать, когда был сделан каждый снимок; и вам будет проще организовывать или находить ваши файлы позже.

ESP32-CAM: фото на MicroSD-карту с датой и временем

Предварительные требования

Прежде чем приступить к этому руководству, ознакомьтесь со следующими предварительными требованиями.

ESP32-CAM

Для этого проекта мы будем использовать плату ESP32-CAM AI-Thinker.

Плата ESP32-CAM

Если вы ещё не знакомы с ESP32-CAM, можете ознакомиться со следующими уроками:

Вы также можете использовать другую плату ESP32 с камерой — главное, чтобы она поддерживала карту microSD и вы скорректировали распиновку в коде. Этот проект совместим только с камерами OV2640.

Arduino IDE

Логотип Arduino IDE 2

Мы будем программировать плату ESP32 с помощью Arduino IDE. Для этого вам нужна установленная Arduino IDE, а также дополнение для ESP32. Если вы ещё не установили дополнение для ESP32, следуйте инструкции:

MicroSD-карта

Мы будем сохранять фотографии, сделанные с помощью ESP32-CAM, на карту microSD. Ваша карта microSD должна быть отформатирована в FAT32.

Чтобы ознакомиться с работой файлов на карте microSD с ESP32, посмотрите следующий урок:

Получение даты и времени с ESP32 (точный часовой пояс и летнее время)

Мы будем использовать текущую дату и время в именах файлов фотографий. У нас есть подробный урок, объясняющий, как настроить часовой пояс и летнее время при получении времени с NTP-сервера с помощью ESP32:

Обзор проекта

На следующей диаграмме показан общий обзор примера, который мы будем создавать.

Обзор проекта ESP32-CAM: фото на MicroSD-карту с датой и временем

В этом уроке мы покажем простой пример, который выполняет следующие действия:

  1. ESP32-CAM подключается к вашему маршрутизатору по Wi-Fi (это необходимо для получения времени с NTP-сервера);

  2. ESP32 подключается к NTP-серверу для инициализации даты и времени с правильным часовым поясом;

  3. Инициализируются камера и карта microSD;

  4. Камера делает новый снимок;

  5. Получается текущая дата и время с NTP-сервера;

  6. Фотография сохраняется на карту microSD — имя файла содержит дату и время съёмки (это уникальное имя файла);

  7. Шаги 4-6 повторяются каждые 10 секунд. Для демонстрации ESP32-CAM будет выполнять эту задачу снова и снова в loop(). Идея состоит в том, чтобы применить концепции, изученные в этом примере, к вашим собственным проектам.

Использование даты и времени в имени файла фотографии имеет несколько преимуществ:

  • все фотографии будут иметь разные имена файлов — у вас не будет проблем с перезаписью предыдущих файлов при перезагрузке ESP32;

  • вы будете знать, когда была сделана каждая фотография;

  • позже будет проще организовать ваши фотографии.

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

Для выполнения этого урока вам понадобится модуль ESP32 с камерой, поддерживающий карту microSD, сама карта microSD и оборудование для загрузки кода на плату (это может быть программатор ESP32-CAM MB или FTDI-программатор).

  • ESP32-CAM с OV2640

  • MicroSD-карта

  • Для загрузки кода на плату:

    • Программатор ESP32-CAM MB

    • Или FTDI-программатор и провода «мама-мама»

Код

Скопируйте следующий код в вашу Arduino IDE. Перед загрузкой кода на плату вам нужно указать ваш SSID и пароль, а также строку часового пояса для установки правильного часового пояса для вашего местоположения (подробнее о настройке строки часового пояса ниже).

/*********
  Rui Santos
  Complete instructions at https://RandomNerdTutorials.com/esp32-cam-photo-microsd-card-timestamp

  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*********/

#include "esp_camera.h"
#include "FS.h"                // SD Card ESP32
#include "SD_MMC.h"            // SD Card ESP32
#include "soc/soc.h"           // Disable brownout problems
#include "soc/rtc_cntl_reg.h"  // Disable brownout problems
#include "driver/rtc_io.h"
#include <WiFi.h>
#include "time.h"

// REPLACE WITH YOUR NETWORK CREDENTIALS
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// REPLACE WITH YOUR TIMEZONE STRING: https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
String myTimezone ="WET0WEST,M3.5.0/1,M10.5.0";

// Pin definition for CAMERA_MODEL_AI_THINKER
// Change pin definition if you're using another ESP32 camera module
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

// Stores the camera configuration parameters
camera_config_t config;

// Initializes the camera
void configInitCamera(){
  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_sccb_sda = SIOD_GPIO_NUM;
  config.pin_sccb_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; //YUV422,GRAYSCALE,RGB565,JPEG
  config.grab_mode = CAMERA_GRAB_LATEST;

  // Select lower framesize if the camera doesn't support PSRAM
  if(psramFound()){
    config.frame_size = FRAMESIZE_UXGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
    config.jpeg_quality = 10; //0-63 lower number means higher quality
    config.fb_count = 1;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }

  // Initialize the Camera
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }
}

// Connect to wifi
void  initWiFi(){
  WiFi.begin(ssid, password);
  Serial.println("Connecting Wifi");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
}

// Function to set timezone
void setTimezone(String timezone){
  Serial.printf("  Setting Timezone to %s\n",timezone.c_str());
  setenv("TZ",timezone.c_str(),1);  //  Now adjust the TZ.  Clock settings are adjusted to show the new local time
  tzset();
}

// Connect to NTP server and adjust timezone
void initTime(String timezone){
  struct tm timeinfo;
  Serial.println("Setting up time");
  configTime(0, 0, "pool.ntp.org");    // First connect to NTP server, with 0 TZ offset
  if(!getLocalTime(&timeinfo)){
    Serial.println(" Failed to obtain time");
    return;
  }
  Serial.println("Got the time from NTP");
  // Now we can set the real timezone
  setTimezone(timezone);
}

// Get the picture filename based on the current ime
String getPictureFilename(){
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return "";
  }
  char timeString[20];
  strftime(timeString, sizeof(timeString), "%Y-%m-%d_%H-%M-%S", &timeinfo);
  Serial.println(timeString);
  String filename = "/picture_" + String(timeString) +".jpg";
  return filename;
}

// Initialize the micro SD card
void initMicroSDCard(){
  // Start Micro SD card
  Serial.println("Starting SD Card");
  if(!SD_MMC.begin()){
    Serial.println("SD Card Mount Failed");
    return;
  }
  uint8_t cardType = SD_MMC.cardType();
  if(cardType == CARD_NONE){
    Serial.println("No SD Card attached");
    return;
  }
}

// Take photo and save to microSD card
void takeSavePhoto(){
  // Take Picture with Camera
  camera_fb_t * fb = esp_camera_fb_get();

  //Uncomment the following lines if you're getting old pictures
  //esp_camera_fb_return(fb); // dispose the buffered image
  //fb = NULL; // reset to capture errors
  //fb = esp_camera_fb_get();

  if(!fb) {
    Serial.println("Camera capture failed");
    delay(1000);
    ESP.restart();
  }

  // Path where new picture will be saved in SD Card
  String path = getPictureFilename();
  Serial.printf("Picture file name: %s\n", path.c_str());

  // Save picture to microSD card
  fs::FS &fs = SD_MMC;
  File file = fs.open(path.c_str(),FILE_WRITE);
  if(!file){
    Serial.printf("Failed to open file in writing mode");
  }
  else {
    file.write(fb->buf, fb->len); // payload (image), payload length
    Serial.printf("Saved: %s\n", path.c_str());
  }
  file.close();
  esp_camera_fb_return(fb);
}

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable brownout detector

  Serial.begin(115200);
  delay(2000);

  // Initialize Wi-Fi
  initWiFi();
  // Initialize time with timezone
  initTime(myTimezone);
  // Initialize the camera
  Serial.print("Initializing the camera module...");
  configInitCamera();
  Serial.println("Ok!");
  // Initialize MicroSD
  Serial.print("Initializing the MicroSD card module... ");
  initMicroSDCard();
}

void loop() {
  // Take and Save Photo
  takeSavePhoto();
  delay(10000);
}

Исходный код на GitHub

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

Продолжайте чтение, чтобы узнать, как работает код, или перейдите к разделу Демонстрация.

Подключение библиотек

Сначала подключите необходимые библиотеки для работы с камерой, картой microSD и временем.

#include "esp_camera.h"
#include "FS.h"                // SD Card ESP32
#include "SD_MMC.h"            // SD Card ESP32
#include "soc/soc.h"           // Disable brownout problems
#include "soc/rtc_cntl_reg.h"  // Disable brownout problems
#include "driver/rtc_io.h"
#include <WiFi.h>
#include "time.h"

Сетевые учётные данные

Вставьте ваши сетевые учётные данные в следующие переменные.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Строка часового пояса

Вставьте строку вашего часового пояса в переменную myTimezone. Вы можете посмотреть список строк часовых поясов здесь. Например, я живу в Порту. Часовой пояс — Europe/Lisbon. Из списка строк часовых поясов я вижу, что строка часового пояса для моего местоположения — WET0WEST,M3.5.0/1,M10.5.0.

//REPLACE WITH YOUR TIMEZONE STRING: https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
String myTimezone ="WET0WEST,M3.5.0/1,M10.5.0";

Распиновка камеры и конфигурация

Далее укажите определение пинов для используемой модели камеры. Для модуля ESP32-CAM AI-Thinker это следующее определение пинов (измените его, если используете другой модуль ESP32 с камерой):

// Pin definition for CAMERA_MODEL_AI_THINKER
// Change pin definition if you're using another ESP32 camera module
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

Определение пинов для различных плат ESP32 с камерой вы можете найти здесь: ESP32-CAM Camera Boards: Pin and GPIOs Assignment Guide.

Следующая строка необходима для сохранения конфигурации камеры. Мы добавим определение пинов и настройки изображения позже в коде.

// Stores the camera configuration parameters
camera_config_t config;

Настройка и инициализация камеры

Функция configInitCamera() начинает с назначения GPIO, которые вы определили ранее, а также формата изображения.

// Initializes the camera
void configInitCamera(){
  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; //YUV422,GRAYSCALE,RGB565,JPEG
  config.grab_mode = CAMERA_GRAB_LATEST;

Формат изображения определяется в следующей строке:

config.pixel_format = PIXFORMAT_JPEG; //YUV422,GRAYSCALE,RGB565,JPEG

Он может быть установлен в один из следующих форматов:

  • PIXFORMAT_JPEG

  • PIXFORMAT_YUV422

  • PIXFORMAT_GRAYSCALE

  • PIXFORMAT_RGB565

  • PIXFORMAT_JPEG (формат, который мы используем)

Определите размер кадра, качество изображения и количество изображений, сохраняемых в буфере кадров:

// Select lower framesize if the camera doesn't support PSRAM
if(psramFound()){
  config.frame_size = FRAMESIZE_UXGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
  config.jpeg_quality = 10; //0-63 lower number means higher quality
  config.fb_count = 1;
} else {
  config.frame_size = FRAMESIZE_SVGA;
  config.jpeg_quality = 12;
  config.fb_count = 1;
}

Если модель камеры поддерживает PSRAM, мы устанавливаем размер кадра UXGA (1600x1200) и качество изображения 1.

Вы можете установить размер кадра в один из этих вариантов:

  • FRAMESIZE_UXGA (1600 x 1200)

  • FRAMESIZE_QVGA (320 x 240)

  • FRAMESIZE_CIF (352 x 288)

  • FRAMESIZE_VGA (640 x 480)

  • FRAMESIZE_SVGA (800 x 600)

  • FRAMESIZE_XGA (1024 x 768)

  • FRAMESIZE_SXGA (1280 x 1024)

Качество изображения может быть числом от 0 до 63. Меньшее число означает более высокое качество.

Важно: очень низкие числа для качества изображения, особенно при более высоком разрешении, могут привести к сбою ESP32-CAM, или камера может не сделать снимки корректно. Поэтому, если вы заметите, что изображения, сделанные ESP32-CAM, обрезаны пополам или имеют странные цвета, это, вероятно, означает, что вам нужно снизить качество (выбрать более высокое число, например 10).

Следующие строки инициализируют камеру с настройками, которые вы задали ранее. Если камера не инициализируется успешно, будет возвращено сообщение об ошибке.

// Initialize the Camera
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
  Serial.printf("Camera init failed with error 0x%x", err);
  return;
}

Инициализация WiFi

Функция initWiFi() подключает вашу плату к локальной сети, используя учётные данные, которые вы указали ранее.

// Connect to wifi
void  initWiFi(){
  WiFi.begin(ssid, password);
  Serial.println("Connecting Wifi");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
}

Инициализация времени и установка часового пояса

Функция setTimezone() устанавливает переменную окружения TZ с правильным часовым поясом. Вызов setenv("TZ", timezone, 1), где timezone — один из часовых поясов, перечисленных здесь. Затем вызывается tzset() для обновления часового пояса. Вы должны были определить свой часовой пояс ранее в коде (переменная myTimezone).

// Function to set timezone
void setTimezone(String timezone){
  Serial.printf("  Setting Timezone to %s\n",timezone.c_str());
  setenv("TZ",timezone.c_str(),1);  //  Now adjust the TZ.  Clock settings are adjusted to show the new local time
  tzset();
}

Функция initTime() подключает ESP32-CAM к NTP-серверу и устанавливает правильный часовой пояс.

// Connect to NTP server and adjust timezone
void initTime(String timezone){
  struct tm timeinfo;
  Serial.println("Setting up time");
  configTime(0, 0, "pool.ntp.org");    // First connect to NTP server, with 0 TZ offset
  if(!getLocalTime(&timeinfo)){
    Serial.println(" Failed to obtain time");
    return;
  }
  Serial.println("Got the time from NTP");
  // Now we can set the real timezone
  setTimezone(timezone);
}

Получение текущего времени и имени файла для фотографии

Вся цель этого урока — сохранять фотографии на карту microSD, включая дату и время в имени файла. Имя файла будет в следующем формате:

picture_YYYY-MM-DD_HH-MM-SS.jpg

Функция getPictureFilename() получает текущую дату и время и выводит строку, которую можно использовать как имя файла для фотографии.

String getPictureFilename(){

Сначала мы получаем дату и время:

struct tm timeinfo;
if(!getLocalTime(&timeinfo)){
  Serial.println("Failed to obtain time");
  return "";
}

Затем мы преобразуем переменную timeinfo в строку в формате Y-m-d_H-M-S и выводим результат:

strftime(timeString, sizeof(timeString), "%Y-%m-%d_%H-%M-%S", &timeinfo);
Serial.println(timeString);

Получив дату и время в формате строки, мы можем объединить их с «picture» и «.jpg» — форматом изображения.

String filename = "/picture_" + String(timeString) +".jpg";

Наконец, мы возвращаем имя файла:

return filename;

Инициализация карты microSD

Функция initMicroSDCard() инициализирует карту microSD. Она возвращает сообщение об ошибке, если инициализация не удалась.

// Start Micro SD card
Serial.println("Starting SD Card");
if(!SD_MMC.begin()){
  Serial.println("SD Card Mount Failed");
  return;
}

Следующие строки возвращают ошибку, если карта microSD не подключена.

uint8_t cardType = SD_MMC.cardType();
if(cardType == CARD_NONE){
  Serial.println("No SD Card attached");
  return;
}

Съёмка и сохранение фотографии

Для съёмки и сохранения фотографии мы создали функцию takeSavePhoto().

Сначала она делает снимок с помощью функции esp_camera_fb_get().

camera_fb_t * fb = esp_camera_fb_get();

Эта строка создаёт буфер кадров fb, который содержит изображение.

Если вы получаете старые изображения при фотографировании, это может означать, что буфер изображений сохраняет более одной фотографии. Чтобы предотвратить это, вы можете раскомментировать следующие строки в коде:

//esp_camera_fb_return(fb); // dispose the buffered image
//fb = NULL; // reset to capture errors
//fb = esp_camera_fb_get();

Если захват не удался, мы выводим сообщение об ошибке и перезагружаем плату (перезагрузка платы необязательна, вы можете обработать ошибку иначе, например, попытаться сделать ещё один снимок).

if(!fb) {
  Serial.println("Camera capture failed");
  delay(1000);
  ESP.restart();
}

После съёмки мы вызываем функцию getPictureFilename() для получения имени файла с текущей временной меткой.

// Path where new picture will be saved in SD Card
String path = getPictureFilename();
Serial.printf("Picture file name: %s\n", path.c_str());

Теперь, когда у нас есть изображение (буфер кадров fb) и имя файла, мы можем сохранить его на карту microSD.

Откройте карту microSD в режиме записи и создайте файл с именем, которое мы определили ранее (оно находится в переменной path):

fs::FS &fs = SD_MMC;
File file = fs.open(path.c_str(),FILE_WRITE);

Если мы не можем открыть файл (из-за ошибки карты microSD или при создании файла), мы выводим сообщение об ошибке.

if(!file){
  Serial.printf("Failed to open file in writing mode");
}

Сохраните изображение, передав в качестве аргументов буфер кадров и его длину методу write().

file.write(fb->buf, fb->len); // payload (image), payload length

После этого закройте файл:

file.close();

Наконец, вызовите esp_camera_fb_return(fb) для очистки буфера fb, чтобы он был доступен для следующего снимка.

esp_camera_fb_return(fb);

setup()

В setup() инициализируйте Serial Monitor, инициализируйте Wi-Fi, установите часовой пояс, настройте и инициализируйте камеру, а также инициализируйте карту microSD.

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable brownout detector

  Serial.begin(115200);
  delay(2000);

  // Initialize Wi-Fi
  initWiFi();
  // Initialize time with timezone
  initTime(myTimezone);
  // Initialize the camera
  Serial.print("Initializing the camera module...");
  configInitCamera();
  Serial.println("Ok!");
  // Initialize MicroSD
  Serial.print("Initializing the MicroSD card module... ");
  initMicroSDCard();
}

loop()

В loop() вызовите функцию takeSavePhoto() для съёмки и сохранения фотографии на карту microSD. Имя файла уже будет содержать текущую временную метку.

void loop() {
  // Take and Save Photo
  takeSavePhoto();
  delay(10000);
}

Эта функция вызывается снова и снова в loop() каждые 10 секунд.

Мы делаем это в демонстрационных целях. Теперь вы сможете использовать функцию takeSavePhoto() в своих собственных проектах для съёмки фотографий с уникальным именем файла.

Демонстрация

После ввода ваших сетевых учётных данных и строки часового пояса загрузите код на вашу плату.

Если у вас ESP32-CAM AI-Thinker, вы должны выбрать AI Thinker ESP32-CAM в меню Tools > Board.

Выбор ESP32-CAM AI Thinker в Arduino IDE

После этого выберите COM-порт в Tools > Port.

Наконец, загрузите код.

Кнопка загрузки Arduino IDE 2.0

Если у вас возникли проблемы с загрузкой кода, ознакомьтесь с нашим руководством по устранению неполадок: ESP32-CAM Troubleshooting Guide: Most Common Problems Fixed.

После успешной загрузки кода на плату откройте Serial Monitor на скорости 115200 бод. Нажмите кнопку RST, чтобы перезагрузить плату и начать выполнение кода.

Не забудьте вставить карту microSD в слот карты microSD на ESP32-CAM.

Каждые 10 секунд вспышка будет включаться, и фотография будет сохраняться на карту microSD. Дайте коду поработать некоторое время, чтобы получить достаточное количество фотографий.

В Serial Monitor вы должны увидеть что-то вроде того, что показано ниже.

Демонстрация ESP32-CAM: фото с временной меткой в Serial Monitor

Затем вставьте карту microSD в ваш компьютер, чтобы просмотреть сделанные фотографии.

Папка с фотографиями ESP32-CAM на карте microSD

Фотографии должны иметь дату и время в названии. Например:

picture_2023-01-17_17-31-40.jpg

Это означает, что эта фотография была сделана:

  • Год: 2023

  • Месяц: 01 (январь)

  • День: 17-е

  • Время: 17:31:40

Заключение

В этом проекте вы узнали, как запрашивать дату и время (с правильным часовым поясом и летним временем) из интернета с помощью ESP32-CAM и использовать эту информацию для именования ваших фотографий. Таким образом, вы знаете, в какое время и дату была сделана определённая фотография, и вам не нужно беспокоиться о перезаписи фотографий на карте microSD.

Для подробного урока о получении даты и времени с ESP32 и настройке часового пояса мы рекомендуем следующий урок: