Note

Hello, welcome to the SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts Community on Facebook! Dive deeper into Raspberry Pi, Arduino, and ESP32 with fellow enthusiasts.

Why Join?

  • Expert Support: Solve post-sale issues and technical challenges with help from our community and team.

  • Learn & Share: Exchange tips and tutorials to enhance your skills.

  • Exclusive Previews: Get early access to new product announcements and sneak peeks.

  • Special Discounts: Enjoy exclusive discounts on our newest products.

  • Festive Promotions and Giveaways: Take part in giveaways and holiday promotions.

👉 Ready to explore and create with us? Click [here] and join today!

4.2 Automatic Capture Camera

Introduction

Imagine you’re away, and a curious little squirrel visits your windowsill. With this project, you can create an automatic capture camera to snap pictures of these delightful moments. Using a motion sensor, the camera detects movement and captures photos at regular intervals.


What You’ll Need

The following components are required for this project:

COMPONENT INTRODUCTION

PURCHASE LINK

Breadboard

BUY

Jumper Wires

BUY

Resistor

BUY

PIR Motion Sensor Module

BUY

Camera Module

BUY

Fusion HAT+

-

Raspberry Pi

-


Circuit Diagram

Below is the circuit diagram for this project:

../_images/4.1.2_sch.png

Wiring Diagram

  1. To use camera module conveniently, Assemble the Pan-tilt (For Camera) is recommended.

    Note

    Assembling the pan-tilt may obscure some pins, so it is recommended to assemble it only when using the camera, or place it on the outside after assembly.

    ../_images/gimbal_assemble.png
  2. Follow this wiring diagram to set up the circuit:

    ../_images/4.1.2_bb.png
  3. For best performance, adjust the two potentiometers on the PIR module: one controls sensitivity, and the other adjusts detection distance. Turn both counterclockwise to the end.

    ../_images/PIR_TTE.png

Running the Example

  1. Access the Raspberry Pi Desktop:

  2. Open a Terminal and go to the code folder:

    cd ~/ai-lab-kit/python
    
  3. Run the script to start the camera:

    sudo python3 4.2_AutomaticCaptureCamera.py
    
  4. After running the script:

    • The camera starts and continuously monitors the PIR motion sensor connected to GPIO 17.

    • When the PIR sensor detects motion and its output goes HIGH, the camera captures one photo and saves it to the Pictures folder with an incremental filename.

    • After each capture, the program waits briefly to avoid repeated photos.

    • The system keeps monitoring for motion and runs until you press Ctrl + C to exit.


Code

Here is the Python code used for this project:

#!/usr/bin/env python3

import os
import time
import threading
from picamera2 import Picamera2, Preview
from fusion_hat.pin import Pin, Mode, Pull

# Resolve the correct user's home directory (works with sudo)
REAL_USER = os.getenv("SUDO_USER") or os.getlogin()
USER_HOME = f"/home/{REAL_USER}"
PICTURES_DIR = os.path.join(USER_HOME, "Pictures")
os.makedirs(PICTURES_DIR, exist_ok=True)

# Initialize camera
camera = Picamera2()
camera.configure(camera.create_preview_configuration(main={"size": (800, 600)}))

# Photo counter with thread safety
photo_index = 1
photo_lock = threading.Lock()

# Track whether preview was started successfully
preview_started = False

# Initialize PIR sensor (GPIO 17)
pir = Pin(17, mode=Mode.IN, pull=Pull.DOWN)

def take_photo():
   """Capture one photo and increment the index."""
   global photo_index
   with photo_lock:
      filepath = os.path.join(PICTURES_DIR, f"photo_{photo_index:03d}.jpg")
      print(f"\nMotion detected! Capturing: {filepath}")
      camera.capture_file(filepath)
      print("Saved.")
      photo_index += 1

def main():
   global preview_started

   # Start preview only when a GUI display is available
   preview_started = False
   if os.getenv("DISPLAY"):
      try:
         camera.start_preview(Preview.QT)
         preview_started = True
      except Exception as e:
         print(f"Preview start failed (continue without preview): {e}")
   else:
      print("No DISPLAY detected (running headless without preview).")

   camera.start()

   print("Camera is running.")
   print("PIR sensor monitoring on GPIO 17.")
   print(f"Photos will be saved to: {PICTURES_DIR}")
   print("Press Ctrl+C to exit.\n")

   try:
      while True:
         if pir.value():        # PIR detects motion (HIGH)
            take_photo()        # Take one photo
            time.sleep(2)       # Delay to avoid repeated shots

         time.sleep(0.1)

   except KeyboardInterrupt:
      print("\nExiting...")

   finally:
      try:
         camera.stop()
      except Exception:
         pass

      if preview_started:
         try:
            camera.stop_preview()
         except Exception:
            pass

      try:
         camera.close()
      except Exception:
         pass

