espressif / esp32-camera

Apache License 2.0
1.89k stars 636 forks source link

BF3005 - JPEG content not updated properly when taking multiple pictures #545

Closed rbruneau-altyor closed 1 year ago

rbruneau-altyor commented 1 year ago

Hi,

I have been trying to use BF3005 camera and simple example code to take a picture every 10 seconds in the main loop. I notice a very strange behavior : the very first picture seem to be fine, but when I take a second one 10 seconds later, it outputs the same picture as the previous one. On the third loop, the picture output is a copy of the actual second picture, and it goes on and on until next reboot. Basically, the only picture that has the right content is the first one, every other picture is shifted. Here is the code I used to test it:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "esp_system.h"
#include "esp_timer.h"
#include "esp_log.h"
#include "soc/uart_struct.h"
#include "driver/gpio.h"
#include "driver/sdmmc_host.h"
#include "driver/sdmmc_defs.h"
#include "sdmmc_cmd.h"
#include "esp_vfs_fat.h"
#include "esp_camera.h"

#define CAM_PIN_PWDN                GPIO_NUM_21 ///<
#define CAM_PIN_RESET               -1          ///< software reset will be performed
#define CAM_PIN_XCLK                GPIO_NUM_15 ///<
#define CAM_PIN_SIOD                GPIO_NUM_4  ///<
#define CAM_PIN_SIOC                GPIO_NUM_5  ///<

#define CAM_PIN_D7                  GPIO_NUM_16 ///<
#define CAM_PIN_D6                  GPIO_NUM_17 ///<
#define CAM_PIN_D5                  GPIO_NUM_18 ///<
#define CAM_PIN_D4                  GPIO_NUM_12 ///<
#define CAM_PIN_D3                  GPIO_NUM_10 ///<
#define CAM_PIN_D2                  GPIO_NUM_8  ///<
#define CAM_PIN_D1                  GPIO_NUM_9  ///<
#define CAM_PIN_D0                  GPIO_NUM_11 ///<
#define CAM_PIN_VSYNC               GPIO_NUM_6  ///<
#define CAM_PIN_HREF                GPIO_NUM_7  ///<
#define CAM_PIN_PCLK                GPIO_NUM_13 ///<

#define CONFIG_XCLK_FREQ 16000000

const char *TAG = "MAIN";

static esp_err_t init_camera(void)
{
    camera_config_t camera_config = {
        .pin_pwdn  = CAM_PIN_PWDN,
        .pin_reset = CAM_PIN_RESET,
        .pin_xclk = CAM_PIN_XCLK,
        .pin_sccb_sda = CAM_PIN_SIOD,
        .pin_sccb_scl = CAM_PIN_SIOC,

        .pin_d7 = CAM_PIN_D7,
        .pin_d6 = CAM_PIN_D6,
        .pin_d5 = CAM_PIN_D5,
        .pin_d4 = CAM_PIN_D4,
        .pin_d3 = CAM_PIN_D3,
        .pin_d2 = CAM_PIN_D2,
        .pin_d1 = CAM_PIN_D1,
        .pin_d0 = CAM_PIN_D0,
        .pin_vsync = CAM_PIN_VSYNC,
        .pin_href = CAM_PIN_HREF,
        .pin_pclk = CAM_PIN_PCLK,

        .xclk_freq_hz = CONFIG_XCLK_FREQ,
        .ledc_timer = LEDC_TIMER_0,
        .ledc_channel = LEDC_CHANNEL_0,

        .pixel_format = PIXFORMAT_YUV422,
        .frame_size = FRAMESIZE_QVGA,//FRAMESIZE_UXGA,   FRAMESIZE_QVGA=320x240

        .jpeg_quality = 12,
        .fb_count = 1,
        .grab_mode = CAMERA_GRAB_WHEN_EMPTY,
        .fb_location = CAMERA_FB_IN_PSRAM
    };//CAMERA_GRAB_LATEST. Sets when buffers should be filled

    esp_err_t err = esp_camera_init(&camera_config);
    if (err != ESP_OK)
    {
        return err;
    }
    return ESP_OK;
}

void app_main()
{
    init_camera();
    camera_fb_t * fb = NULL;
    esp_err_t res = ESP_OK;
    size_t _jpg_buf_len;
    uint8_t * _jpg_buf;
    while(true){
        fb = esp_camera_fb_get();
        if (!fb){
            ESP_LOGE(TAG, "Camera capture failed");
            res = ESP_FAIL;
            break;
        }
        if(fb->format != PIXFORMAT_JPEG){
            ESP_LOGI(TAG, "JPEG compression");
            bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
            if(!jpeg_converted){
                ESP_LOGE(TAG, "JPEG compression failed");
                esp_camera_fb_return(fb);
                res = ESP_FAIL;
            }
        } else {
            _jpg_buf_len = fb->len;
            _jpg_buf = fb->buf;
        }

        if(res == ESP_OK){
            for(uint32_t i = 0; i < _jpg_buf_len; i++){
                printf("%02X", _jpg_buf[i]);
            }
            printf("\n");
        }
        if(fb->format != PIXFORMAT_JPEG){
            ESP_LOGI(TAG, "Freeing picture");
            free(_jpg_buf);
        }
        esp_camera_fb_return(fb);
        vTaskDelay(pdMS_TO_TICKS(10000));
    }
}

