我有一块带有 OV2640 摄像头的 Ai-Thinker ESP32-CAM 板。我正在尝试构建一个项目(细节不相关),其中我需要以一定的帧速率(30fps+)拍照(jpeg)并处理它们。
这里的代码很简单。我正在以一定的延迟拍照 - 然后释放缓冲区。 问题是,当我将相机对准明亮的物体或更改场景并使用
Serial.printf("Free Stack: %u bytes\n", uxTaskGetStackHighWaterMark(NULL));
监视我的堆栈时,我发现存在内存泄漏。如果场景变化太频繁,堆栈在几分钟内就会溢出。
我的问题是我做错了什么导致内存泄漏?我是不是错过了什么?
#include "esp_camera.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_fb_t *frameBuffer = NULL;
void setup() {
Serial.begin(115200);
Serial.printf("\r\n");
Serial.printf("Before camera init:\r\n");
Serial.printf("Free DRAM: %u bytes\r\n", heap_caps_get_free_size(MALLOC_CAP_8BIT));
Serial.printf("Free PSRAM: %u bytes\r\n", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
initialize_camera();
Serial.printf("\r\n");
Serial.printf("After camera init:\r\n");
Serial.printf("Free DRAM: %u bytes\r\n", heap_caps_get_free_size(MALLOC_CAP_8BIT));
Serial.printf("Free PSRAM: %u bytes\r\n", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
delay(5000);
}
void loop() {
camera_fb_t *frameBuffer = esp_camera_fb_get();
if (!frameBuffer) {
Serial.println("Failed to capture frame");
delay(100);
return;
}
vTaskDelay(pdMS_TO_TICKS(10));
if (frameBuffer) {
esp_camera_fb_return(frameBuffer);
frameBuffer = NULL;
}
vTaskDelay(pdMS_TO_TICKS(20));
if (!heap_caps_check_integrity(MALLOC_CAP_8BIT, true)) {
Serial.println("Heap integrity check failed \r\n");
}
Serial.printf("Free Stack: %u bytes\n", uxTaskGetStackHighWaterMark(NULL));
Serial.printf("\r\n");
}
void initialize_camera() {
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_QQVGA;
config.pixel_format = PIXFORMAT_JPEG;
if (psramFound()) {
Serial.print("Using psram \n\r");
config.jpeg_quality = 5;
config.fb_count = 2;
config.grab_mode = CAMERA_GRAB_LATEST;
config.fb_location = CAMERA_FB_IN_PSRAM;
} else {
Serial.print("Using dram. Exiting \n\r");
return;
}
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Сamera error: 0x%x", err);
return;
}
Serial.print("Camera initialized \n\r");
}
有几个技巧可以帮助您解决问题
config.xclk_freq_hz = 10000000;
我测试了修复我的 WDT 问题
config.jpeg_quality = 10;
fb_count
以确保有足够的缓冲区config.fb_count = 30;
将循环功能的延迟减少到以下
1ms
确保您在 Arduino 中正确配置您的开发板并使用稳定的固件,启用
PSRAM
如果上述所有步骤都没有解决您的问题测试
CameraWebServer
示例与您的测试条件,以确保这是您的代码问题而不是项目配置或板或其他问题