ESP32-CAM LED does not shut off between photos

Hello,
I'm trying to build a Wildlife Trail Cam using a ESP32-CAM (AI-Thinker) camera module.
I came across this sketch which can be configured to take a Flash Photo at pre-set time intervals.
This code may do the job, but has one major problem. The front mounted LED flashes to take the photo, but does not shut off completely between shots (It only dims) . As I want to save battery power, I wondered if anyone knows how to do this in code?

Here is the Sketch:

// SKETCH NAME: ESP32-CAM_AUTO_SETUP_CAMERA_SD-CARD.ino
// Sketch auto configures camera settings & saves photo every 60 seconds to SD card,
// and Front LED flashes with each photo taken.

// ##### Change the interval time on line 70.
// ##### Currently set to 1 minute! ?What size are the photos?

// Photo size is 160Kb each. 1440 photos taken in 24 Hrs.
// 2Gb camera card will hold 12,500 photos which will last 8.7 days. 

// ***** TO PROGRAM ESP32-CAM and CHANGE CAMERA SETTINGS *****
// https://RandomNerdTutorials.com/esp32-cam-ov2640-camera-settings/
// https://randomnerdtutorials.com/program-upload-code-esp32-cam/

#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"

// Pin definition for CAMERA_MODEL_AI_THINKER
// Change pin definition if you're using another ESP32 with 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

// Keep track of number of pictures
unsigned int pictureNumber = 0;

//Stores the camera configuration parameters
camera_config_t config;

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

  Serial.begin(115200);

  //Initialize the camera
  Serial.print("Initializing the camera module...");
  configInitCamera();  //Run configInitCamera void below.
  Serial.println("Ok!");

  //Initialize MicroSD
  Serial.print("Initializing the MicroSD card module... ");
  initMicroSDCard();  //Run configInitCamera void below.
}

// ******************************
void loop() {
  //Path where new picture will be saved in SD Card
  String path = "/picture" + String(pictureNumber) + ".jpg";
  Serial.printf("Picture file name: %s\n", path.c_str());

  //Take and Save Photo
  takeSavePhoto(path);  //Run takeSavePhoto void below
  pictureNumber++;
  
  // Set Photo interval:
  delay(60000); //default 10 seconds equals 10000 (1 min = 60000)(10 mins = 600000)
}

// ******************************
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

  // 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_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;
  }

  sensor_t * s = esp_camera_sensor_get();
  s->set_brightness(s, 0);     // -2 to 2
  s->set_contrast(s, 0);       // -2 to 2
  s->set_saturation(s, 0);     // -2 to 2
  s->set_special_effect(s, 0); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
  s->set_whitebal(s, 1);       // 0 = disable , 1 = enable
  s->set_awb_gain(s, 1);       // 0 = disable , 1 = enable
  s->set_wb_mode(s, 0);        // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
  s->set_exposure_ctrl(s, 1);  // 0 = disable , 1 = enable
  s->set_aec2(s, 1);           // 0 = disable , 1 = enable  //default=0
  s->set_ae_level(s, 0);       // -2 to 2
  s->set_aec_value(s, 300);    // 0 to 1200
  s->set_gain_ctrl(s, 1);      // 0 = disable , 1 = enable
  s->set_agc_gain(s, 0);       // 0 to 30
  s->set_gainceiling(s, (gainceiling_t)0);  // 0 to 6
  s->set_bpc(s, 1);            // 0 = disable , 1 = enable //default=0
  s->set_wpc(s, 1);            // 0 = disable , 1 = enable
  s->set_raw_gma(s, 1);        // 0 = disable , 1 = enable
  s->set_lenc(s, 1);           // 0 = disable , 1 = enable
  s->set_hmirror(s, 0);        // 0 = disable , 1 = enable
  s->set_vflip(s, 0);          // 0 = disable , 1 = enable
  s->set_dcw(s, 1);            // 0 = disable , 1 = enable
  s->set_colorbar(s, 0);       // 0 = disable , 1 = enable
}

// ******************************
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;
  }
}

// ******************************
void takeSavePhoto(String path) {
  // Take Picture with Camera
  camera_fb_t  * fb = esp_camera_fb_get();

  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }

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

  //return the frame buffer back to the driver for reuse
  esp_camera_fb_return(fb);
}

The White LED is on GPIO4.

The code will be setting that pin high to turn the LED on, you need to set it low to turn the LED fully off.

Hi srnet, Yes, I know. I was hoping to shut it completely off in the code, but my programming prowess is lacking. I don't know why the existing code doesn't automatically do it. If I don't get any help with the code, maybe I could add a bleed resistor to ground on GP104 as a hardware work around.

Its not straight forward.

If you check the schematic you will see that GPIO4 is also connected to the SD card.

Arduino code to set a GPIO pin low is very basic.

Yes, but timing is critical as you only want to set it low when LED is not active.
I just soldered a 10k resistor between GP104 and Ground, which stopped the LED afterglow. More tests have to be done to confirm this workaround. I would have preferred to do it in the code. More advice will be welcomed. Mac

Your resistor may prevent the LED from remaining lit, but I'm doubtful that it's saving your battery.

Hi dThirteen,
The LED lights up normally, and the current draw on the resistor is minimal 0.32v/10k amps. Also, my other reason was, I did not want any light showing all the time. Thanks, Mac

That's a really ugly, hacky, kludge. As long as you're willing to do surgery on the board, here's a much better solution:
https://www.youtube.com/watch?v=loet1ndG8Sg

Also, if you're serious about increasing battery life, you should look into the various ESP32 sleep modes.

If you put the sd card in to 1-bit mode this will stop it using the same gpio pin as the flash although sd card access will be slower.

see Using the SD Card in 1-Bit Mode on the ESP32-CAM from AI-Thinker – Dr. Mountain

Hi gfvalvo,
I like your idea the best as it has GPIO33 triggering the Flash LED, not tied to the SD card reader. Unfortunately, I have no Idea how or where to add code to get this to work. I know how to make a GPIO pin high/low, but not sure how to implement it in the above sketch. Thanks, Mac

EDIT, don't need the final delay:
The sequence would be:

  • Turn on the LED
  • Delay a little bit (say 100 ms)
  • Grab the image from the camera
  • Delay a little bit (say 100 ms)
  • Turn off the LED

So, it all goes in your takeSavePhotofunction.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.