Does anyone has the same problem with the BF3005 camera? Or is there something wrong in my code?

me-no-dev commented 1 year ago

what happens if you use .grab_mode = CAMERA_GRAB_LATEST?

rbruneau-altyor commented 1 year ago

@me-no-dev same behavior. It seems like 2 pictures are taken at the same time when I do the first loop

rbruneau-altyor commented 1 year ago

Though, If I initialize and deinitialize the camera every time I loop, it works fine...

me-no-dev commented 1 year ago

that is really strange... I gave the suggestion for grab_mode, though it should not have happened anyway, because when fb_count is set to 1, then whenever you call esp_camera_fb_get();, only then the driver goes and waits for new frame from the sensor and grabs it, therefore you should always get a current frame with .fb_count = 1

rbruneau-altyor commented 1 year ago

What is even stranger is it that all pictures are taken fine, but returned shifted everytime, so the camera is able to take the picture but does not return it at the right time...

me-no-dev commented 1 year ago

do you have any other sensors to test with? like OV2640?

rbruneau-altyor commented 1 year ago

Yes, I will try to adjust my configuration with OV2640 and I will let you know the result asap. Thank you for your help

rbruneau-altyor commented 1 year ago

@me-no-dev Same result with OV2640... the picture is duplicated

rbruneau-altyor commented 1 year ago

Can anyone try the code I gave with either OV2640 or BF3005 and tell me if you observe the same problem?

me-no-dev commented 1 year ago

OK, I can confirm the issue. Will look into it

rbruneau-altyor commented 1 year ago

Hi @me-no-dev, any news on the subject? I tried the same code with different boards (esp-camera, esp-eye and custom esp32s3 + camera board) and different cameras on each hardware (BF3005 and OV2640), and the issue always shows up, so it seems like hardware is fine

me-no-dev commented 1 year ago

it will not be very easy to fix this and we are currently a bit overloaded with other tasks. I have started the "research" on how to best approach this and will fix it. Till then you can get around this by grabbing and returning the frame immediately, then grabbing another one (which will be the latest one). The code will fill the frame as soon as you return it, so that is why you are getting an old frame currently.

WangYuxin-esp commented 1 year ago

Hi, @rbruneau-altyor , I suggest you try using the following configuration to test this sensor: XCLK=10M,
format = RGB565,
resolution = VGA. My testing here is completely normal.

rbruneau-altyor commented 1 year ago

Hi @WangYuxin-esp, what I2C speed do you use beside of these parameters?

WangYuxin-esp commented 1 year ago

Hi @WangYuxin-esp, what I2C speed do you use beside of these parameters?

100K. And here are some simple examples.

rbruneau-altyor commented 1 year ago

I re-wrote my code with your parameters, the first picture is still duplicated...

WangYuxin-esp commented 1 year ago

I re-wrote my code with your parameters, the first picture is still duplicated...

In most cases, we should always ignore the first few images by esp_camera_fb_return(esp_camera_fb_get()).
Because most sensors have an automatic adjustment process after they are first configured.

rbruneau-altyor commented 1 year ago

There is another way to get rid of the problem with both OV2640 and BF3005, set .fb_count = 2 and .grab_mode = CAMERA_GRAB_LATEST, with either PIXFORMAT_RGB565 or PIXFORMAT_YUV422. It worked fine for me, but I'm still a bit confused why I could not use use fb_count set to 1...

Anyway, thank you @WangYuxin-esp and @me-no-dev for your advices

WangYuxin-esp commented 1 year ago

When .fb_count is set to 1, it only affects the frame rate. It does not affect obtaining images. If you want to obtain new images, just call fb_retrun() is sufficient, so that the buffer can be reused to receive data from the sensor.

rbruneau-altyor commented 1 year ago

Well, I can't explain why but switching fb_count to 2 made it worked by itself for me. Do you think there is a hardware problem?

WangYuxin-esp commented 1 year ago

Well, I can't explain why but switching fb_count to 2 made it worked by itself for me. Do you think there is a hardware problem?

This is unlikely to be a hardware issue. Because the value of parameter fb_count only affects the operation of ESP32. I do not recommend configuring XCLK to 16M, as the standard clock for this sensor should be 10M.

