ESP32-CAM PIR Motion Detector with Photo Capture (saves to microSD card)

In this project, we’re going to make a motion sensor detector with photo capture using an ESP32-CAM. When your PIR sensor detects motion, it wakes up, takes a photo and saves it in the microSD card.

ESP32-CAM Motion Detection with Photo Capture (saves to microSD card)

This project is very similar with a previous one, but after so many requests, we added a PIR motion sensor to the circuit. So, when motion is detected a picture is taken and saved on the microSD card.

Other ESP32-CAM projects and tutorials:

We have a similar project using a Raspberry Pi and a camera module:

Watch the Video Tutorial

You can watch the video tutorial or continue reading for the complete project instructions.

Parts Required

For this project, you’ll need the following parts:

You can use the preceding links or go directly to to find all the parts for your projects at the best price!

Project Overview

ESP32-CAM Motion Detector with Photo Capture Project Overview

Here is a quick overview on how the project works.

  • The ESP32-CAM is in deep sleep mode with external wake up enabled.
  • When motion is detected, the PIR motion sensor sends a signal to wake up the ESP32.
  • The ESP32-CAM takes a photo and saves it on the microSD card.
  • It goes back to deep sleep mode until a new signal from the PIR motion sensor is received.

Recommended reading: ESP32 Deep Sleep with Arduino IDE and Wake Up Sources

Formatting MicroSD Card

The first thing we recommend doing is formatting your microSD card. You can use the Windows formatter tool or any other microSD formatter software.

1. Insert the microSD card in your computer. Go to My Computer and right click in the SD card. Select Format as shown in figure below.

Formatting your microSD card Windows

2. A new window pops up. Select FAT32, press Start to initialize the formatting process and follow the onscreen instructions.

Formatting your microSD card Windows

Note: according to the product specifications, the ESP32-CAM should only support 4 GB SD cards. However, we’ve tested with 16 GB SD card and it works well.

Installing the ESP32 add-on

We’ll program the ESP32 board using Arduino IDE. So, you need the Arduino IDE installed as well as the ESP32 add-on:

ESP32-CAM Take Photo with PIR Sketch

Copy the following code to your Arduino IDE.

  Rui Santos
  Complete project details at
   - Select Board "AI Thinker ESP32-CAM"
   - GPIO 0 must be connected to GND to upload a sketch
   - After connecting GPIO 0 to GND, press the ESP32-CAM on-board RESET button to put your board in flashing mode
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
#include "esp_camera.h"
#include "esp_timer.h"
#include "img_converters.h"
#include "Arduino.h"
#include "fb_gfx.h"
#include "fd_forward.h"
#include "fr_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 "dl_lib.h"
#include "driver/rtc_io.h"
#include <EEPROM.h>            // read and write from flash memory
// define the number of bytes you want to access
#define EEPROM_SIZE 1
RTC_DATA_ATTR int bootCount = 0;

// Pin definition for 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
int pictureNumber = 0;

