0

I'm working on a project using the ESP32-CAM module, where I capture an image with the camera and send it to a server using an HTTP POST request. The server then processes the image using an AI API. The image transmission part works correctly, but approximately 6 seconds after sending the image, the ESP32 reports an error: "Error sending HTTP POST request: -11." Additionally, it doesn't wait for the server's response. I'm puzzled by this behavior and would appreciate any insights into why it's happening.

My ESP32 code :

#include "WiFi.h"
#include "esp_camera.h"
#include "Arduino.h"
#include "soc/soc.h"           // Disable brownout problems
#include "soc/rtc_cntl_reg.h"  // Disable brownout problems
#include "driver/rtc_io.h"
#include <HTTPClient.h>

// Replace with your network credentials
const char* ssid = "WIFI_NAME";
const char* password = "WIFI_PSSWD";

// Replace with your PHP page URL
const char* phpURL = "http://192.168.0.116:80/index.php";

// OV2640 camera module pins (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

void setup() {
  // Serial port for debugging purposes
  Serial.begin(115200);

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }

  // Turn-off the 'brownout detector'
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

  // OV2640 camera module pins
  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;

  if (psramFound()) {
    config.frame_size = FRAMESIZE_UXGA;
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }

  // 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();
  }

  //Let the camera adapt to the environment (light, exposure, etc..)
  camera_fb_t* fb = nullptr;
  // Skip first N frames.
  for (int i = 0; i < 3; i++) {
    fb = esp_camera_fb_get();
    esp_camera_fb_return(fb);
    fb = nullptr;
    delay(500);  // delay between photos
  }

  // Set timeout for HTTP client
  HTTPClient http;
  http.setTimeout(60000);  // Set timeout to 60 seconds (adjust as needed)

  // Take photo and send to PHP page
  captureAndSendPhoto();
}

void loop() {
  delay(10000);
  captureAndSendPhoto();
}

void captureAndSendPhoto() {
  camera_fb_t* fb = NULL;  // pointer

  // Take a photo with the camera
  Serial.println("Taking a photo...");
  fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }

  // Send HTTP POST request to PHP page
  Serial.println("Sending photo to PHP page...");
  HTTPClient http;
  http.begin(phpURL);
  http.addHeader("Content-Type", "image/jpeg");
  int httpResponseCode = http.POST((uint8_t*)fb->buf, fb->len);

  // Check for errors
  if (httpResponseCode > 0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);

    // Print the content of the page
    String response = http.getString();
    Serial.println("Response content:");
    Serial.println(response);
  } else {
    Serial.print("Error sending HTTP POST request: ");
    Serial.println(httpResponseCode);
  }

  // Free up memory
  esp_camera_fb_return(fb);
}

And the PHP code on server-side :

<?php
// Check if raw image data was sent via POST
if ($_SERVER['REQUEST_METHOD'] === 'POST' && null !== (file_get_contents("php://input"))) {
        // Retrieve the API key from the request header
        $headers = getallheaders();
        $apiKeyShuttle = isset($headers['Shuttle_API_Key']) ? str_replace('Bearer ', '', $headers['Shuttle_API_Key']) : '';
        $apiKeyClarifai = isset($headers['Clarifai_API_Key']) ? str_replace('Bearer ', '', $headers['Clarifai_API_Key']) : '';
       
        // Define the directory to save the image
        $uploadDir = '/var/www/html/'; // Change this to the desired directory
    
        // Generate a unique filename for the image
        $filename = uniqid() . '.jpg';
    
        // Combine the directory and filename
        $filePath = $uploadDir . $filename;
    
        // Retrieve raw POST data
        $rawData = file_get_contents("php://input");
    
        $image= "http://theyoungmaker.ddns.net:8332/" . $filename;
        // Save the raw image data to a file
        if (file_put_contents($filePath, $rawData) !== false) {
            http_response_code(200);
            echo "Saved the image.";
        // Pass the response data to Image_AI_Speech.php using another POST request
        $Image_AI_Speech_URL = "http://whisper.local/Image_AI_Speech.php";

        $json = json_encode(['image' => $image]);

        $ch = curl_init($Image_AI_Speech_URL);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            "Shuttle_API_Key: Bearer $apiKeyShuttle",
            "Clarifai_API_Key: Bearer $apiKeyClarifai",
            "Content-Type: application/json"
        ]);

        $imageResponse = curl_exec($ch);
        $err = curl_error($ch);

        curl_close($ch);

        if ($err) {
            echo "cURL Error #:" . $err;
        } else {
            echo $imageResponse; 
        }
            // echo "Image uploaded successfully. File saved as: " . $filename;
        } else {
            // If unable to save the file, return an error message
            http_response_code(500);
            echo "Error: Failed to save image.";
        }
    }
 else {
    // If no image data was received, return an error message
    http_response_code(400);
    echo "Error: No image data received.";
}
?>

Additional Information:

  • The ESP32-CAM module is connected to a Wi-Fi network and communicates with the server via HTTP.

  • The server receives the image and processes it by saving it as a jpg file without any issues

  • The error occurs approximately 6 seconds after sending the image, and the ESP32 doesn't wait for the server's response.

  • I've tried troubleshooting by increasing the timeout both on the server and on the ESP32, but the issue persists.

  • Requests seems to works fine with Reqbin

Any insights or suggestions on resolving this issue would be greatly appreciated.

3
  • The issue might related to the buffering logic. You could try to store the buffer data to another media (e.g. SPI Flash Memory, SD Card, etc) until the buffer was saved. Also replace the code reading the new media content and send to server. Commented Mar 5, 2024 at 6:30
  • But I don't think it is that because the server successfully receive the image and it saves it in a jpg file successfully. Commented Mar 5, 2024 at 17:37
  • try add http.stop(); before esp_camera_fb_return(fb); Commented Mar 6, 2024 at 9:57

0

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.