rbruneau-altyor commented 1 year ago

XCLK set to 10MHz gives OVF errors so I have to stick to 16MHz, which is indicated as experimental for ESP32-S3 but it is the only way I found to make it work

me-no-dev commented 1 year ago

XCLK set to 10MHz gives OVF errors so I have to stick to 16MHz, which is indicated as experimental for ESP32-S3 but it is the only way I found to make it work

Start the camera with XCLK different than 16MHz and then switch it to 16MHz after init. This should get you out of the experimental mode (which is direct write to PSRAM from DMA).

rbruneau-altyor commented 1 year ago

Ok i'll try that. Do you think the problem is linked to experimental mode?

me-no-dev commented 1 year ago

In experimental mode everything is handled in hardware and only VSYNC is captured in the ISR. Which OVF error are you getting?

rbruneau-altyor commented 1 year ago

I get cam_hal: FB-OVF error with 10MHz

Just in case, I have BLE and other tasks running in the back ground, is it possible that CPU time given to each tasks has an impact on camera usage?

WangYuxin-esp commented 1 year ago

I get cam_hal: FB-OVF error with 10MHz

Just in case, I have BLE and other tasks running in the back ground, is it possible that CPU time given to each tasks has an impact on camera usage?

Could you provide more detailed configurations, including resolution and data format? Different sensors have very different characteristics. For this sensor, I suggest that you use the configuration I suggest to confirm that it works properly. Then it's about improving its performance in other configurations.

rbruneau-altyor commented 1 year ago

Currently, I'm using the following configuration:

Camera: BF3005 I2C speed: 800000kHz (lower values simply do not work) XCLK Frequency: 16MHz Picture format: PIXFORMAT_RGB565 Frame size: FRAMESIZE_QVGA JPEG quality: 6 fb_count: 2 Grab mode: CAMERA_GRAB_LATEST fb_location: CAMERA_FB_IN_PSRAM

I'm planning to use several UART interfaces + BLE beside of the camera.

The configuration I've detailed above works fine, the problem is that I have to set fb_count to 2 to make it work. Otherwise, the doubled picture problem appears.

Right now I'm fine with these settings, though I would prefer to use fb_count set to 1.

Though, it seems like the configuration you are sugegsting me does not work at all. XCLK frequency and I2C speed are too low, giving me other errors than the one I encountered with my own settings. May be I should open another issue as it is not directly related to the original problem?

WangYuxin-esp commented 1 year ago

Currently, I'm using the following configuration:

Camera: BF3005 I2C speed: 800000kHz (lower values simply do not work) XCLK Frequency: 16MHz Picture format: PIXFORMAT_RGB565 Frame size: FRAMESIZE_QVGA JPEG quality: 6 fb_count: 2 Grab mode: CAMERA_GRAB_LATEST fb_location: CAMERA_FB_IN_PSRAM

I'm planning to use several UART interfaces + BLE beside of the camera.

The configuration I've detailed above works fine, the problem is that I have to set fb_count to 2 to make it work. Otherwise, the doubled picture problem appears.

Right now I'm fine with these settings, though I would prefer to use fb_count set to 1.

Though, it seems like the configuration you are sugegsting me does not work at all. XCLK frequency and I2C speed are too low, giving me other errors than the one I encountered with my own settings. May be I should open another issue as it is not directly related to the original problem?

What is the 'double picture problem', could you provide specific some pictures? Or I suggest you use the example here for testing, simply using the following configuration:

init_camera(10000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 1)

In the above example, I have no problem using the above configuration.

rbruneau-altyor commented 1 year ago

@WangYuxin-esp Ok, I'll rexplain with pictures so you can understand better:

My code basically takes a picture every 10 second, and logs the JPEG hex code that I convert to an image later to check the content. I have 3 papers written from 1 to 3, and I take a picture of each of them. Here are the outputs I get for each of them, using fb_count set to 1, FRAMESIZE_QVGA, PIXFORMAT_RGB565 and XCLK = 16MHz :

First take: image

Second take (10 seconds later): image

Third take (10 seconds later): image

As you can see, I should have gotten 1, 2 and then 3, but instead, I get 1, 1 and then 2, which means the first picture is duplicated (or 2 picures are taken almost at the same time and saved), and all other picture are returned displaced.

Using the parameters you gave me, it does work either. The only way to make it work properly is to set fb_count to 2

rbruneau-altyor commented 1 year ago

So, I tried the esp-iot-solution and took a look at the code, and it seems to me that 2 pictures are taken in a row in pic_server.c, line 43: esp_camera_fb_return(esp_camera_fb_get()); frame = esp_camera_fb_get();

So, do I have to do the same in my code? Because the examples from esp32-camera repository do not show that king of code in the examples. It seems like a major difference to me

