Time-lapse Image Capture with ESP32 Cameras

Clocks

Three ways to shoot time-lapse videos from an ESP32 based camera system such as the ESP32-Cam and the ESP-EYE

This tutorial will explain how to use JavaScript to capture images, how to capture and write images to an microSD card reader and also how to capture and send images to a server on the internet. Using one of these techniques you can make time-lapse videos such as these:

Before following this tutorial make sure your camera and Arduino IDE are set up correctly by following this tutorial Ai-Thinker ESP32-CAM in the Arduino IDE

Time-lapse Capture via JavaScript

This is the easiest way to capture time-lapse images from your camera. It works using JavaScript in a web page to request a new image from the camera at an interval you choose.

JavaScript Version Screenshot

Download JavaScript Time-lapse

Paste the script above into a new Sketch and upload it to your device. Reset the device, look for the IP address in the Serial Monitor and connect to that IP address with your browser.

You can speed up or slow down the speed of the capture using the slider during the process.  When the capture has completed use the ‘Save page as’ menu or Ctrl+s to save the images.

This method doesn’t work it you want to capture thousands of frames because the browser won’t save everything if there are too many images.

Capture to the SD Card

The Ai-Thinker has a built-in Micro-SD card reader. This Sketch captures an image at the interval set in the Sketch and saves it to the SD card. If there is an available internet connection the Sketch retrieves the time from the internet and uses this in the filename. If there is no connection, files are named numerically. Be aware that without internet, if the device restarts it will begin overwriting existing files.

Download MicroSD Card Time-lapse

The card must be formatted to FAT32 and be 4GB or less. For some reason the ‘flash’ LED on the front is connected to one of the SD card pins so it glows brightly every time a file is written. I ended up putting black tape over it.

Upload a Capture to a Server

This the most complicated approach but once working, it’s the easiest to manage and keep an eye on progress. Every time an image is captured it is sent to a server via http POST for saving. This would make an ideal solution for an online web cam.

Download Time-lapse to Server

Some simple PHP to name and copy the uploaded image to a folder (don’t forget to add the opening <?php tag):

$received = file_get_contents('php://input');
$fileToWrite = "timelapse/upload - ".time().".jpg";
file_put_contents($fileToWrite, $received);

Making the time-lapse video

This is the easiest to follow guide I found to make the time-lapse video from your images: https://www.youtube.com/watch?v=JwF6I0iLGS4

References

Time formatting: http://www.cplusplus.com/reference/ctime/strftime/
Code for SD card: https://github.com/espressif/esp-idf/tree/master/examples/storage/sd_card
Tips for making time-lapse videos: http://www.enriquepacheco.com/10-tips-for-shooting-time-lapse/

