ESP32-CAM esp_camera_fb_get always fails on second photo

My ESP32-CAM always fails on the second call to esp_camera_fb_get. Here is my code for reference, I'll talk through some steps I've taken below.

#include "esp_camera.h"
#include <base64.h>

#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

camera_config_t config;

const int buttonPin = 0;  // IO0 for the button
const int ledPin = 4;     // Built-in LED on the ESP32-CAM
volatile bool buttonPressed = false;


void cameraInit() {
  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 = 10000000;
  config.frame_size = FRAMESIZE_UXGA;
  config.pixel_format = PIXFORMAT_JPEG;  // for streaming
  config.grab_mode = CAMERA_GRAB_LATEST;
  config.fb_location = CAMERA_FB_IN_PSRAM;
  config.jpeg_quality = 12;
  config.fb_count = 2;

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

String grabImage() {
  camera_fb_t *fb = NULL;
  fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    esp_camera_fb_return(fb);
    fb = NULL;
    return "";
  }
  // Convert the image data to base64
  String base64String = base64::encode(fb->buf, fb->len);
  esp_camera_fb_return(fb);
  fb = NULL;
  return base64String;
}


void buttonInterrupt() {
  buttonPressed = true;
}

void setup() {
  Serial.begin(115200);
  cameraInit();
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);

  attachInterrupt(digitalPinToInterrupt(buttonPin), buttonInterrupt, FALLING);
}

void loop() {
  if (buttonPressed) {
    Serial.println("Button pressed!");
    digitalWrite(ledPin, HIGH);
    delay(100);
    String base64String = grabImage();
    delay(100);
    digitalWrite(ledPin, LOW);
    buttonPressed = false;
  }
}

Things I've tried:

  1. The ESP32 Camera WebServer example works great for both of my devices. Therefore, I suspect it is not hardware.
  2. I have tried multiple external power sources, it's likely not a voltage sag issue.
  3. I have verified that my module has PSRAM via psramFound()

Potentially unrelated, but when I change fb.fb_location from CAMERA_FB_IN_PSRAM to CAMERA_FB_IN_DRAM, my board goes into a reset loop. I do not understand why.

Programming with log level debug does not yield any useful information, infact between "Button Pressed!" and "Camera capture failed" logs, there is no debug output at all.

The only directly similar post I have found on this issue is here, and it seems to be dead.

The fact that esp_camera_fb_get always fails on the second call, makes me think that the frame buffer is not returning properly and overflowing or something? I am at a loss.

Any ideas?

This seems like a really bad idea. Why are you using a String, instead of a simple character array?

To test the camera functionality, run one of the reliable, simple examples, like this one.

That's helpful feedback, but in this case that line does not affect the camera capture failure.

I will give your example recommendation a try, but I should also emphasize that the out of the box example for the ESP32 CAM works great with my hardware.

I have to think it is something with my code configuration that is causing this issue.

I FINALLY found the solution to this. Apparently the camera module uses GPIO0 as a clock pin on my board. Me setting pinMode(buttonPin, INPUT_PULLUP); interfered with the camera clock.

Changing buttonPin to a different GPIO solved the problem.

1 Like

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