#define uS_TO_S_FACTOR 1000000
void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
  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;
  pinMode(4, INPUT);
  digitalWrite(4, LOW);
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  // Init Camera
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
  Serial.println("Starting SD Card");
    Serial.println("SD Card Mount Failed");
  uint8_t cardType = SD_MMC.cardType();
  if(cardType == CARD_NONE){
    Serial.println("No SD Card attached");
  camera_fb_t * fb = NULL;
  // Take Picture with Camera
  fb = esp_camera_fb_get();  
  if(!fb) {
    Serial.println("Camera capture failed");
  // initialize EEPROM with predefined size
  pictureNumber = + 1;
  // Path where new picture will be saved in SD Card
  String path = "/picture" + String(pictureNumber) +".jpg";
  fs::FS &fs = SD_MMC;
  Serial.printf("Picture file name: %s\n", path.c_str());
  File file =, FILE_WRITE);
    Serial.println("Failed to open file in writing mode");
  else {
    file.write(fb->buf, fb->len); // payload (image), payload length
    Serial.printf("Saved file to path: %s\n", path.c_str());
    EEPROM.write(0, pictureNumber);
  // Turns off the ESP32-CAM white on-board LED (flash) connected to GPIO 4
  pinMode(4, OUTPUT);
  digitalWrite(4, LOW);

  esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 0);
  Serial.println("Going to sleep now");
  Serial.println("This will never be printed");
void loop() {

View raw code

This code is very similar to one of our previous ESP32-CAM projects, but it enables external wake up on GPIO 13.


To learn more about the code, go to the following project:

ESP32-CAM Upload Code

To upload code to the ESP32-CAM board, connect it to your computer using an FTDI programmer. Follow the next schematic diagram:

ESP32-CAM FTDI Programmer Wiring Circuit Diagram 5V

Important: GPIO 0 needs to be connected to GND so that you’re able to upload code.

To upload the code, follow the next steps:

  1. Go to Tools > Board and select AI Thinker ESP32-CAM
  2. Go to Tools > Port and select the COM port the ESP32 is connected to
  3. Press the ESP32-CAM on-board RESET button
  4. Then, click the upload button to upload the code
ESP32-CAM upload code to AI Thinker ESP32-CAM

Important: if you can’t upload the code, double-check that GPIO 0 is connected to GND and that the RX and TX connections are correct. Check if you’ve selected the right settings in the Tools menu. You should also press the on-board Reset button to restart your ESP32 in flashing mode.

Schematic Diagram

ESP32-CAM with PIR Motion Sensor Circuit Breadboard

Assemble all the parts as shown in the following schematic diagram.

ESP32-CAM with PIR Motion Sensor Circuit Diagram
Thanks to David Graff for sharing the schematic diagram for this project

If you prefer, you can follow the Fritzing diagram instead.

ESP32-CAM with PIR Motion Sensor Schematic Diagram Fritzing

To prevent problems during upload, we recommend assembling the circuit only after uploading the code.


After uploading de code and assembling the circuit, insert a formatted microSD card and apply power to your circuit – you can use a portable charger, for example.

Powering ESP32-CAM with powerbank

Then, press the reset (RST) button, and it should start working. When it detects motion, it turns on the flash, takes a photo and saves it on the microSD card.

ESP32-CAM takes photo when detects motion with PIR sensor

Experiment with this circuit several times to make sure that it is working. Then, insert the microSD card to your computer to see the captured photos.

ESP32-CAM takes photo when detects motion with PIR sensor photo demonstration

Here’s an example:

ESP32-CAM photo example captured

Now you can finish this project the way you want, you can either use a dummy camera and insert your ESP32-CAM with the PIR motion sensor, or you can build your own enclosure.

ESP32-CAM PIR Motion Detector with Photo Capture with fake dummy camera

You can also apply the concepts learned in this tutorial in your own projects.


If you’re getting any of the following errors, read our ESP32-CAM Troubleshooting Guide: Most Common Problems Fixed

  • Failed to connect to ESP32: Timed out waiting for packet header
  • Camera init failed with error 0x20001 or similar
  • Brownout detector or Guru meditation error
  • Sketch too big error – Wrong partition scheme selected
  • Board at COMX is not available – COM Port Not Selected
  • Psram error: GPIO isr service is not installed
  • Weak Wi-Fi Signal
  • No IP Address in Arduino IDE Serial Monitor
  • Can’t open web server
  • The image lags/shows lots of latency

Wrapping Up

We hope you’ve liked this project. For more ESP32-CAM projects you can subscribe to our newsletter. If you don’t have an ESP32-CAM yet, you can get one for approximately $6.

If there is any project you’d like to see with the ESP32-CAM or if you’d like to share your project with us, write a comment in the comment’s section below.

Learn more about the ESP32 with our “Learn ESP32 with Arduino IDE” course or check our ESP32 free resources.

Thank you for reading.

Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »

Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our weekly newsletter!

66 thoughts on “ESP32-CAM PIR Motion Detector with Photo Capture (saves to microSD card)”

    • Hi Saman.
      That will be one of our next projects.
      But at the moment, we don’t have any tutorial about that.

  1. Hi love all your articles, thought you mite like to do a project using the small e ink modules 1.5 inches type maybe thanks so much .

  2. Just curious why you are using the elaborate setup to pull the pin low with the PIR instead of just connecting it directly and pulling it high?

    • Hi Jeffery.
      The part of the setup() you’re referring to is to control the Flash lamp of the board, not the PIR sensor.

    • That’s a good question. Why not just change the code to expect a high signal from the motion sensor instead of building the transistor circuit?

  3. Is it possible to use only the ESP32-CAM as a motion sensor to send an email when it detects motion? In my case, it won’t be asleep/need to wake up, it will be on power supply and on waiting for a client to connect to stream video.

    thank you. nice website.

    • Hi.
      I’m not sure if the ESP32-CAM is powerful enough to detect motion on its own (i’ve never tried it).
      Sending an image via email will be one of our next projects.

    • Yes, it is possible. I realized, with due limits, a motion detector without the aid of the PIR, but processing the images (frame). The purpose was didactic and not professional, but it works 🙂

    • Yes. It should be possible to achieve, but we haven’t taken the time to make that project yet.
      We plan to do something similar soon.

    • The 2N3904 is a very generic small silicon NPN transistor being used as a switch. Almost any cheap silicon NPN transistor ought to work, since you’re not using it for audio or RF purposes. Amazon lists a bag of 200 of them for less than a nickel ($0.05) each

  4. Hello,
    Is it possible to change the code because I will not be using PIR sensor. Im thinking if it is possible that the esp32 can be made to automatically take pictures once it is turn on. and take pictures every 2 seconds. What do I need to change in the Codes. thanks

  5. Hi, great article.

    Question: is it possible in this esp32 board that you plug in directly an e-ink raw display like WaveShare and drive it with the esp-32?

    • Hi Nik.
      Many of the pins exposed in this ESP32 board are being used either by the camera or by the microSD card slot.
      So, it can be very difficult and tricky to setup a display like that with this ESP32-CAM.
      (I’m not saying it is not possible, but it should be very tricky).

  6. Hi there, i am a newbie. The article it is just the Top.
    I have this problem:
    /esp-who/examples/single_chip/esp32-camera-screen/main/app_main.cpp:41:20: fatal error: dl_lib.h: No such file or directory
    i just comented the:
    //#include “dl_lib.h”
    and it work ok.
    Any idea?
    And it is possible to disable the flash light? Thnx.

  7. I can upload the sketch OK but cannot get the camera to work. Just grounding GPIO13 should cause the flash and camera to record a photo but nothing happens. Do you think I have got a faulty ESP32-CAM board?

  8. Just thinking about it, to wake up from deep sleep your code indicates that the pin is to be turned low by the PIR when movement is detected. But for this to work it will need an external pullup resistor so that it is normally high. When movement is detected by the PIR it will then pull this pin low and wake it up from deep sleep.
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 0);
    The pullup resistor would need to connect to 3.3V and not 5V.

    • The U0R and U0T are the U(ART)0R(X) and U(ART)0T(X) ports/pins on the ESP32. The ESP32 also has a UART1 (GPIO9/10, neither of which are broken out) and a UART2 (GPIO 16/17 but only GIPO16/RX2 is broken out.)

      • Hi Micro, if I know that the esp32 has several serial ports, but my question is about the esp32 cam, I want to know if it has more serial ports because seeing the data sheet says it only has one UOT and one UOR is why my doubt.

        Also that you recommend me to connect with a sim800l and send commands at from esp32 cam 🙂

        Thanks in advance 🙂

  9. in the beginning i had problem compiling the code but after reading in the comment section about the l.lib.h that can be commented,i did that and uploaded the code and is working perfect now.thank you guys,i appreciated it.regards.

    • Just comment out that library and you’re ready to go… It was already explained in some other comments and even one above yours 😉

  10. So if I understand correctly , there is nothing in the code that inhibits flash for this project? I really would like to set it up on a warehouse but I need it without flash
    Thanks again for all you guys do!

  11. Hi guys,
    Trying to run this ESP-Cam motion sensor app. On compile, I get “dl_lib.h No such file or directory”. Your first web server app works fine. Obviously, I’m missing a library or two.
    Where do you reference these libraries?

  12. Hi Sara and Rui,

    Can I use the PIR Motion Sensor (HC-SR501) in this project?

    If I can use it, do I have to modify the circuit, or the code?


  13. The ESP32 doesn’t stay in sleep mode. Therefore I’m getting numerous photos saved to the SD card because the code is automatically resetting again.
    Would this be because the PIR is constantly on LOW and so PIN 13 is always 0. I have kept very still but it goes round again and takes and saves a photo.

  14. Solved. It was a question of a reliable constant power supply. So, instead of using the laptop or a mains 5v adapter plug to power the device I used a YuRobot 545043 breadboard power supply fixed to a 1/4 size (420 points) breadboard. It now works smoothly at a constant 5v and without any glitches. I’ve yet to see how long the 9v battery will last though!
    Excellent sketch. I’ve also got it to send me email with photo attachment.

    • Hi Malcom.
      Thanks for sharing that.
      Can you tell me what approach did you use to send the photo to your email?

    • Yes.
      You can use GPIO 16 por example to attach the button (I’ve tested it and it works well with that pin).
      Then, you can simply check if the button was pressed and take a photo if that is the case.
      buttonState = digitalRead(buttonPin);
      if (buttonState==HIGH){
      (code to take a photo)

  15. Wow, Thank You both for your time, expertise and effort in helping us all out with this great hobby of ours. Please keep up the great work!!!
    From BC, Canada

  16. Hey Guys,
    I’m running this code on two AI Thinker ESP-32-Cam modules. Both systems run fine for awhile, taking pictures, storing pics, etc but then error-out when they come out of sleep. i.e.
    Saved file to path: /picture157.jpg
    Going to sleep now
    ets Jun 8 2016 00:22:57

    rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    mode:DIO, clock div:1
    ho 0 tail 12 room 4
    ho 0 tail 12 room 4
    entry 0x400806b8
    Starting SD Card
    Picture file name: /picture158.jpg
    Saved file to path: /picture158.jpg
    Going to sleep now
    ets Jun 8 2016 00:22:57

    rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    mode:DIO, clock div:1
    ho 0 tail 12 room 4
    ho 0 tail 12 room 4
    entry 0x400806b8
    [E][camera.c:1049] camera_probe(): Detected camera not supported.
    [E][camera.c:1249] esp_camera_init(): Camera probe failed with error 0x20004

    This happens on both systems. Anything similar happening for anyone else??

Leave a Comment

Download our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.