if __name__ == "__main__":
   main()

Understanding the Code

  1. Imports:

    import os
    import time
    import threading
    from picamera2 import Picamera2, Preview
    from fusion_hat.pin import Pin, Mode, Pull
    

    The script imports libraries for file handling (os), timing control (time), thread safety (threading), camera operation (Picamera2), and GPIO control (Pin).

  2. Path Setup:

    REAL_USER = os.getenv("SUDO_USER") or os.getlogin()
    USER_HOME = f"/home/{REAL_USER}"
    PICTURES_DIR = os.path.join(USER_HOME, "Pictures")
    os.makedirs(PICTURES_DIR, exist_ok=True)
    

    This section determines the correct user home directory and ensures the Pictures folder exists for saving photos.

  3. Camera Initialization:

    camera = Picamera2()
    camera.configure(camera.create_preview_configuration(main={"size": (800, 600)}))
    

    The camera is initialized and configured with a preview resolution of 800 × 600.

  4. Photo Counter and Thread Lock:

    photo_index = 1
    photo_lock = threading.Lock()
    

    A photo counter is used to create sequential filenames, and a lock ensures safe access when capturing photos.

  5. PIR Sensor Initialization:

    pir = Pin(17, mode=Mode.IN, pull=Pull.DOWN)
    

    The PIR motion sensor is connected to GPIO 17 and set as an input with a pull-down resistor.

  6. Photo Capture Function:

    def take_photo():
       """Capture one photo and increment the index."""
       global photo_index
       with photo_lock:
          filepath = os.path.join(PICTURES_DIR, f"photo_{photo_index:03d}.jpg")
          print(f"\nMotion detected! Capturing: {filepath}")
          camera.capture_file(filepath)
          print("Saved.")
          photo_index += 1
    

    This function captures a single photo and saves it to the Pictures directory whenever motion is detected.

  7. Preview Handling and Camera Start:

    preview_started = False
    if os.getenv("DISPLAY"):
       try:
          camera.start_preview(Preview.QT)
          preview_started = True
       except Exception as e:
          print(f"Preview start failed (continue without preview): {e}")
    else:
       print("No DISPLAY detected (running headless without preview).")
    

    A camera preview is started only when a graphical display is available; otherwise, the script runs in headless mode.

  8. Main Loop (Motion Detection):

    while True:
       if pir.value():
          take_photo()
          time.sleep(2)
    

    The program continuously monitors the PIR sensor. When motion is detected (HIGH), one photo is taken, followed by a short delay to prevent repeated captures.

  9. Program Exit and Cleanup:

    except KeyboardInterrupt:
       camera.stop()
       camera.close()
    

    When the user presses Ctrl + C, the program exits gracefully and safely stops and closes the camera.


Troubleshooting

  1. Photos Are Not Captured:

    • Cause: PIR motion sensor is not working or incorrectly wired.

    • Solution:

      • Verify the PIR sensor is connected to GPIO pin 17, power, and ground.

      • Adjust the PIR sensor’s sensitivity and delay potentiometers if available.

  2. PIR Sensor Always Detects Motion:

    • Cause: Faulty PIR sensor or excessive environmental interference.

    • Solution:

      • Test the sensor with a multimeter to ensure it detects motion correctly.

      • Place the sensor in a stable, controlled environment to avoid false positives.

  3. Script Crashes with Camera Error:

    • Cause: Camera is not properly initialized or in use by another process.

    • Solution:

      • Ensure the camera is connected and enabled via raspi-config.

      • Restart the Raspberry Pi to release any conflicting processes.


Extendable Ideas

  1. Timestamped Filenames: Save photos with timestamps in their filenames for better organization:

    timestamp = time.strftime("%Y%m%d-%H%M%S")
    camera.capture_file(f'{user_home}/capture_{timestamp}.jpg')
    
  2. LED Indicator: Add an LED that lights up when the PIR sensor detects motion:

    from fusion_hat import Pin
    led = Pin(27)
    if pir.value() == 1:
       led.on()
    else:
       led.off()
    
  3. Photo Gallery Management: Automatically organize captured photos into folders based on date or event.


Conclusion

This project demonstrates how to build an automated camera system using a PIR motion sensor and a Raspberry Pi Camera Module. It’s a great way to capture unexpected moments and explore the possibilities of IoT and computer vision. Try expanding its functionality to include additional features like video recording or cloud uploads for real-time monitoring.