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:
- The ESP32 Camera
WebServerexample works great for both of my devices. Therefore, I suspect it is not hardware. - I have tried multiple external power sources, it's likely not a voltage sag issue.
- 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?