WangYuxin-esp commented 1 year ago

So, I tried the esp-iot-solution and took a look at the code, and it seems to me that 2 pictures are taken in a row in pic_server.c, line 43: esp_camera_fb_return(esp_camera_fb_get()); frame = esp_camera_fb_get();

So, do I have to do the same in my code? Because the examples from esp32-camera repository do not show that king of code in the examples. It seems like a major difference to me

Thank you for your patient explanation. Firstly, we should talk about how the current driver receives image data. After the initialization of the sensor is completed, the sensor will continuously collect data and send it to ESP32. When esp32 has an idle framebuffer, the received data is stored in the buffer. If there is no idle buffer, ESP32 will only stop receiving data, while the sensor is still collecting data. When the driver is working in GRAB_LASTEST mode, esp32 always tries to cache the latest data to the buffer. In this mode, the value of fb_count must be greater than 2. When the driver is working in GRAB_WHEN_EMPTY mode, esp32 will stop working after filling fb_count buffers. The value of fb_count in the sample program is 1. In order to receive the latest data every time the webpage is refreshed, I always consume the old data (by esp_camera_fb_return(esp_camera_fb_get());) in the program first and then retrieve the latest data again.

rbruneau-altyor commented 1 year ago

Thank you for all these details,

So, I should either use: 1) fb_count = 2 and GRAB_LATEST or 2) fb_count = 1, GRAB_WHEN_EMPTY and esp_camera_fb_return(esp_camera_fb_get()); to consume the old data

Is that right?

AthenasArch commented 1 year ago

Can someone help me, I have the camera initialization problem.

the software returns that the camera is not supported:

ESP-ROM: esp32s3-20210327 Build: Mar 27 2021 rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:1 load:0x3fce3808,len:0x44c load:0x403c9700,len:0xbe4 load:0x403cc700,len:0x2a38 entry 0x403c98d4

E (33) camera: Detected camera not supported. E (33) camera: Camera probe failed with error 0x106(ESP_ERR_NOT_SUPPORTED) Camera init failed with error 0x106

ESP32-S3 - Platformio - Arduino.

#include 
#include "esp_camera.h"
#include 

// ===================
// Select camera model
// ===================
//#define CAMERA_MODEL_WROVER_KIT // Has PSRAM
//#define CAMERA_MODEL_ESP_EYE // Has PSRAM
#define CAMERA_MODEL_ESP32S3_EYE // Has PSRAM
//#define CAMERA_MODEL_M5STACK_PSRAM // Has PSRAM
//#define CAMERA_MODEL_M5STACK_V2_PSRAM // M5Camera version B Has PSRAM
//#define CAMERA_MODEL_M5STACK_WIDE // Has PSRAM
//#define CAMERA_MODEL_M5STACK_ESP32CAM // No PSRAM
//#define CAMERA_MODEL_M5STACK_UNITCAM // No PSRAM
//#define CAMERA_MODEL_AI_THINKER // Has PSRAM
//#define CAMERA_MODEL_TTGO_T_JOURNAL // No PSRAM
// ** Espressif Internal Boards **
//#define CAMERA_MODEL_ESP32_CAM_BOARD
//#define CAMERA_MODEL_ESP32S2_CAM_BOARD
//#define CAMERA_MODEL_ESP32S3_CAM_LCD

#include "camera_pins.h"

#define USE_OV2640 0

// ===========================
// Enter your WiFi credentials
// ===========================
const char* ssid     = "Athenas 2.4G";
const char* password = "HILGEMBERG";

sensor_t * s;

void startCameraServer();
void camera_ini(void);

void setup() {
    Serial.begin(115200);
    Serial.setDebugOutput(true);
    Serial.println();
    // camera_ini();

    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;
#if USE_OV2640
    config.xclk_freq_hz = 20000000;
    config.frame_size = FRAMESIZE_UXGA;
    config.pixel_format = PIXFORMAT_JPEG; // for streaming
    config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
    config.fb_location = CAMERA_FB_IN_PSRAM;
    config.jpeg_quality = 12;
    config.fb_count = 1;
#else 
    config.xclk_freq_hz = 10000000;
    config.frame_size = FRAMESIZE_VGA;
    config.pixel_format = PIXFORMAT_RGB565; // for streaming
    config.grab_mode = CAMERA_GRAB_LATEST;
    config.fb_location = CAMERA_FB_IN_PSRAM;
    config.jpeg_quality = 6;
    config.fb_count = 2;
#endif
    // if PSRAM IC present, init with UXGA resolution and higher JPEG quality
    // for larger pre-allocated frame buffer.
    if(psramFound()){
        config.jpeg_quality = 10;
        config.fb_count = 2;
        config.grab_mode = CAMERA_GRAB_LATEST;
    } else {
        // Limit the frame size when PSRAM is not available
        config.frame_size = FRAMESIZE_SVGA;
        config.fb_location = CAMERA_FB_IN_DRAM;
    }

    // camera init
    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();
    // initial sensors are flipped vertically and colors are a bit saturated
    s->set_vflip(s, 1); // flip it back
    s->set_brightness(s, 1); // up the brightness just a bit
    s->set_saturation(s, 0); // lower the saturation

    WiFi.begin(ssid, password);
    WiFi.setSleep(false);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("");
    Serial.println("WiFi connected");

    startCameraServer();

    Serial.print("Camera Ready! Use 'http://");
    Serial.print(WiFi.localIP());
    Serial.println("' to connect");
}

