PIR Sensor for Wildlife Camera Trigger

Project Overview

This project creates a wildlife camera trigger system that captures photos or videos when animals are detected. A PIR sensor detects animal movement and triggers a camera (GoPro, DSLR, or USB camera) to capture images, perfect for observing wildlife in your backyard or remote locations.

Difficulty: Intermediate
Estimated time: 2-3 hours
Estimated cost: $30-50 (plus camera)

How It Works

A PIR sensor detects warm, moving animals. When motion is detected, the ESP32 triggers the camera via a shutter control cable (for DSLR) or by activating a USB camera. Images are stored on an SD card or transmitted via Wi-Fi. The system includes a real-time clock to timestamp images.

Materials Needed

  • ESP32-CAM or Arduino + camera module (1)
  • HC-SR501 PIR sensor (1)
  • SD card for image storage
  • Battery pack (18650 lithium cells) or 5V USB power bank
  • TP4056 charging module (if using rechargeable batteries)
  • Weatherproof enclosure (IP65 or better)
  • Jumper wires
  • IR LED array for night vision (optional)

Circuit Diagram

Connection Table (ESP32-CAM + PIR)

VCC

5V

GND

GND

OUT

GPIO 13

Positive

GPIO 4

Arduino Code (ESP32-CAM)

// Wildlife Camera Trigger with ESP32-CAM
#include "esp_camera.h"
#include <FS.h>
#include <SD_MMC.h>
#include <time.h>

#define PIR_PIN 13
#define LED_PIN 4

#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 char* ntpServer = "pool.ntp.org";
const long gmtOffset = 0;
const int daylightOffset = 0;

unsigned long lastTriggerTime = 0;
const unsigned long triggerCooldown = 10000;
int imageCount = 0;

void setup() {
  Serial.begin(115200);
  
  pinMode(PIR_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  
  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;
  config.frame_size = FRAMESIZE_SVGA;
  config.jpeg_quality = 12;
  config.fb_count = 1;
  
  esp_camera_init(&config);
  
  SD_MMC.begin();
  configTime(gmtOffset, daylightOffset, ntpServer);
  
  delay(30000);
}

String getTimestamp() {
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) return "00000000_000000";
  char buffer[20];
  strftime(buffer, sizeof(buffer), "%Y%m%d_%H%M%S", &timeinfo);
  return String(buffer);
}

void captureImage() {
  if (millis() - lastTriggerTime < triggerCooldown) return;
  
  lastTriggerTime = millis();
  
  digitalWrite(LED_PIN, HIGH);
  delay(100);
  
  camera_fb_t *fb = esp_camera_fb_get();
  if (!fb) {
    digitalWrite(LED_PIN, LOW);
    return;
  }
  
  String filename = "/IMG_" + getTimestamp() + ".jpg";
  File file = SD_MMC.open(filename, FILE_WRITE);
  if (file) {
    file.write(fb->buf, fb->len);
    file.close();
    imageCount++;
  }
  
  esp_camera_fb_return(fb);
  digitalWrite(LED_PIN, LOW);
}

void loop() {
  if (digitalRead(PIR_PIN) == HIGH) {
    captureImage();
    delay(2000);
    captureImage();
  }
  
  delay(100);
}

DSLR Trigger Version

const int shutterPin = 12;
const int focusPin = 14;

void triggerCamera() {
  digitalWrite(focusPin, HIGH);
  delay(200);
  digitalWrite(shutterPin, HIGH);
  delay(100);
  digitalWrite(shutterPin, LOW);
  delay(200);
  digitalWrite(focusPin, LOW);
}

Installation Steps

  1. Assemble electronics and test indoors
  2. Program ESP32-CAM and verify image capture
  3. Mount components in weatherproof enclosure
  4. Position near animal trails, water sources, or feeding areas
  5. Adjust PIR sensitivity for animals of appropriate size
  6. Connect battery pack (use solar panel for long-term deployment)
  7. Walk in front to verify camera triggers

Project Extensions

  • Add IR LED array and remove IR filter for night vision
  • Add cellular module for remote image transmission
  • Record video clips instead of still images
  • Add machine learning to identify species
  • Add solar panel for indefinite operation
  • Upload images to cloud when in Wi-Fi range

Conclusion

This wildlife camera trigger lets you observe animals in their natural habitat without disturbing them, capturing amazing photos of local wildlife.

Leave a Reply

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

Component Pin ESP32-CAM Pin
PIR Sensor PIR Sensor PIR Sensor IR LED Array