Note

Welcome to the SunFounder Raspberry Pi, Arduino & ESP32 Community on Facebook!

  • Get technical support and troubleshooting help.

  • Learn and share projects, tips, and tutorials.

  • Access early product previews and updates.

  • Enjoy exclusive discounts and giveaways.

👉 Join us here: [here]

Pan-Tilt Camera Module

../../_images/pan_tilt.jpg

Note

The Pironman 5 series does not include a camera module. You need to prepare one yourself or purchase it from our official website:

In this section, you will learn how to set up and control a Pan-Tilt camera module using two SG90 servos connected directly to the GPIO pins. By the end of this section, you will have a fully installed and functional Pan-Tilt module ready for your projects.

Hardware Connection

Before starting, make sure your Raspberry Pi is powered off.

Connection Diagram:

Device

GPIO Pin

Physical Pin

Pan Servo (Orange)

GPIO17

Pin 11

Tilt Servo (Orange)

GPIO18

Pin 12

VCC (Red)

5V

Pin 2 or 4

GND (Brown)

GND

Pin 6, 9, 14, 20, 25, 30, 34, 39

Camera Module

CSI Interface

Connect to camera port

Warning

While SG90 servos can draw power directly from the Raspberry Pi’s 5V pin during testing, prolonged use or simultaneous movement of both servos may cause voltage drops and system instability. For long-term projects, consider using an external 5V power supply (ensure common ground with Raspberry Pi).

Step-by-Step Connection:

  1. Connect the servos:

    • Connect the orange signal wire of the Pan servo to GPIO17 (physical pin 11)

    • Connect the orange signal wire of the Tilt servo to GPIO18 (physical pin 12)

    • Connect the red VCC wires of both servos to a 5V pin (physical pin 2 or 4)

    • Connect the brown GND wires of both servos to any GND pin (e.g., physical pin 6)

  2. Connect the camera:

    • Gently lift the plastic clip on the CSI camera connector

    • Insert the camera ribbon cable with the metal contacts facing away from the Ethernet port

    • Press the plastic clip back down to secure the cable

Test the Servo

Before running the full Pan-Tilt example, let’s test each servo individually to ensure they are working correctly.

1. Enable GPIO and I2C (if needed):

sudo raspi-config
# Navigate to: Interface Options -> I2C -> Enable
# Reboot after enabling

2. Simple servo test script:

Create a test file servo_test.py:

#!/usr/bin/env python3
# servo_test.py - Simple servo test

from gpiozero import Servo
import time

# Test Pan servo on GPIO17
pan = Servo(17, min_pulse_width=0.5/1000, max_pulse_width=2.5/1000)

print("Testing Pan servo (GPIO17)...")
print("Moving to 0° position...")
pan.value = -1  # 0°
time.sleep(2)

print("Moving to 90° position...")
pan.value = 0   # 90°
time.sleep(2)

print("Moving to 180° position...")
pan.value = 1   # 180°
time.sleep(2)

pan.close()
print("Pan servo test complete")

3. Run the test:

python3 servo_test.py

If the servo moves smoothly through all positions, repeat the test for the Tilt servo by changing the pin number to 18.

Test the Camera

1. Enable the camera interface:

sudo raspi-config
# Navigate to: Interface Options -> Camera -> Enable
# Or for newer systems: Interface Options -> Legacy Camera -> Enable
sudo reboot

2. Test camera capture:

For Raspberry Pi OS Bullseye and newer (using libcamera):

# Take a test photo
libcamera-jpeg -o test.jpg -t 2000 --width 640 --height 480

# Preview camera feed
libcamera-hello -t 0

For older systems (using raspistill):

# Take a test photo
raspistill -o test.jpg -t 2000 -w 640 -h 480

# Preview camera feed
raspivid -t 0

3. Verify the photo:

ls -l test.jpg
# Open the image (if you have a GUI)
xdg-open test.jpg

Pan-Tilt Example

Now let’s combine both servo control and camera functionality into a complete Pan-Tilt control program. This example allows you to control the camera direction using WSAD keys and take photos with the T key.

1. Create the Pan-Tilt control script:

nano ptz_wsad_simple.py

Copy the following code:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ptz_wsad_simple.py - Control PTZ with WSAD keys, ultra simple version

from gpiozero import Servo
import os
from datetime import datetime

# Initialize servos
# SG90 parameters: min pulse width 0.5ms (0°), max pulse width 2.5ms (180°)
pan = Servo(17, min_pulse_width=0.5/1000, max_pulse_width=2.5/1000)
tilt = Servo(18, min_pulse_width=0.5/1000, max_pulse_width=2.5/1000)

# Initial position (center)
pan.value = 0
tilt.value = 0

print("\n=== SG90 PTZ Control ===")
print("W: Up")
print("S: Down")
print("A: Left")
print("D: Right")
print("T: Take photo")
print("C: Center")
print("Q: Quit")
print("-" * 30)

def take_photo():
    """Take photo function"""
    # Create photo directory if it doesn't exist
    photo_dir = "/home/pi/Pictures/ptz"
    os.makedirs(photo_dir, exist_ok=True)

    # Generate filename with timestamp
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = f"{photo_dir}/ptz_{timestamp}.jpg"

    # Take photo using libcamera (for Raspberry Pi Bullseye and above)
    # Alternative for older systems: use raspistill
    os.system(f"libcamera-jpeg -o {filename} -t 1 --width 640 --height 480")

    # Alternative command for older systems:
    # os.system(f"raspistill -o {filename} -t 1 -w 640 -h 480")

    print(f"Photo saved: {filename}")

try:
    while True:
        # Get user input
        cmd = input("Enter command: ").lower().strip()

        if cmd == 'w':
            # Move up (increase tilt angle)
            tilt.value = min(1.0, tilt.value + 0.2)
            print(f"↑ Up ({tilt.value:.1f})")

        elif cmd == 's':
            # Move down (decrease tilt angle)
            tilt.value = max(-1.0, tilt.value - 0.2)
            print(f"↓ Down ({tilt.value:.1f})")

        elif cmd == 'a':
            # Move left (decrease pan angle)
            pan.value = max(-1.0, pan.value - 0.2)
            print(f"← Left ({pan.value:.1f})")

        elif cmd == 'd':
            # Move right (increase pan angle)
            pan.value = min(1.0, pan.value + 0.2)
            print(f"→ Right ({pan.value:.1f})")

        elif cmd == 't':
            # Take photo
            take_photo()

        elif cmd == 'c':
            # Center the PTZ
            pan.value = 0
            tilt.value = 0
            print("PTZ centered")

        elif cmd == 'q':
            # Quit program
            print("Exiting program")
            break

        else:
            print("Invalid command, please use W/S/A/D/T/C/Q")

except KeyboardInterrupt:
    print("\nProgram interrupted by user")

finally:
    # Clean up GPIO resources
    pan.close()
    tilt.close()
    print("GPIO cleaned up")

2. Make the script executable:

chmod +x ptz_wsad_simple.py

3. Run the Pan-Tilt controller:

python3 ptz_wsad_simple.py

4. Control the camera:

  • Press W/S to tilt up/down

  • Press A/D to pan left/right

  • Press T to take a photo (saved to /home/pi/Pictures/ptz/)

  • Press C to center the camera

  • Press Q to quit

Camera Capture:

The script uses libcamera-jpeg (for newer Raspberry Pi OS versions) to capture photos. Photos are automatically saved with timestamps to prevent overwriting.