void loop() {
  // Do nothing. Everything is done in another task by the web server
  delay(10000);
}
rbruneau-altyor commented 1 year ago

Try tuning the xclk_freq_hz parameter as well as the I2C speed. I used 16MHz for XCLK and 800k for I2C, may be you can try that first. If it does not work, I suggest you open another issue as your problem is probably not related to the original issue here

AthenasArch commented 1 year ago

Sorry for my ignorance, but where can I change the i2c speed to 800k, I'm not finding where to make this change.

rbruneau-altyor commented 1 year ago

I am not familiar with ESP-IDF combined with Arduino environment. When using ESP-IDF, this option is situated in sdkconfig file, where you also enable the camera support. Do you have something similar in your project?

AthenasArch commented 1 year ago

the code I sent earlier was tested on ESP32-S3, and I didn't get any results.

Now this code I got a different result, it's using ESP32-CAM, but I still couldn't make it work.

have you seen this log?


#include "esp_camera.h"
// #include "camera_index.h"
#include "Arduino.h"
// #include "fd_forward.h"
//#include "FS.h"                // SD Card ESP32
//#include "SD_MMC.h"            // SD Card ESP32
#include "soc/soc.h"           // Disable brownour problems
#include "soc/rtc_cntl_reg.h"  // Disable brownour problems
#include "driver/rtc_io.h"
//#include             // read and write from flash memory

// define the number of bytes you want to access
#define EEPROM_SIZE 1

#define CONFIG_CAMERA_CONVERTER_ENABLED 1

#define USE_OV2640 0

#include 
#include 
#include 
TFT_eSPI tft = TFT_eSPI();
TFT_eFEX  fex = TFT_eFEX(&tft);

camera_fb_t *fb1 = NULL;
camera_fb_t *fb2 = NULL;
camera_fb_t *current_fb = NULL;
bool buffer_ready = false;

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

//Controle de foco/exposição automatico 
#define MAX_BRIGHTNESS 170 // valor máximo de brilho [200/0-255]
#define MIN_BRIGHTNESS 70 // valor mínimo de brilho [50/0-255] 
#define AEC_STEP 100 // passo de ajuste do AEC [50] velocidade de atualzação 
#define AGC_GAIN_STEP 10 // passo de ajuste do ganho do AGC [1] velocidade de atualzação 

int pictureNumber = 0;

sensor_t * s;

unsigned long lastButtonPress = 0;
const unsigned long debounceTime = 200; // Tempo em milissegundos
int specialEffect = 0;

// https://github.com/espressif/esp32-camera/issues/545

void camera_ini(void);
void display_ini(void);

void setup() {
    WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
    // put your setup code here, to run once:
    Serial.begin(115200);
    Serial.println("V1.0.16 - Inicializa comunicacao Serial");
    camera_ini();
    display_ini();
}

void loop() {
    camera_fb_t * fb = NULL;

    if (buffer_ready) {
        // Swap the two frame buffers
        if (current_fb == fb1) {
        current_fb = fb2;
        } else {
        current_fb = fb1;
        }
        // Capture a new frame from the camera
        esp_camera_fb_return(current_fb);
        current_fb = esp_camera_fb_get();
    }

    if (buffer_ready) {
        // Display the current frame buffer using a fast DMA transfer
        tft.pushImageDMA(0, 0, current_fb->width, current_fb->height, (uint16_t*)current_fb->buf);
    }

    // Take Picture with Camera
    fb = esp_camera_fb_get(); 
    if(!fb) {
        Serial.println("Camera capture failed");
        return;
    }
    else{
        //tft.fillScreen(random(0xFFFF));
        fex.drawJpg((const uint8_t*)fb->buf, fb->len,0,0,240,240);
    }
    esp_camera_fb_return(fb); 
}

void dmaTransferComplete() {
    buffer_ready = true;
}

