I'm struggling with making a simple sketch to take a photo on esp32cam and save to sd card. I have found a bunch of examples that that do what I want but basically they just take a photo and go to sleep. so every time you reset the unit it runs some code to take a photo, then goes into deep sleep. The thing is the photos suck, they are green and have no exposure control. I think that it is a known issue that the first photo is always green and the auto gain has not figured out the exposure yet. So because every photo is the first photo after waking up, they all suck.
I tried to move the setup stuff into the loop, and remove the sleep part, but it just straight up doesn't work. and I don't understand enough about coding to even get Chat GPT to help.....
I will put the working code below, and then the part i changed. Any help would be great. I thought it would be so simple, I just want to take a photo when i push a button.....
/*
ESP32 CAM Camera with MicroSD storage
esp32cam-microsd.ino
Take picture when button pressed
Store image on MicroSD card
DroneBot Workshop 2022
https://dronebotworkshop.com
*/
// Include Required Libraries
// Camera libraries
#include "esp_camera.h"
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "driver/rtc_io.h"
// MicroSD Libraries
#include "FS.h"
#include "SD_MMC.h"
// EEPROM Library
#include "EEPROM.h"
// Use 1 byte of EEPROM space
#define EEPROM_SIZE 1
// Counter for picture number
unsigned int pictureCount = 0;
// Pin definitions for CAMERA_MODEL_AI_THINKER
#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
void configESPCamera() {
// Configure Camera parameters
// Object to store the camera configuration parameters
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; // Choices are YUV422, GRAYSCALE, RGB565, 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; //10-63 lower number means higher quality
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_UXGA;
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;
}
// Camera quality adjustments
sensor_t * s = esp_camera_sensor_get();
// BRIGHTNESS (-2 to 2)
s->set_brightness(s, 0);
// CONTRAST (-2 to 2)
s->set_contrast(s, 1);
// SATURATION (-2 to 2)
s->set_saturation(s, 0);
// SPECIAL EFFECTS (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
s->set_special_effect(s, 2);
// WHITE BALANCE (0 = Disable , 1 = Enable)
s->set_whitebal(s, 1);
// AWB GAIN (0 = Disable , 1 = Enable)
s->set_awb_gain(s, 1);
// WB MODES (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
s->set_wb_mode(s, 0);
// EXPOSURE CONTROLS (0 = Disable , 1 = Enable)
s->set_exposure_ctrl(s, 1);
// AEC2 (0 = Disable , 1 = Enable)
s->set_aec2(s, 0);
// AE LEVELS (-2 to 2)
s->set_ae_level(s, 0);
// AEC VALUES (0 to 1200)
s->set_aec_value(s, 300);
// GAIN CONTROLS (0 = Disable , 1 = Enable)
s->set_gain_ctrl(s, 1);
// AGC GAIN (0 to 30)
s->set_agc_gain(s, 0);
// GAIN CEILING (0 to 6)
s->set_gainceiling(s, (gainceiling_t)0);
// BPC (0 = Disable , 1 = Enable)
s->set_bpc(s, 0);
// WPC (0 = Disable , 1 = Enable)
s->set_wpc(s, 1);
// RAW GMA (0 = Disable , 1 = Enable)
s->set_raw_gma(s, 1);
// LENC (0 = Disable , 1 = Enable)
s->set_lenc(s, 1);
// HORIZ MIRROR (0 = Disable , 1 = Enable)
s->set_hmirror(s, 0);
// VERT FLIP (0 = Disable , 1 = Enable)
s->set_vflip(s, 0);
// DCW (0 = Disable , 1 = Enable)
s->set_dcw(s, 1);
// COLOR BAR PATTERN (0 = Disable , 1 = Enable)
s->set_colorbar(s, 0);
}
void initMicroSDCard() {
// Start the MicroSD card
Serial.println("Mounting MicroSD Card");
if (!SD_MMC.begin()) {
Serial.println("MicroSD Card Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType();
if (cardType == CARD_NONE) {
Serial.println("No MicroSD Card found");
return;
}
}
void takeNewPhoto(String path) {
// Take Picture with Camera
// Setup frame buffer
camera_fb_t * fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
return;
}
// Save picture to microSD card
fs::FS &fs = SD_MMC;
File file = fs.open(path.c_str(), FILE_WRITE);
if (!file) {
Serial.println("Failed to open file in write mode");
}
else {
file.write(fb->buf, fb->len); // payload (image), payload length
Serial.printf("Saved file to path: %s\n", path.c_str());
}
// Close the file
file.close();
// Return the frame buffer back to the driver for reuse
esp_camera_fb_return(fb);
}
void setup() {
// Disable brownout detector
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
// Start Serial Monitor
Serial.begin(115200);
// Initialize the camera
Serial.print("Initializing the camera module...");
configESPCamera();
Serial.println("Camera OK!");
// Initialize the MicroSD
Serial.print("Initializing the MicroSD card module... ");
initMicroSDCard();
// initialize EEPROM with predefined size
EEPROM.begin(EEPROM_SIZE);
pictureCount = EEPROM.read(0) + 1;
// Path where new picture will be saved in SD Card
String path = "/image" + String(pictureCount) + ".jpg";
Serial.printf("Picture file name: %s\n", path.c_str());
// Take and Save Photo
takeNewPhoto(path);
// Update EEPROM picture number counter
EEPROM.write(0, pictureCount);
EEPROM.commit();
// Bind Wakeup to GPIO13 going LOW
esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 0);
Serial.println("Entering sleep mode");
delay(1000);
// Enter deep sleep mode
esp_deep_sleep_start();
}
void loop() {
}
I changed the set up and loop:
void setup() {
// Disable brownout detector
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
// Start Serial Monitor
Serial.begin(115200);
// Initialize the camera
Serial.print("Initializing the camera module...");
configESPCamera();
Serial.println("Camera OK!");
// Initialize the MicroSD
Serial.print("Initializing the MicroSD card module... ");
initMicroSDCard();
// initialize EEPROM with predefined size
EEPROM.begin(EEPROM_SIZE);
pictureCount = EEPROM.read(0) + 1;
}
void loop() {
// Path where the new picture will be saved on the SD Card
String path = "/image" + String(pictureCount) + ".jpg";
Serial.printf("Picture file name: %s\n", path.c_str());
// Check if GPIO13 is low
if (digitalRead(GPIO_NUM_13) == LOW) {
// Take and Save Photo
takeNewPhoto(path);
// Update EEPROM picture number counter
EEPROM.write(0, pictureCount);
EEPROM.commit();
}
}