#include "esp_camera.h" #include "FS.h" #include "SD.h" #include "SPI.h" #define CAMERA_MODEL_XIAO_ESP32S3 // Has PSRAM #include "camera_pins.h" unsigned long lastCaptureTime = 0; // Last shooting time int imageCount = 1; // File Counter bool camera_sign = false; // Check camera status bool sd_sign = false; // Check sd status // Save pictures to SD card void photo_save(const char * fileName) { // Take a photo camera_fb_t *fb = esp_camera_fb_get(); if (!fb) { Serial.println("Failed to get camera frame buffer"); return; } // Save photo to file writeFile(SD, fileName, fb->buf, fb->len); // Release image buffer esp_camera_fb_return(fb); Serial.println("Photo saved to file"); } // SD card write file void writeFile(fs::FS &fs, const char * path, uint8_t * data, size_t len){ Serial.printf("Writing file: %s\r\n", path); File file = fs.open(path, FILE_WRITE); if(!file){ Serial.println("Failed to open file for writing"); return; } if(file.write(data, len) == len){ Serial.println("File written"); } else { Serial.println("Write failed"); } file.close(); } void setup() { Serial.begin(115200); while(!Serial); // When the serial monitor is turned on, the program starts to execute 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.frame_size = FRAMESIZE_UXGA; config.pixel_format = PIXFORMAT_JPEG; // for streaming config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; config.fb_location = CAMERA_FB_IN_PSRAM; config.jpeg_quality = 12; config.fb_count = 1; // if PSRAM IC present, init with UXGA resolution and higher JPEG quality // for larger pre-allocated frame buffer. if(config.pixel_format == PIXFORMAT_JPEG){ if(psramFound()){ config.jpeg_quality = 10; config.fb_count = 2; config.grab_mode = CAMERA_GRAB_LATEST; } else { // Limit the frame size when PSRAM is not available config.frame_size = FRAMESIZE_SVGA; config.fb_location = CAMERA_FB_IN_DRAM; } } else { // Best option for face detection/recognition config.frame_size = FRAMESIZE_240X240; #if CONFIG_IDF_TARGET_ESP32S3 config.fb_count = 2; #endif } // camera init esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("Camera init failed with error 0x%x", err); return; } camera_sign = true; // Camera initialization check passes // Initialize SD card if(!SD.begin(21)){ Serial.println("Card Mount Failed"); return; } uint8_t cardType = SD.cardType(); // Determine if the type of SD card is available if(cardType == CARD_NONE){ Serial.println("No SD card attached"); return; } Serial.print("SD Card Type: "); if(cardType == CARD_MMC){ Serial.println("MMC"); } else if(cardType == CARD_SD){ Serial.println("SDSC"); } else if(cardType == CARD_SDHC){ Serial.println("SDHC"); } else { Serial.println("UNKNOWN"); } sd_sign = true; // sd initialization check passes Serial.println("Photos will begin in one minute, please be ready."); } void loop() { // Camera & SD available, start taking pictures if(camera_sign && sd_sign){ // Get the current time unsigned long now = millis(); //If it has been more than 1 minute since the last shot, take a picture and save it to the SD card if ((now - lastCaptureTime) >= 60000) { char filename[32]; sprintf(filename, "/image%d.jpg", imageCount); photo_save(filename); Serial.printf("Saved picture: %s\r\n", filename); Serial.println("Photos will begin in one minute, please be ready."); imageCount++; lastCaptureTime = now; } } }