void camera_ini(void){
    Serial.println("Inicializa a camera...");

    camera_config_t camera_config = {
        .pin_pwdn       = PWDN_GPIO_NUM,
        .pin_reset      = RESET_GPIO_NUM,
        .pin_xclk       = XCLK_GPIO_NUM,
        .pin_sccb_sda   = SIOD_GPIO_NUM,
        .pin_sccb_scl   = SIOC_GPIO_NUM,

        .pin_d7         = Y9_GPIO_NUM,
        .pin_d6         = Y8_GPIO_NUM,
        .pin_d5         = Y7_GPIO_NUM,
        .pin_d4         = Y6_GPIO_NUM,
        .pin_d3         = Y5_GPIO_NUM,
        .pin_d2         = Y4_GPIO_NUM,
        .pin_d1         = Y3_GPIO_NUM,
        .pin_d0         = Y2_GPIO_NUM,
        .pin_vsync      = VSYNC_GPIO_NUM,
        .pin_href       = HREF_GPIO_NUM,
        .pin_pclk       = PCLK_GPIO_NUM,

#if USE_OV2640
        .xclk_freq_hz   = 20000000,
        .ledc_timer     = LEDC_TIMER_0,
        .ledc_channel   = LEDC_CHANNEL_0,
        .pixel_format   = PIXFORMAT_JPEG, // PIXFORMAT_YUV422, // ,
        .frame_size     = FRAMESIZE_240X240, // , // FRAMESIZE_QVGA, // FRAMESIZE_240X240,
        .jpeg_quality   = 12,
        .fb_count       = 4,
        .grab_mode      = CAMERA_GRAB_LATEST
#else 
        .xclk_freq_hz   = 16000000,
        .ledc_timer     = LEDC_TIMER_0,
        .ledc_channel   = LEDC_CHANNEL_0,
        .pixel_format   = PIXFORMAT_RGB565, // PIXFORMAT_YUV422, // PIXFORMAT_JPEG,
        .frame_size     = FRAMESIZE_QVGA, // FRAMESIZE_240X240, // FRAMESIZE_QVGA, // FRAMESIZE_240X240,
        .jpeg_quality   = 12,
        .fb_count       = 2,
        .grab_mode      = CAMERA_GRAB_LATEST
#endif
    };
    camera_config.fb_location = CAMERA_FB_IN_PSRAM; 

    Serial.println("Define pinos camera");

    Serial.println("Obtem os bufers");

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

    Serial.printf("Pixel Format: %d\n", camera_config.pixel_format);
    Serial.printf("Frame Size: %d\n", camera_config.frame_size);
    Serial.printf("JPEG Quality: %d\n", camera_config.jpeg_quality);

    // right here
    s = esp_camera_sensor_get();
    pinMode(12, INPUT_PULLUP);

    if (s->id.PID == BF3005_PID) {
        Serial.println("Camera BF3005 detectada");
    } else {
        Serial.print("Camera desconhecida detectada: ");
        Serial.println(s->id.PID);
        return; // Finaliza se a câmera não for a esperada
    }

    Serial.println("Configurando parametros da camera");
    //Comandos a baixo servem para controle do sensor Luz, imagem, posição... 

    Serial.println("Configuracao da camera concluida");
}

void display_ini(void){
    tft.begin();
    tft.setRotation(0);  // 0 & 2 Portrait. 1 & 3 landscape (rotação de tela)
    tft.fillScreen(TFT_BLACK);
}

void adjust_aec_agc(camera_fb_t *fb) {
    // calcular o brilho médio da imagem
    int brightness = 0;
    for (int i = 0; i < fb->len; i++) {
        brightness += fb->buf[i];
    }
    brightness /= fb->len;

    // ajustar o valor do AEC e do ganho do AGC com base no brilho da imagem
    sensor_t *s = esp_camera_sensor_get();
    if (brightness > MAX_BRIGHTNESS) {
        // diminuir a exposição e o ganho se o brilho estiver muito alto
        s->set_exposure_ctrl(s, 1);
        s->set_aec_value(s, s->status.aec_value - AEC_STEP);
        s->set_agc_gain(s, s->status.agc_gain - AGC_GAIN_STEP);
    } else if (brightness < MIN_BRIGHTNESS) {
        // aumentar a exposição e o ganho se o brilho estiver muito baixo
        s->set_exposure_ctrl(s, 1);
        s->set_aec_value(s, s->status.aec_value + AEC_STEP);
        s->set_agc_gain(s, s->status.agc_gain + AGC_GAIN_STEP);
    }
}

