2

I'm using ESP32-CAM for one of my project. The project is to capture image continuously 1 second duration and send to server. I can capture image and send it to server successfully.

But the problem is, it is not send current image frame. I think it sends image from its buffer which I want to clear. I mean I want to clear its frame buffer after capturing and image to get current image.

Thanks.

Here is my code :

#include <Arduino.h>
#include <WiFi.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "esp_camera.h"
const char* ssid = "ABC";
const char* password = "def";

//http://192.186.86.5:8787/Home/UploadFile
String serverName = "192.168.86.5";
//String serverName = "example.com";
String serverPath = "/Home/UploadFile";
const int serverPort = 8787;
WiFiClient client;

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

const int timerInterval = 10000;
unsigned long previousMillis = 0;


int image_serial_no = 0;


void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); 
  Serial.begin(115200);

//Flash - pin 4

pinMode(4, OUTPUT);
digitalWrite(4, LOW);



  WiFi.mode(WIFI_STA);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);  
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.print("ESP32-CAM IP Address: ");
  Serial.println(WiFi.localIP());

  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.pixel_format = PIXFORMAT_JPEG;//PIXFORMAT_JPEG

  // init with high specs to pre-allocate larger buffers
  if(psramFound()){
    config.frame_size = FRAMESIZE_UXGA;//FRAMESIZE_SVGA
    config.jpeg_quality = 6;  //0-63 lower number means higher quality
    config.fb_count = 10;//2  -- May be light
  } else {
    config.frame_size = FRAMESIZE_UXGA;//FRAMESIZE_CIF
    config.jpeg_quality = 7;  //0-63 lower number means higher quality
    config.fb_count = 9;//1  -- May be light
  }

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

  sendPhoto(); 
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= timerInterval) {
    sendPhoto();
    previousMillis = currentMillis;
  }
}

String sendPhoto() {
  String getAll;
  String getBody;


  image_serial_no++;

//Flash - On
digitalWrite(4, HIGH);




  camera_fb_t * fb = NULL;
  fb = esp_camera_fb_get();
  if(!fb) {
    Serial.println("Camera capture failed");
    delay(1000);
    ESP.restart();
  }

  Serial.println("Connecting to server: " + serverName);

  if (client.connect(serverName.c_str(), serverPort)) {
    Serial.println("Connection successful!");    
    String head = "--Zitu\r\nContent-Disposition: form-data; name=\"file\"; filename=\" "+String(image_serial_no)+".jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
    String tail = "\r\n--Zitu--\r\n";

    uint32_t imageLen = fb->len;
    uint32_t extraLen = head.length() + tail.length();
    uint32_t totalLen = imageLen + extraLen;

    client.println("POST " + serverPath + " HTTP/1.1");
    client.println("Host: " + serverName);
    client.println("Content-Length: " + String(totalLen));
    client.println("Content-Type: multipart/form-data; boundary=Zitu");
    client.println();
    client.print(head);

    uint8_t *fbBuf = fb->buf;
    size_t fbLen = fb->len;
    for (size_t n=0; n<fbLen; n=n+1024) {
      if (n+1024 < fbLen) {
        client.write(fbBuf, 1024);
        fbBuf += 1024;
      }
      else if (fbLen%1024>0) {
        size_t remainder = fbLen%1024;
        client.write(fbBuf, remainder);
      }
    }   
    client.print(tail);

    esp_camera_fb_return(fb);

    int timoutTimer = 10000;
    long startTimer = millis();
    boolean state = false;

    while ((startTimer + timoutTimer) > millis()) {
      Serial.print(".");
      delay(100);      
      while (client.available()) {
        char c = client.read();
        if (c == '\n') {
          if (getAll.length()==0) { state=true; }
          getAll = "";
        }
        else if (c != '\r') { getAll += String(c); }
        if (state==true) { getBody += String(c); }
        startTimer = millis();
      }
      if (getBody.length()>0) { break; }
    }
    Serial.println();
    client.stop();
    Serial.println(getBody);
  }
  else {
    getBody = "Connection to " + serverName +  " failed.";
    Serial.println(getBody);
  }





//Flash - Off
digitalWrite(4, LOW);



  return getBody;
}
2
  • 1
    Hi Maruf, we can't help you without your code. Please post the code as a Minimal, Reproducible Example. Commented Jun 1, 2022 at 8:23
  • Edited & share my code. Commented Jun 1, 2022 at 9:52

3 Answers 3

3

I don't have a clean solution for this but rather a workaround.

First, inside setup, set the frame buffer to 1 so only one frame will be buffered. It cannot be set to 0, so there always is one image too much.

config.fb_count = 1;

Next, when reading the image, read it twice. This will clear the buffer and force the ESP32 to fill it up again with the fresh image. In the sendPhoto() function, edit this block

  camera_fb_t * fb = NULL;
  fb = esp_camera_fb_get();
  if(!fb) {
    Serial.println("Camera capture failed");
    delay(1000);
    ESP.restart();
  }

to this

  camera_fb_t * fb = NULL;
  fb = esp_camera_fb_get();
  esp_camera_fb_return(fb); // dispose the buffered image
  fb = NULL; // reset to capture errors
  fb = esp_camera_fb_get(); // get fresh image
  if(!fb) {
    Serial.println("Camera capture failed");
    delay(1000);
    ESP.restart();
  }  
Sign up to request clarification or add additional context in comments.

Comments

3

The only solution I have found to avoid that lag/delay with the buffered data is to add:

config.grab_mode = CAMERA_GRAB_LATEST;

after "camera_config_t config;"

Comments

0

If your ESP32 module has enough RAM, another solution is to set the frame buffer count to 2, and then set grab mode as CAMERA_GRAB_LATEST.

Example:

config.fb_count = 2;
config.grab_mode = CAMERA_GRAB_LATEST;

This is mentioned in the ESP32CAM libraryenter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.