138 Replies to “Time-lapse Image Capture with ESP32 Cameras”

  1. Vicente says:

    Hello,

    Congratulations for your post, I’ve tried all the moldes and I have problems with the “Upload a Capture to a Server” model. I never get any picture in the server
    This is the message in the serial monitor.
    Can you please let me know what i’m doing wrong?
    Thank you for your help
    __________
    Taking picture…
    HTTP_EVENT_ON_CONNECTED

    HTTP_EVENT_ON_HEADER, key=Date, value=Tue, 14 May 2019 20:11:51 GMT
    HTTP_EVENT_ON_HEADER, key=Server, value=Apache
    HTTP_EVENT_ON_HEADER, key=Vary, value=Accept-Encoding
    HTTP_EVENT_ON_HEADER, key=Content-Length, value=145
    HTTP_EVENT_ON_HEADER, key=Content-Type, value=text/html; charset=UTF-8
    HTTP_EVENT_ON_DATA, len=145
    HTTP_EVENT_ON_FINISH
    esp_http_client_get_status_code: 200
    HTTP_EVENT_DISCONNECTED

    1. WordBot says:

      It looks like it’s working on the ESP32. Do you have an error log on the server?

  2. Mile says:

    Terrific programs!

    Question 1: Is there a mechanism to switch off the “flash” led?
    I’ve been scanning the ESP-CAM schematic and driver code. It seems to be driven by HS2_DATA1 GPIO4? but I cannot find who turns it on.
    Question 2: Do you know of a mp4 recorder onto sd card program? Or is that possible with this chip/cam combo?

    Thanks

    1. WordBot says:

      Thanks! DATA1 is one of the SD card data lines so whenever data is written the LED lights up. I don’t know how it still writes data when this is happening! I’ve looked into MP4 but not found anything yet.

  3. Mike says:

    Wow – that’s crazy. You are running a camera, and there is a giant white led flashing on and off as the “disk active” light — interfering with the camera if you take another picture before the write is done. It is marked “flash” on the schematic, but is does not turn on with the camera, but after the picture, during the write — so it is clearly not a flash to use in low light.

    There is a small led on the back that might be better used as “disk active” light.
    I see a small transistor marked J3Y just above the big led — i think there is room to de-solder that.

    I haven’t done it before, but I might try to grab some raspivid code, and write a video recorder.

    Thanks for the info.

  4. Najib says:

    Hi..

    Thank you for your script. I try upload a capture to the server with time lapse. In the serial monitor there are message:

    HTTP_EVENT_ON_HEADER, key=Date, value=Mon, 01 Jul 2019 13:34:27 GMT
    HTTP_EVENT_ON_HEADER, key=Server, value=Apache/2.4.25 (Raspbian)
    HTTP_EVENT_ON_HEADER, key=Content-Length, value=0
    HTTP_EVENT_ON_HEADER, key=Content-Type, value=text/html; charset=UTF-8
    HTTP_EVENT_ON_FINISH
    esp_http_client_get_status_code: 200
    HTTP_EVENT_DISCONNECTED
    Taking picture…

    but it’s like vicente’s problem, i cant find the picture. Are you have php script completely? Where i put the folder name which is the picture placed?

    Thank you
    Najib

    1. WordBot says:

      Hi, You might have to create a folder called timelapse in the same folder as the PHP script. Do you know PHP?

  5. Najib says:

    i got it, thank you so much.

  6. Roberto says:

    Hi!
    Thank for your code,I used the last example and it works perfectly!
    I would like to know if it possible to upload picture to server only when it detects some change on environment..is it possible to implement? thank you again!!

    1. WordBot says:

      Hi, I’m working on movement detection in the video field at the moment. It’s easy with a PIR sensor but you need a different board for this: https://robotzero.one/ttgo-security-camera-pir/

  7. Rizki Adi Saputra says:

    THANKS BRO!!!!
    CODE WORK 100% PERFECTLY ON MY ESP32 CAM! with esp to server method.
    searched this method for 3 days!

    1. WordBot says:

      No problem. I’m happy it worked for you. Feel free to mention the tutorial on Facebook etc so more people can find it.

  8. Roberto says:

    Hi again!
    I had an issue today without a clear explanation..the server code does not work anymore..inside the loop function it does not call take photo because the millis condition is never satisfied..so I used delay and it works but I don’t know why everything was working and suddenly not..probably is the millis?
    I do not understand!

    1. WordBot says:

      Hi,

      What value do have for capture_interval?

      The millis code below should be OK AFAIK. millis() is the time since the ESP32 was started so the first few loops you’ll get something like 10 – 0, 20 – 0, 30 – 0 for current_millis – last_capture_millis. If you have capture_interval at 20000 (20 secs) when the millis hit 20010 (for example) it should make last_captured_millis equal to 20010 and take a photo.

      current_millis = millis();
      if (current_millis – last_capture_millis > capture_interval) { // Take another picture
      last_capture_millis = millis();
      take_send_photo();
      }

      The problem with delay() is that it stops everything for that number of milliseconds so if your application takes 2 seconds to complete (in this case taking and sending a photo) you are actually taking a photo every 22 seconds. Things get really random timings if you have a short delay.

      1. Lutz says:

        Hi there,

        I had the same problem as Roberto.
        Everything went wonderfully for 71 minutes, then nothing worked.
        The cause is a timer overflow.
        Solution:
        unsigned long current_millis;
        unsigned long last_capture_millis = 0;
        Instead of:
        long current_millis;
        long last_capture_millis = 0;
        It’s been like this for days.

        Thanks for the example

        1. WordBot says:

          Hi and thanks for pointing out that error. I’ve been looking into this a bit and wondered if:
          unsigned long long current_millis;
          unsigned long long last_capture_millis = 0;
          would be better as reading the comments here: https://arduino.stackexchange.com/questions/12587/how-can-i-handle-the-millis-rollover it will ‘rollover’ at ~50 days twice and then break. What do you think?

  9. Vicente Tomás says:

    Congratulations for your post. Is it possible to use the sd library (SD.h) instead the Sdmmc?
    Thank you.

    1. WordBot says:

      Thanks! I’m not sure.. I remember something about the Arduino library for SD cards using a different connection method (i2C or SPI) to the Espressif driver I used.

  10. Christoph says:

    Hello!
    Unfortunately I have no experience with PHP. Is this code

    $received = file_get_contents(‘php://input’);
    $fileToWrite = “timelapse/upload – “.time().”.jpg”;
    file_put_contents($fileToWrite, $received);

    the complete content of the yourscript.php file? Or is at the end missing?

    Thanks for your answer!

    1. WordBot says:

      Hi, Yes, you need to enclose the code in tags like this:

      Code

      The end one is optional

      1. Alz says:

        I am getting this
        01:26:43.172 -> HTTP_EVENT_ON_HEADER, key=Content-Type, value=text/html; charset=UTF-8
        01:26:43.172 -> HTTP_EVENT_ON_HEADER, key=Server, value=Microsoft-IIS/7.5
        01:26:43.172 -> HTTP_EVENT_ON_HEADER, key=X-Powered-By, value=PHP/5.6.0
        01:26:43.172 -> HTTP_EVENT_ON_HEADER, key=X-Powered-By, value=ASP.NET
        01:26:43.172 -> HTTP_EVENT_ON_HEADER, key=Date, value=Fri, 11 Mar 2022 19:56:38 GMT
        01:26:43.172 -> HTTP_EVENT_ON_HEADER, key=Content-Length, value=0
        01:26:43.205 -> HTTP_EVENT_ON_FINISH
        01:26:43.205 -> esp_http_client_get_status_code: 500
        01:26:43.205 -> HTTP_EVENT_DISCONNECTED

        The issue is not sure where the image is getting stored on the server? as it is not visible .
        Also is it possible to combine code to save on sdcard and send to the server both at the same time?

        3) The code $fileToWrite = “timelapse/upload – “.time().”.jpg”; implies that the file is being written in the timelapse folder?

        1. WordBot says:

          esp_http_client_get_status_code: 500 is a server error so the PHP code isn’t correct.

          It should be fairly easy to combine the two scripts to get it to save on the sd card and post it.

          Yep.. you might need to create the ‘timelapse’ folder in the same location as the PHP file.

          1. Alz says:

            Super thanks for your reply. I could finally make it work.
            My progress so far
            1) I would save the image to microsd card
            2)Send pic to server (offcourse separately as 2 different sketches)
            Now I have been trying to combine the two that is take pic and save it to micro sd card and then send it to server.
            I am ok with interchanging the order
            So When I tried combining the code I get this in the serial monitor
            —-
            Mounting SD card…
            01:21:41.507 -> SD card mount successfully!
            01:23:35.380 -> Taking picture…
            01:23:35.380 -> /sdcard/capture_2022-04-05_01_23_34.jpg
            01:23:35.959 -> File saved: /sdcard/capture_2022-04-05_01_23_34.jpg

            The first part work but the pic is not getting sent to the server
            I am using the following code by combining the two sets of code.(I gave marked my wifi credentials as *** and domain as a dummy domain only in the code below for security. It works fine with my actual details. Thanks to your help earlier 😉
            Not sure what I am doing wrong ? Could you please suggest a way out to fix this?
            —–
            #include “esp_camera.h”
            #include
            #include “Arduino.h”
            // Time
            #include “time.h”
            #include “lwip/err.h”
            #include “lwip/apps/sntp.h”
            // MicroSD
            #include “driver/sdmmc_host.h”
            #include “driver/sdmmc_defs.h”
            #include “sdmmc_cmd.h”
            #include “esp_vfs_fat.h”
            //for server
            #include “esp_http_client.h”

            // Edit ssid, password, capture_interval:
            const char* ssid = “****”;
            const char* password = “****”;
            int capture_interval = 60000; // milliseconds between captures
            const char *post_url = “http://mydomain.com/yourscript.php”; // Location where images are POSTED
            // define post url 2 server

            long current_millis;
            long last_capture_millis = 0;
            static esp_err_t cam_err;
            static esp_err_t card_err;
            char strftime_buf[64];
            int file_number = 0;
            bool internet_connected = false;
            struct tm timeinfo;
            time_t now;

            // 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.begin(115200);

            if (init_wifi()) { // Connected to WiFi
            internet_connected = true;
            Serial.println(“Internet connected”);
            init_time();
            time(&now);
            setenv(“TZ”, “IST-5:30”, 1);
            tzset();
            }

            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;
            //init with high specs to pre-allocate larger buffers
            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
            cam_err = esp_camera_init(&config);
            if (cam_err != ESP_OK) {
            Serial.printf(“Camera init failed with error 0x%x”, cam_err);
            return;
            }
            // SD camera init
            card_err = init_sdcard();
            if (card_err != ESP_OK) {
            Serial.printf(“SD Card init failed with error 0x%x”, card_err);
            return;
            }
            }

            bool init_wifi()
            {
            int connAttempts = 0;
            Serial.println(“\r\nConnecting to: ” + String(ssid));
            WiFi.begin(ssid, password);
            while (WiFi.status() != WL_CONNECTED ) {
            delay(500);
            Serial.print(“.”);
            if (connAttempts > 10) return false;
            connAttempts++;
            }
            return true;
            }

            void init_time()
            {
            sntp_setoperatingmode(SNTP_OPMODE_POLL);
            sntp_setservername(0, “pool.ntp.org”);
            sntp_init();
            // wait for time to be set
            time_t now = 0;
            timeinfo = { 0 };
            int retry = 0;
            const int retry_count = 10;
            while (timeinfo.tm_year < (2016 – 1900) && ++retry buf, 1, fb->len, file);
            Serial.printf(“File saved: %s\n”, filename);
            } else {
            Serial.println(“Could not open file”);
            }
            fclose(file);
            esp_camera_fb_return(fb);
            free(filename);
            }

            static esp_err_t save_photo_dated()
            {
            Serial.println(“Taking picture…”);
            camera_fb_t *fb = esp_camera_fb_get();

            time(&now);
            localtime_r(&now, &timeinfo);
            strftime(strftime_buf, sizeof(strftime_buf), “%F_%H_%M_%S”, &timeinfo);

            char *filename = (char*)malloc(21 + sizeof(strftime_buf));
            sprintf(filename, “/sdcard/capture_%s.jpg”, strftime_buf);

            Serial.println(filename);
            FILE *file = fopen(filename, “w”);
            if (file != NULL) {
            size_t err = fwrite(fb->buf, 1, fb->len, file);
            Serial.printf(“File saved: %s\n”, filename);

            } else {
            Serial.println(“Could not open file”);
            }
            fclose(file);
            esp_camera_fb_return(fb);
            free(filename);
            }

            void save_photo()
            {
            if (timeinfo.tm_year event_id) {
            case HTTP_EVENT_ERROR:
            Serial.println(“HTTP_EVENT_ERROR”);
            break;
            case HTTP_EVENT_ON_CONNECTED:
            Serial.println(“HTTP_EVENT_ON_CONNECTED”);
            break;
            case HTTP_EVENT_HEADER_SENT:
            Serial.println(“HTTP_EVENT_HEADER_SENT”);
            break;
            case HTTP_EVENT_ON_HEADER:
            Serial.println();
            Serial.printf(“HTTP_EVENT_ON_HEADER, key=%s, value=%s”, evt->header_key, evt->header_value);
            break;
            case HTTP_EVENT_ON_DATA:
            Serial.println();
            Serial.printf(“HTTP_EVENT_ON_DATA, len=%d”, evt->data_len);
            if (!esp_http_client_is_chunked_response(evt->client)) {
            // Write out data
            // printf(“%.*s”, evt->data_len, (char*)evt->data);
            }
            break;
            case HTTP_EVENT_ON_FINISH:
            Serial.println(“”);
            Serial.println(“HTTP_EVENT_ON_FINISH”);
            break;
            case HTTP_EVENT_DISCONNECTED:
            Serial.println(“HTTP_EVENT_DISCONNECTED”);
            break;
            }
            return ESP_OK;
            }

            static esp_err_t take_send_photo()
            {
            Serial.println(“Taking picture…”);
            camera_fb_t * fb = NULL;
            esp_err_t res = ESP_OK;

            fb = esp_camera_fb_get();
            if (!fb) {
            Serial.println(“Camera capture failed”);
            return ESP_FAIL;
            }

            esp_http_client_handle_t http_client;

            esp_http_client_config_t config_client = {0};
            config_client.url = post_url;
            config_client.event_handler = _http_event_handler;
            config_client.method = HTTP_METHOD_POST;

            http_client = esp_http_client_init(&config_client);

            esp_http_client_set_post_field(http_client, (const char *)fb->buf, fb->len);

            esp_http_client_set_header(http_client, “Content-Type”, “image/jpg”);

            esp_err_t err = esp_http_client_perform(http_client);
            if (err == ESP_OK) {
            Serial.print(“esp_http_client_get_status_code: “);
            Serial.println(esp_http_client_get_status_code(http_client));
            }

            esp_http_client_cleanup(http_client);

            esp_camera_fb_return(fb);
            }
            void loop()
            {
            current_millis = millis();
            if (current_millis – last_capture_millis > capture_interval) { // Take another picture
            last_capture_millis = millis();
            save_photo();
            }
            }

            1. WordBot says:

              Hi, I think you need to redo your code a bit. The init_time function shouldn’t have any other code in it and the save_photo() in the loop doesn’t appear to do anything. Maybe write down the structure or flow you want on paper and then create that in code using my examples as reference.

  11. Christoph says:

    Thought so. Thanks for the clarification!

    Another question: Is it possible to upload the images to a web server without using PHP? It is not necessary to number the images. It is sufficient to save an image and overwrite the last saved one.
    Like: const char *post_url = “http://your-webserver.net/img.jpg”; // Location where images are POSTED

    I try to build a camera (as a part of a doorbell) that takes a picture after pressing a button and uploads it to a webserver (without PHP). The previously captured image should be overwritten.

    1. WordBot says:

      I can’t think of any way of doing this from the ESP32. You have to send the data (image) somewhere that can process it (save it as a file in this case). Maybe you could email the image https://github.com/mobizt/ESP32-Mail-Client or https://github.com/gpepe/esp8266-sendemail (see issues for fixes) ?

  12. Najib says:

    Hello,

    Thanks a lot for your code. Can i save video to sd card use esp32 cam? Why should use time-lapse? Thank you.

    1. WordBot says:

      Video might be possible at slow frame rates but I’ve not really looked into it that hard.

  13. James says:

    Hi,

    New to this, but your example is exactly what i need.

    i think i have got everything working, but i am not getting any picturs in my timelapse folder. if i enter the web address of the script into my browser manuall i get an empty file appear in my timelapse folder. but nothing from my ESP32.
    my serail output looks like:
    Taking picture…
    HTTP_EVENT_ON_CONNECTED

    HTTP_EVENT_ON_HEADER, key=Server, value=nginx
    HTTP_EVENT_ON_HEADER, key=Date, value=Sat, 20 Jul 2019 16:26:57 GMT
    HTTP_EVENT_ON_HEADER, key=Content-Type, value=text/html
    HTTP_EVENT_ON_HEADER, key=Content-Length, value=852
    HTTP_EVENT_ON_HEADER, key=Connection, value=keep-alive
    HTTP_EVENT_ON_HEADER, key=Vary, value=Accept-Encoding
    HTTP_EVENT_ON_HEADER, key=Expires, value=Thu, 01 Jan 1970 00:00:01 GMT
    HTTP_EVENT_ON_HEADER, key=Cache-Control, value=no-cache
    HTTP_EVENT_ON_DATA, len=283
    HTTP_EVENT_ON_DATA, len=512
    HTTP_EVENT_ON_DATA, len=57
    HTTP_EVENT_ON_FINISH
    esp_http_client_get_status_code: 200
    HTTP_EVENT_DISCONNECTED

    Any ideas??

    Thank you

    1. WordBot says:

      Hi, When you send an image from the ESP32 do you see anything on the server in the PHP error log? You have to POST an image for it to work but you could try testing with just POSTing text using this: https://reqbin.com/

  14. Parth says:

    Hi, The examples are very helpful & with little modifications I have been able to upload image to “Remote Server” through ESP-EYE. But, I am able to upload image of FRAME SIZE up to QVGA & below. Can anyone help me understand, whether this is the highest resolution that can be uploaded or I need to change the code so that it can be uploaded with higher resolutions too.

    1. WordBot says:

      Hi,
      Something like
      sensor_t * s = esp_camera_sensor_get();
      s->set_framesize(s, FRAMESIZE_QVGA);

      Taken from here: https://robotzero.one/esp32-face-door-entry/ might help?

  15. Mariano Ceneri says:

    Great job !
    Any ideas how to send a photo ID from the ESP?

    Send PhotoID and photo.

    regards

    1. WordBot says:

      What’s a photoID?

  16. Mariano Ceneri says:

    In case you want to identify the camera, send an ID.
    I solved it by sending the parameter in the URL and retrieving in PHP with GET method

    INO
    const char *post_url = “http://********.com/image.php?id=14”; // Location where images are POSTED and ID Camera

    PHP

    Regards !

  17. Mariano Ceneri says:

    PHP File

    $trapID = $_GET [‘id’];
    echo $trapID;

    $received = file_get_contents(‘php://input’);
    $fileToWrite = “Photos/”.$trapID.” – “.time().”.jpg”;
    file_put_contents($fileToWrite, $received);

  18. WordBot says:

    Cool. I can see that being useful for identifing which camera took a particular image.

  19. David says:

    Thanks for sharing this!

    Q1: Under what copyright license is the code provide? I’d like to make some fixes/improvements and redistribute it.
    Q2: Why does the SD card has to be 4GB or less? I’m currently using a 8 GB card and it seems to work fine.

    Regarding the Flash led being connected to SD data1. I found this nice video on how to mod the board to change this: https://www.youtube.com/watch?v=1ojUXSgMBVY

    1. WordBot says:

      Hi,

      Nearly all the code is rewritten from the documentation and examples of the Espressif IDF which has this license – https://github.com/espressif/esp-idf/blob/master/LICENSE . I think that means you can do whatever you want with it.
      The SD card size was something mentioned on the Ai-Thinker site I think but it seems like it’s not true. I’ll edit the article.

      Supposedly this code cancels the LED lighting up when data is written the card but I didn’t think you could mess about with the pins connected to the SD card reader.
      pinMode(4, OUTPUT);
      digitalWrite(4, LOW);
      rtc_gpio_hold_en(GPIO_NUM_4);

  20. David says:

    What I understand from https://github.com/espressif/esp-idf/blob/master/examples/storage/sd_card/README.md the HS2_DATA1 signal(=GPIO4) is used in 4-bit communication mode. So I guess reconfiguring GPIO4 to output will only work if your SD card doesn’t have support for 4-bit signalling. Else you have to explicitly configure the ESP32 SD/MMC host driver to 1-bit mode. Which can be done by adding ‘host.flag = SDMMC_HOST_FLAG_1BIT’ to init_sdcard().

    With my SD card, with 4-bit bus support, the strong flashing of the flash LED disappears if I switch the host to 1-bit mode. However the led still burns softly, and about 0.6 V is at the base of the transistor that controls the LED. This is due the voltage divider created by R10, R12 and R13. To overcome this you still have to explicitly configure the GPIO4 pin at a LOW level as you described above. This has to be done after configuring the SD card, the driver apparently sets the pin to float since it isn’t used.

    1. WordBot says:

      Wow, you know your stuff! I’d read that about 1-bit mode before and wondered about trying it but I’ve spent so much time trying to make various things work without crashing the ESP32-CAM that I decided to work on other stuff.

  21. David says:

    If you’re interested, my modified version of the SD Card time-lapse code is available here: https://github.com/dimhoff/Esp32CamTimelapse/

    One small bug I came across in the original version is a buffer overflow in save_photo_numbered(). The filename variable is allocated to small to hold the ASCII representation of INT_MAX.

    1. WordBot says:

      Nice! Much more polished code than my version.

    2. WordBot says:

      One small bug I came across in the original version is a buffer overflow in save_photo_numbered(). The filename variable is allocated to small to hold the ASCII representation of INT_MAX.

      I think I’ve fixed that with this code…

      //char *filename = (char*)malloc(21 + sizeof(int));
      char *filename = (char*)malloc(21 + sizeof(file_number));

  22. James says:

    This seems to be the internet home for ESP-CAM discussion!

    Regarding the flash, or the “blinding disk-active-light” – my solution was to de-solder the collector of the J3Y transistor just above the led. It just takes a second, and you can solder it back again if you want to. I’ll post some pictures on the github below.

    Also, I have written an program to write an AVI video file on the SD chip, with the http server to start/stop and configure the video, and an ftp server to download it to your computer.

    I’m just struggling with the ESP32 WiFi disconnect problem — I can access the ESP32 with http and ftp, but it will mysteriously disappear from wifi at times, and even checking every loop() to see if wifi has disconnected or failed, it can disappear for 30 minutes before it reports it failed, and I can run the reconnect.

    I’ll post it tomorrow – perhaps someone can solve the wifi disconnect.

    https://github.com/jameszah/ESP32-CAM-Video-Recorder

  23. Parth says:

    Thank you for trying to provide solution, it really helped. But, my problem was I was not trying with secure connection, tried with secured & problem got resolved for ESP-EYE. Other facing similar can try same.

  24. Steve says:

    Thanks for this tutorial!

    I am not able to see the images on my server.
    I have created timelapse folder where my PHP file exists.
    I am using 000webhostapp free account.

    What is the possible mistake ?

    I have checked the “Log” section on my website dashboard, I don’t get anything there.

    Thanks for your help!

  25. Gublu says:

    Thanks for the tutorial.
    I am not able to see images in my server.
    I have timelapse folder where my PHP file is located.
    I have also tried reqbin where the code returned is 200(OK) when I send some text to a PHP file.
    The ESP seems to be working fine since this is what I get in my Serial monitor,
    ————————-
    15:23:23.156 -> Taking picture…
    15:23:23.757 -> HTTP_EVENT_ON_CONNECTED
    15:23:30.777 ->
    15:23:30.777 -> HTTP_EVENT_ON_HEADER, key=Server, value=nginx
    15:23:30.777 -> HTTP_EVENT_ON_HEADER, key=Date, value=Thu, 15 Aug 2019 09:53:37 GMT
    15:23:30.777 -> HTTP_EVENT_ON_HEADER, key=Content-Type, value=text/html
    15:23:30.777 -> HTTP_EVENT_ON_HEADER, key=Content-Length, value=841
    15:23:30.777 -> HTTP_EVENT_ON_HEADER, key=Connection, value=keep-alive
    15:23:30.777 -> HTTP_EVENT_ON_HEADER, key=Vary, value=Accept-Encoding
    15:23:30.777 -> HTTP_EVENT_ON_HEADER, key=Expires, value=Thu, 01 Jan 1970 00:00:01 GMT
    15:23:30.777 -> HTTP_EVENT_ON_HEADER, key=Cache-Control, value=no-cache
    15:23:30.777 -> HTTP_EVENT_ON_DATA, len=283
    15:23:30.777 -> HTTP_EVENT_ON_DATA, len=512
    15:23:30.777 -> HTTP_EVENT_ON_DATA, len=46
    15:23:30.777 -> HTTP_EVENT_ON_FINISH
    15:23:30.777 -> esp_http_client_get_status_code: 200
    15:23:30.777 -> HTTP_EVENT_DISCONNECTED
    ——————-
    What could be the problem ?

    1. WordBot says:

      Maybe change this line…
      const char *post_url = "http://your-webserver.net/yourscript.php"; // Location where images are POSTED
      to
      const char *post_url = "https://your-webserver.net/yourscript.php"; // Location where images are POSTED
      Do you have a error log for PHP on the server?

  26. Steve says:

    My mistake was I didn’t include the <?php tags for the code.
    Everything working fine on 000webhostapp now. Able to see images in the timelapse folder.

    The php file should include the following code should be,

    Code

    Once again Thanks a lot WordBot for the tutorial !

  27. Ashiq Ullah says:

    Hey sir, here in Pakistan, I can’t find this module (from Ai thinker). Can I use eye esp instead for the same code?

    1. WordBot says:

      Hi, The JavaScript and POSTing to a server versions will work fine with the ESP-EYE. You’ll have to change pin definitions for the camera and maybe one or two other definitions. You can find them in the Camera Web Server example.

  28. Ashiq Ullah says:

    In fact, I want to use it for my scenario. I have esp eyes v2.1 . The scenario is similar to the one of yours “Upload a Capture to a Server”. How to change pic in this code (https://robotzero.one/wp-content/uploads/2019/04/Esp32CamTimelapsePost.ino) . It would be greate if you help me in this regard.
    Addition: I want to trigger the board by pressing a button to take a picture and send it to server. (I need your guidence here as well).

    1. WordBot says:

      Did you want to use the button on the ESP-EYE or use a button in an HTML based interface? I don’t have time to look at this at the moment but there should be some code in this example https://github.com/espressif/esp-who/tree/master/examples/single_chip/recognition_solution that can use if you want to access the ESP-EYE button. Otherwise you can look at the Camera Web Server code to see how a button is made in HTML.

  29. Ashiq Ullah says:

    If you can’t help me with esp-eye. Then I have another question. Kindly tell me.
    I have another product similar to this one you have shown. But it is not “Ai thinker” version.
    Here is the product you may want to see. (https://hallroad.org/esp32-cam-wifi-bluetooth-camera-module-development-board-esp32-with-camera-module-ov2640-for-arduino-in-pakistan.html) It is from HW. Can I use this with the code above?

    1. WordBot says:

      It’s the same product. You can buy versions of this with different names from Banggood, AliExpress, Amazon etc.

  30. Ashiq Ullah says:

    I want the same thing you have given. I am asking for if you can guide me in making this code for esp-eye as we don’t have esp32 cam from ai-thinker. Here is another version. Kindly check it for me if it is possible to do it with this module. (https://hallroad.org/esp32-cam-wifi-bluetooth-camera-module-development-board-esp32-with-camera-module-ov2640-for-arduino-in-pakistan.html)

  31. Ashiq Ullah says:

    Okay, thank you so much. If it is the same product with a different version and if I can use it. I will buy it now. I will let you know.

  32. Vellayan V says:

    Fatastic. I have tried timelapse javascript and timelapse server methods. Both working fine. Thanks

  33. Steve says:

    I tried to reduce the time between the image capture. It is taking atleast 7 seconds between, “Taking picture …..”. How can I upload my picture quickly to the server ? Is internet upload speed the only reason which is why my esp32 camera is taking so much time to upload an image.

    What changes do I make so that my camera can live stream events ? Like an Online webcam.

    Would like to have video streaming like in the example CameraWebserver. What changes can I do ?

    1. WordBot says:

      It’s possible that if the capture_interval variable is set too low that the function take_send_photo in the loop is called too often and you get a slow down. I would have thought every 3-5 seconds would be possible. It also will depend on the server. There may be restrictions on how many post requests can be made per minute.

      If you want to stream the video you can do port forwarding. I think in the comments for the CameraWebServer tutorial someone has explained how to do this.

  34. Steve says:

    A comment from aelorenzo(May 6, 2019), talks about web streaming (in “Editing the ESP32-CAM Camera Web Server HTML” tutorial), but that person doesn’t talk about how to do it exactly. I did search for “port forwarding” on “Editing the ESP32-CAM Camera Web Server HTML” tutorial and “Unlock a Door Using Face Detection and a Sonoff”, but the search results returned nothing.
    @Wordbot Can you please post some links where someone has given detailed description on how to do it ?

    Thanks for the help!

  35. Steve says:

    Found the Port forwarding discussion in “Ai-Thinker ESP32-CAM in the Arduino IDE”.
    Also this is one more discussion on github on esp32 cam port forwarding “https://github.com/espressif/arduino-esp32/issues/2492”.

    1. WordBot says:

      If you just want to see the stream without the interface you can change the port as in the Github issue. Then map it in your router. If you want see the HTML interface from outside you have to change the HTML code (https://robotzero.one/esp32-cam-custom-html/) I can’t test this because my internet is 4G and port forwarding doesn’t work.

  36. Ashiq Ullah says:

    Thank you so much. It worked for me. I have esp32 cam from DM and I successfully uploaded the picture to my server.

    1. WordBot says:

      Great! I’m glad you have it working.

  37. Curt Wells says:

    Thank you so much..my implementation of your javascript timelapse is working great !
    One question…do you know how to turn on the flash lamp and adjust its brightness ?

    1. WordBot says:

      The flash LED is on Pin io4. I’ve not really investigated it but maybe the brightness could be controlled with PWM?

  38. Ronald says:

    Wonderful code, it helps me a lot.
    Is there anybody can give me advise? Since I’d like to receive captured images with python flask instead of php.

  39. Tadej says:

    Hello!
    The last one works perfectly, except in bright situations I get weird picture, over saturated ,greenish colour .. ( https://ibb.co/MMQ3Qp7 )any ideas?

    1. WordBot says:

      Hi, Could be this problem: https://github.com/espressif/esp32-camera/issues/55 . The camera doesn’t seem to adjust the exposure fast enough before the picture is taken.
      You could try changing some settings by doing something like this:

      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();
      s->set_framesize(s, FRAMESIZE_QVGA);

      by using something from the options below. See the CameraWebServer example to test this.

      s->set_quality(s, val);
      s->set_contrast(s, val);
      s->set_brightness(s, val);
      s->set_saturation(s, val);
      s->set_gainceiling(s, (gainceiling_t)val);
      s->set_whitebal(s, val);
      s->set_gain_ctrl(s, val);
      s->set_exposure_ctrl(s, val);
      s->set_awb_gain(s, val);
      s->set_agc_gain(s, val);
      s->set_aec_value(s, val);
      s->set_aec2(s, val);
      s->set_dcw(s, val);
      s->set_bpc(s, val);
      s->set_wpc(s, val);
      s->set_raw_gma(s, val);
      s->set_wb_mode(s, val);
      s->set_ae_level(s, val);

  40. Ronald says:

    I solve this problem by using multipart content-type and then use flask request.files. If someone has the same question as I had, you may try this direction.

  41. Christian says:

    Hi and thanks for the great tutorials.
    With the Time-lapse to Server script I only get a new HTTP_EVENT_ON_CONNECTED every 2min. I send the buffer to a node-red http node. What could I change to achieve a faster transfer?

  42. Christian says:

    Solved it via node red http-response node.

  43. Sam Wilson says:

    Hi There, thanx for this great project.
    But can i use the 2nd on that saves to sd card on LILYGO® TTGO (the black one with long camera ribbon).
    Pls let me know.

    1. WordBot says:

      This one? https://es.aliexpress.com/item/32971057846.html It won’t work without some code changes. If you look at this project you can see the code you need to change to access the SD card: https://github.com/moononournation/arduino-selfie-camera

  44. David says:

    Perfect!!!
    Great work.

    One question my pictures have too white points at night.
    Is my camera problem or all.

    1. WordBot says:

      If it’s the same spot all the time it’s probably the sensor has a couple of dead pixels.

  45. marcos says:

    I have been trying to get this working using multipart without luck.
    @Rolan can you pls pass on your working exmaple?

  46. Wahyu Pria Purnama says:

    hay thanks for this tutorial but i cant open the image, in my server showing message “this file is not supported” but the file extension is .jpg.
    any solution?
    sory bad english.

    1. WordBot says:

      Hi, When you download the file from the server, how many kb is it?

  47. mehrad says:

    Hi thanks for sharing your experiences with others.
    I’m using esp32-cam m5stack WiFi module.
    The codes are correctly plugged into the board and the photos are uploaded to the server.
    But the problem starts with the fact that the photos are not visible and “Could not load image” message is displayed.

    log serial esp32:
    3:02:47.431 -> Taking picture…

    13:02:47.597 -> HTTP_EVENT_ON_CONNECTED

    13:02:47.597 -> HTTP_EVENT_HEADER_SENT

    13:02:47.796 ->

    13:02:47.796 -> HTTP_EVENT_ON_HEADER, key=Date, value=Mon, 21 Oct 2019 09:32:47 GMT

    13:02:47.796 -> HTTP_EVENT_ON_HEADER, key=Server, value=Apache/2.4.25 (Debian)

    13:02:47.796 -> HTTP_EVENT_ON_HEADER, key=Content-Length, value=0

    13:02:47.796 -> HTTP_EVENT_ON_HEADER, key=Content-Type, value=text/html; charset=UTF-8

    13:02:47.830 -> HTTP_EVENT_ON_FINISH

    13:02:47.830 -> esp_http_client_get_status_code: 200

    13:02:47.830 -> HTTP_EVENT_DISCONNECTED

    and 30kb photo size

    please guide.

    1. WordBot says:

      Hi, What happens if you download the image from the server. Will it display then?

  48. Dylan says:

    Hello,
    I am struggling to change the image size of the time-lapse to server code. How would I select the largest file type?
    I am expecting it to be here:
    if (psramFound()) {
    config.frame_size = FRAMESIZE_UXGA; //Can this be changed?
    config.jpeg_quality = 10; //I’ve tried changing this but it didn’t work
    config.fb_count = 2;
    } else {
    config.frame_size = FRAMESIZE_SVGA;//Can this be changed?
    config.jpeg_quality = 12; //I’ve tried changing this but it didn’t work
    config.fb_count = 1;
    }

    1. WordBot says:

      Hi, Does my comment date July 25, 2019 at 10:28 am help you?

  49. mehrad says:

    Thanks for your follow up.
    This was resolved. I changed the connection to the Internet.
    The question that is so important to me for weeks is the following:
    How can I save the video to the server using php script

    Thank you very much for your guidance

  50. Dylan says:

    Hello,
    Thanks for your reply. I had a look at that comment but I’m afraid I don’t understand how to implement it. Would it be like this:

    if (psramFound()) {
    sensor_t * s = esp_camera_sensor_get();
    s->set_framesize(s, FRAMESIZE_UXGA);
    config.frame_size = FRAMESIZE_UXGA;
    config.jpeg_quality = 10;
    config.fb_count = 2;
    } else {
    sensor_t * s = esp_camera_sensor_get();
    s->set_framesize(s, FRAMESIZE_SVGA);
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
    }

  51. Dylan says:

    Turns out I didn’t understand what UXGA meant, that part IS what defines the resolution. My confusion came about due to the image on the server being around 30kb, where as when I do the CameraWebServer version and take a still photo, it shows as 124.8kb which is much better resolution.

    Is something happening when transferring the image that reduces its resolution/quality/size?

    1. WordBot says:

      Hi, In the sketches that stream video the code starting if(psramFound())… is there to create a space in the memory for the video frames. Later in those sketches the resolution is dropped with

      //drop down frame size for higher initial frame rate
      sensor_t * s = esp_camera_sensor_get();
      s->set_framesize(s, FRAMESIZE_QVGA);

      In this example I think the frame size will be set as in config.frame_size = and you don’t need to change it later.

      This document has the various framesizes if you want to experiment – https://github.com/espressif/esp32-camera/blob/master/driver/include/sensor.h remember with JPG the contents of the image affect the filesize.

  52. mehrad says:

    Give me your answer if possible
    Thankful

    1. WordBot says:

      This might take you somewhere near to what you want but you’re probably better looking at Home Assistant or similar if you want to record video streams on a server.

      https://github.com/jameszah/ESP32-CAM-Video-Recorder

  53. mehrad says:

    What is the best solution for sending video without using an ip camera and using external rstp rtmp http servers?
    i need help with uploading video to external server with php script.
    Thanks for your guidance

  54. hsn says:

    device gets too hot. why the device becomes hot when the camera is not in use? (capture_interval = 60000)
    Is it possible to take images at 10 minute intervals?
    Can sleep mode be used to save power?
    Can the security of the php script be increased?

    thank you so much for everything.

    1. WordBot says:

      It shouldn’t get too hot as it’s just connected to Wi-Fi and not doing anything else. You can set a 10 minute interval. If you want long intervals it would be better to sleep the ESP32

      https://www.instructables.com/id/ESP32-Deep-Sleep-Tutorial/ Wake the device, take the picture and sleep again.

      If you look at the two comments above July 28, 2019 at 6:48 pm You could use this to send a password with the file and in the PHP only run the rest of the script if the password is correct. Maybe look at using HTTPS as well.

  55. Roberto says:

    Hi!Very good tutorial!I usedthe timelapse sample code to upload an image every 2 minutes to a server,then deep sleep and so on.
    I have a very strange issue..i get every time picture that seems satured in green,this not happens if i do not use the deep sleep, but even if i did not use deep sleep, the first photo is always green satured.
    What do you think i have this issue?
    Thank you in advance!

    1. WordBot says:

      I’m not sure why that is. Someone else mentioned the first frame being washed out. I wonder if the camera is still setting up when the photo is taken. Maybe a delay at the start of the static esp_err_t take_send_photo() function. Alternatively you might have to take two images and just upload the second?

  56. Roberto says:

    Thank you for your fast reply!
    I tried to take 2 pictures but also in this case with no luck.
    Since this happens only if I use Deep sleep ,it seems that the first picture taken after the boot it’s not valid for some reason..I will try to put a delay and I will let you know!

  57. Roberto says:

    Hi!
    I fixed this issue,now your code can be used also with deep sleep!
    As you suggested i inserted a delay here:

    Serial.println(“Taking picture…”);
    camera_fb_t * fb = NULL;
    delay(2000);
    esp_err_t res = ESP_OK;
    Serial.println(“Waiting camera to be ready…”);
    delay(2000);

    It works perfectly without any green predominance!
    Thank you very much!

    1. WordBot says:

      Great! I found a bit more info for anyone else with this problem – https://github.com/espressif/esp-who/issues/37

  58. Radko says:

    Hello great tutorial !!! I was wondering if you have some modification where Content type of POST request is multipart/ form-data. I tried to modify your code and added headers and boundaries. But i still get “Missing initial boundary” error

    1. WordBot says:

      Hi. I seem to remember struggling with multipart until I realised you could send a ‘raw’ jpg. I have another tutorial that might help – https://robotzero.one/posting-data-server-esp32/ or maybe you could combine post and get on the server to read from the URL and the posted image?

  59. bloodstone says:

    running into an issue where the esp32-cam doesnt mount the sd card, not sure what to check, as I have tried the tests and they fail as well. I have reformatted and tried different sd cards and they all do not mount. Any suggestions?

    1. WordBot says:

      I guess if none of the examples work for the SD card then the reader is broken.

  60. dimitris petrakis says:

    Hey this sample of code works with esp-32 camera module ?

    1. WordBot says:

      They should all work with any ESP32 camera module. You need the Ai-Thinker ESP32-CAM for the SD card example.

  61. sanil jain says:

    Hi, Thank you for providing so many cool projects. This helped me greatly in learning more about my Esp32cam.
    But I was hoping if you could tell me how do I publish the clicked photos on MQTT. Using the same procedure of clicking in intervals and pushing the images over to the MQTT.

    1. WordBot says:

      Hi, I’ve not used MQTT so I don’t really know how you would do it but if you look at the POST example you can see how a JPG is sent to a server.

  62. Jimnewt says:

    Hi i did as you told as and everything worked allright but suddenly i get this error

    [E][camera.c:1215] camera_init(): Failed to set frame size
    [E][camera.c:1270] esp_camera_init(): Camera init failed with error 0x20002

    Could you please help me guys ?

    1. WordBot says:

      Hi, Are you saying it used to work but doesn’t any more? Most likely a hardware problem. Always worth trying the CameraWebServer example to test things.

  63. Dien Nguyen Van says:

    hi, i don’t know why all of my file *.jpg which i posted to my host is always only 0.1kb. and this is my response from ESP:
    [10:38:33.167] Taking picture…
    [10:38:33.169]
    [10:38:35.167] Waiting camera to be ready…
    [10:38:35.170]
    [10:38:39.585] HTTP_EVENT_ON_CONNECTED
    [10:38:39.585]
    [10:38:43.887]
    [10:38:43.887] HTTP_EVENT_ON_HEADER, key=Date, value=Sun, 29 Mar 2020 03:38:44 GMT
    [10:38:43.896] HTTP_EVENT_ON_HEADER, key=Content-Type, value=text/html; charset=UTF-8
    [10:38:43.907] HTTP_EVENT_ON_HEADER, key=Transfer-Encoding, value=chunked
    [10:38:43.907] HTTP_EVENT_ON_HEADER, key=Connection, value=keep-alive
    [10:38:43.917] HTTP_EVENT_ON_HEADER, key=Server, value=awex
    [10:38:43.917] HTTP_EVENT_ON_HEADER, key=X-Xss-Protection, value=1; mode=block
    [10:38:43.927] HTTP_EVENT_ON_HEADER, key=X-Content-Type-Options, value=nosniff
    [10:38:43.927] HTTP_EVENT_ON_HEADER, key=X-Request-ID, value=29c8fd96198c80e5581f060cdc7ef562
    [10:38:43.937] HTTP_EVENT_ON_DATA, len=27
    [10:38:43.937] HTTP_EVENT_ON_FINISH
    [10:38:43.937] esp_http_client_get_status_code: 200
    [10:38:43.941] HTTP_EVENT_DISCONNECTED

    1. WordBot says:

      Hi, Is there any data in the image files at all?

  64. Ryan says:

    HI,

    My esp32-cam is getting really hot but the same camera doesn’t get hot with other sketches.

    I’m using a 16gig sds card could that be the issue?

    Is there any way to help keep the temp down?

    Thanks.

    1. WordBot says:

      Hi, It’s probably the Wi-Fi that’s heating up the board. If you add the wrong details for the Wi-Fi so it doesn’t connect, does it still get hot?

  65. x6l7y5 says:

    Hi,
    I’m triyng to post images to a NodeRed HTTPS Server. Can you help me with the mods needed to work with HTTPS ?

  66. vilaoculta says:

    Hi Mr. WordBot, thanks for the great tutorial.

    I’m new into the ESP32 world and I have some questions:
    1- Is it possible make the JavaScript example acessible via another remote internet connection? I’ve tried the port forward with no success.
    2- How do you access your PHP page file? Is it stored in a web server and receiving the data from ESP32?
    3- Is it possible to put the php code with the ESP32 code (like the JavaScript example) and access remotely?
    4- Can you please send the php code?

    Like I said, I’m new in this kind of technology and please forgive me if I said any absurd. Thanks again!

    1. WordBot says:

      Hi,
      1) You could use desktop sharing. Remote desktop in Windows 10 or Teamviewer but I don’t know how well this will work
      2) The PHP sits on the server waiting to be called by the code on the ESP32
      3) PHP code needs to be run on a server with PHP installed so no
      4) The code is in the tutorial. The three lines shown.
      Another tutorial for POSTing data from an ESP32 to a PHP server: https://robotzero.one/posting-data-server-esp32/ I’m not sure if this will help or confuse you more!

  67. vilaoculta says:

    Thank you Mr. WordRobot! Helped me a lot!

  68. Paulo says:

    Hi, congrats for the great tutorial…

    How about if I want for the pictures to be transferred to my web server as they are taken?
    Either straight or after been stored on the SD card?

    Thanks

    1. WordBot says:

      Hi,
      One of the options in the tutorial is sending the image to a server. Alternatively, this tutorial has code for POSTing https://robotzero.one/ttgo-security-camera-pir/ and also this one… https://robotzero.one/posting-data-server-esp32/

  69. Petri Luoto says:

    Hi.
    Thanks for good instructions. I managed to implement the last example, but I would need to add more information in POST parameters.
    The line setting the post fields in your last example is: esp_http_client_set_post_field(http_client, (const char *)fb->buf, fb->len); which includes only the captured image. But I would need to add some more parameters like id=27 etc.

    Could you tell me how can I send both the captured image (fb->buf) AND another parameter (key=value) which I could fetch on server side with $_POST[‘key’]?

    Thanks a lot!

    1. WordBot says:

      Hi, Can you send your extra data in the query string and collect it on the server with $_GET ?

  70. Petri Luoto says:

    I did try that in the first place, but it didn’t work. It looks like that when sending with POST there will be nothing to retrieve with $_GET. To verify that I did send with GET and then the query string could be received (but obviously not the image). My server is on Raspberry. Could it be it behaves differently if the method (POST & query string) should be OK otherwise?

    So, still lacking knowledge on how to combine the image and other string parameters on POST data in ESP32 side.

    Thanks.

    1. WordBot says:

      I’ve had a look around and can’t see a simple solution. Normally you use multipart/form-data as the form type. Maybe this is possible somehow with the HTTP server I used – https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/esp_http_server.html Maybe a different ESP32 HTTP server would offer this.
      I often combine GET and POST with my web work but this is web browser to PHP webserver. I would have thought the Pi would function the same way.
      I found this as well – php://input is not available with enctype=”multipart/form-data”. https://www.php.net/manual/en/wrappers.php.php in case you get half way and are testing still with query string data.

  71. Petri Luoto says:

    Thanks for your response.
    I can now say (after a heavy investigation :)) that using query parameters together with POST in Pi /PHP webserver. works. Not sure what was the problem, but I retyped much text and played with single/double quotation marks and suddenly it started to work. Perhaps some invisible white space chars there (sorry for the trouble).

    This was a bit cumbersome to get right with the ESP32-cam client as it didn’t show the response, so I couldn’t echo back what was sent by ESP32-cam. I couldn’t find a working example anywhere either, but finally managed to modify your original code to show the received response on Arduino serial monitor. Here the changed part:
    esp_err_t err = esp_http_client_perform(http_client);
    if (err == ESP_OK) {
    //char charbuffer[2000];
    //char *buffer = charbuffer;

    int data_len = esp_http_client_read(http_client, buffer, esp_http_client_get_content_length(http_client));
    printf(“Status %d, data length %i\n”, esp_http_client_get_status_code(http_client), data_len);

    if (data_len >= 0) {
    charbuffer[data_len] = ‘\0’;
    Serial.printf(“Received:\n%s\n”, buffer);
    } else {
    Serial.println(“No response.”);
    }
    }

    So, now my code sends the camera ID and running picture number as query parameters with POST image. The ID represents a directory on the server where images will be stored by each camera. With Virtualdup I can then create a time lapse video from them.
    This is the modified php on Pi server:

    Thanks a lot for your help!

  72. Petri Luoto says:

    Oops! the modified server code was not showing so here it is:

  73. Petri Luoto says:

    Sorry. the system does not accept php snippet and drops it.
    One more try without php tags:

    $received = file_get_contents(‘php://input’);
    $deviceID = $_GET [‘id’];
    $fileID = $_GET [‘filename’];

    $target_dir = “/NAS/Surveillance/” . $deviceID . “/”;
    $fileToWrite = $target_dir . $fileID . “.jpg”;

    file_put_contents($fileToWrite, $received);
    //this goes back to ESP32-cam client
    echo “ID:” . $deviceID . “, path:”. $fileToWrite;

  74. Abdul wahab says:

    If you can’t help me with esp-eye. Then I have another question. Kindly tell me.
    I have another product similar to this one you have shown. But it is not the “Ai thinker” version.
    Here is the product you may want to see. (https://www.rawlix.com/product/esp32-cam-wifi-bluetooth-camera-module-development-board-esp32-with-camera-module-ov2640-for-arduino-637240323374426679) It is from HW. Can I use this with the code above?

    1. WordBot says:

      Yep.. that’s the same model with a different name.

  75. Trevor says:

    I have not been able to save to SD card! I have formatted it with windows 8 formatter but there is no Flash LED flashing and the SD card is empty. Any ideas please?

    1. WordBot says:

      Do you see any errors in the serial monitor when the ESP32 starts up? Might not be able to open the card for writing.

      1. Trevor says:

        No. I don’t get any errors at all. Sorry for the slow reply this thread was in my junk folder!

        1. WordBot says:

          There should be something in the serial monitor when it starts up. Try flashing with verbose mode on.

          1. Trevor says:

            Yes OK I’ll do that. Thanks a lot.

  76. Alz says:

    currently my serial monitor gives this msg

    Connecting to: hq_main
    13:51:25.860 -> …………Taking picture…
    13:52:24.534 -> E (61136) TRANS_TCP: DNS lookup failed err=202 res=0x0
    13:52:24.534 -> E (61136) HTTP_CLIENT: Connection failed, sock HTTP_EVENT_DISCONNECTED

    The image does not get uploaded.can u please help?

    1. WordBot says:

      TRANS_TCP: DNS lookup failed

      The ESP can’t connect to the server. Are you using an IP address to connect to?

      1. Alz says:

        yes I am using an ip address.Is there a way to make it work with an ip address?

        1. WordBot says:

          The ip address of the server with the PHP file. It looks like it can’t connect. Can you connect if you type that ip address into the browser URL bar?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

scroll to top