//Controle de brilho automatico 
void adjust_brightness(camera_fb_t *fb) {
    // calcular o brilho médio da imagem
    int brightness = 0;
    for (int i = 0; i < fb->len; i++) {
        brightness += fb->buf[i];
    }
    brightness /= fb->len;

    // ajustar o valor do brilho com base no brilho da imagem
    sensor_t *s = esp_camera_sensor_get();
    if (brightness > MAX_BRIGHTNESS) {
        // diminuir o brilho se estiver muito alto
        s->set_brightness(s, -2);
    } else if (brightness < MIN_BRIGHTNESS) {
        // aumentar o brilho se estiver muito baixo
        s->set_brightness(s, -1);
    } else {
        // manter o brilho se estiver dentro do intervalo aceitável
        s->set_brightness(s, 0);
    }
}

Camera capture failed E (17851) cam_hal: FB-SIZE: 149760 != 153600 E (17885) cam_hal: FB-SIZE: 149760 != 153600 E (17918) cam_hal: FB-SIZE: 149760 != 153600 E (17952) cam_hal: FB-SIZE: 149760 != 153600 E (17986) cam_hal: FB-SIZE: 149760 != 153600

WangYuxin-esp commented 1 year ago

the code I sent earlier was tested on ESP32-S3, and I didn't get any results.

Now this code I got a different result, it's using ESP32-CAM, but I still couldn't make it work.

have you seen this log?

include "esp_camera.h"

// #include "camera_index.h"

include "Arduino.h"

// #include "fd_forward.h" //#include "FS.h" // SD Card ESP32 //#include "SD_MMC.h" // SD Card ESP32

include "soc/soc.h" // Disable brownour problems

include "soc/rtc_cntl_reg.h" // Disable brownour problems

include "driver/rtc_io.h"

//#include // read and write from flash memory

// define the number of bytes you want to access

define EEPROM_SIZE 1

define CONFIG_CAMERA_CONVERTER_ENABLED 1

define USE_OV2640 0

include

include

include

TFT_eSPI tft = TFT_eSPI(); TFT_eFEX fex = TFT_eFEX(&tft);

camera_fb_t fb1 = NULL; camera_fb_t fb2 = NULL; camera_fb_t *current_fb = NULL; bool buffer_ready = false;

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

//Controle de foco/exposição automatico

define MAX_BRIGHTNESS 170 // valor máximo de brilho [200/0-255]

define MIN_BRIGHTNESS 70 // valor mínimo de brilho [50/0-255]

define AEC_STEP 100 // passo de ajuste do AEC [50] velocidade de atualzação

define AGC_GAIN_STEP 10 // passo de ajuste do ganho do AGC [1] velocidade de atualzação

int pictureNumber = 0;

sensor_t * s;

unsigned long lastButtonPress = 0; const unsigned long debounceTime = 200; // Tempo em milissegundos int specialEffect = 0;

// https://github.com/espressif/esp32-camera/issues/545

void camera_ini(void); void display_ini(void);

void setup() { WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector // put your setup code here, to run once: Serial.begin(115200); Serial.println("V1.0.16 - Inicializa comunicacao Serial"); camera_ini(); display_ini(); }

void loop() { camera_fb_t * fb = NULL;

if (buffer_ready) {
    // Swap the two frame buffers
    if (current_fb == fb1) {
    current_fb = fb2;
    } else {
    current_fb = fb1;
    }
    // Capture a new frame from the camera
    esp_camera_fb_return(current_fb);
    current_fb = esp_camera_fb_get();
}

if (buffer_ready) {
    // Display the current frame buffer using a fast DMA transfer
    tft.pushImageDMA(0, 0, current_fb->width, current_fb->height, (uint16_t*)current_fb->buf);
}

// Take Picture with Camera
fb = esp_camera_fb_get(); 
if(!fb) {
    Serial.println("Camera capture failed");
    return;
}
else{
    //tft.fillScreen(random(0xFFFF));
    fex.drawJpg((const uint8_t*)fb->buf, fb->len,0,0,240,240);
}
esp_camera_fb_return(fb); 

}

void dmaTransferComplete() { buffer_ready = true; }

void camera_ini(void){ Serial.println("Inicializa a camera...");

camera_config_t camera_config = {
    .pin_pwdn       = PWDN_GPIO_NUM,
    .pin_reset      = RESET_GPIO_NUM,
    .pin_xclk       = XCLK_GPIO_NUM,
    .pin_sccb_sda   = SIOD_GPIO_NUM,
    .pin_sccb_scl   = SIOC_GPIO_NUM,

    .pin_d7         = Y9_GPIO_NUM,
    .pin_d6         = Y8_GPIO_NUM,
    .pin_d5         = Y7_GPIO_NUM,
    .pin_d4         = Y6_GPIO_NUM,
    .pin_d3         = Y5_GPIO_NUM,
    .pin_d2         = Y4_GPIO_NUM,
    .pin_d1         = Y3_GPIO_NUM,
    .pin_d0         = Y2_GPIO_NUM,
    .pin_vsync      = VSYNC_GPIO_NUM,
    .pin_href       = HREF_GPIO_NUM,
    .pin_pclk       = PCLK_GPIO_NUM,

if USE_OV2640

    .xclk_freq_hz   = 20000000,
    .ledc_timer     = LEDC_TIMER_0,
    .ledc_channel   = LEDC_CHANNEL_0,
    .pixel_format   = PIXFORMAT_JPEG, // PIXFORMAT_YUV422, // ,
    .frame_size     = FRAMESIZE_240X240, // , // FRAMESIZE_QVGA, // FRAMESIZE_240X240,
    .jpeg_quality   = 12,
    .fb_count       = 4,
    .grab_mode      = CAMERA_GRAB_LATEST

else

    .xclk_freq_hz   = 16000000,
    .ledc_timer     = LEDC_TIMER_0,
    .ledc_channel   = LEDC_CHANNEL_0,
    .pixel_format   = PIXFORMAT_RGB565, // PIXFORMAT_YUV422, // PIXFORMAT_JPEG,
    .frame_size     = FRAMESIZE_QVGA, // FRAMESIZE_240X240, // FRAMESIZE_QVGA, // FRAMESIZE_240X240,
    .jpeg_quality   = 12,
    .fb_count       = 2,
    .grab_mode      = CAMERA_GRAB_LATEST

endif

};
camera_config.fb_location = CAMERA_FB_IN_PSRAM; 

Serial.println("Define pinos camera");

Serial.println("Obtem os bufers");

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

Serial.printf("Pixel Format: %d\n", camera_config.pixel_format);
Serial.printf("Frame Size: %d\n", camera_config.frame_size);
Serial.printf("JPEG Quality: %d\n", camera_config.jpeg_quality);

// right here
s = esp_camera_sensor_get();
pinMode(12, INPUT_PULLUP);

if (s->id.PID == BF3005_PID) {
    Serial.println("Camera BF3005 detectada");
} else {
    Serial.print("Camera desconhecida detectada: ");
    Serial.println(s->id.PID);
    return; // Finaliza se a câmera não for a esperada
}

Serial.println("Configurando parametros da camera");
//Comandos a baixo servem para controle do sensor Luz, imagem, posição... 

Serial.println("Configuracao da camera concluida");

}

void display_ini(void){ tft.begin(); tft.setRotation(0); // 0 & 2 Portrait. 1 & 3 landscape (rotação de tela) tft.fillScreen(TFT_BLACK); }

void adjust_aec_agc(camera_fb_t *fb) { // calcular o brilho médio da imagem int brightness = 0; for (int i = 0; i < fb->len; i++) { brightness += fb->buf[i]; } brightness /= fb->len;

// ajustar o valor do AEC e do ganho do AGC com base no brilho da imagem
sensor_t *s = esp_camera_sensor_get();
if (brightness > MAX_BRIGHTNESS) {
    // diminuir a exposição e o ganho se o brilho estiver muito alto
    s->set_exposure_ctrl(s, 1);
    s->set_aec_value(s, s->status.aec_value - AEC_STEP);
    s->set_agc_gain(s, s->status.agc_gain - AGC_GAIN_STEP);
} else if (brightness < MIN_BRIGHTNESS) {
    // aumentar a exposição e o ganho se o brilho estiver muito baixo
    s->set_exposure_ctrl(s, 1);
    s->set_aec_value(s, s->status.aec_value + AEC_STEP);
    s->set_agc_gain(s, s->status.agc_gain + AGC_GAIN_STEP);
}

}

//Controle de brilho automatico void adjust_brightness(camera_fb_t *fb) { // calcular o brilho médio da imagem int brightness = 0; for (int i = 0; i < fb->len; i++) { brightness += fb->buf[i]; } brightness /= fb->len;

// ajustar o valor do brilho com base no brilho da imagem
sensor_t *s = esp_camera_sensor_get();
if (brightness > MAX_BRIGHTNESS) {
    // diminuir o brilho se estiver muito alto
    s->set_brightness(s, -2);
} else if (brightness < MIN_BRIGHTNESS) {
    // aumentar o brilho se estiver muito baixo
    s->set_brightness(s, -1);
} else {
    // manter o brilho se estiver dentro do intervalo aceitável
    s->set_brightness(s, 0);
}

}

Camera capture failed E (17851) cam_hal: FB-SIZE: 149760 != 153600 E (17885) cam_hal: FB-SIZE: 149760 != 153600 E (17918) cam_hal: FB-SIZE: 149760 != 153600 E (17952) cam_hal: FB-SIZE: 149760 != 153600 E (17986) cam_hal: FB-SIZE: 149760 != 153600

For BF3005, you can try using Format = RGB565, XCLK=10M, and Framesize = VGA.