Advanced Level • Lesson 10

🎯 Motor Control for Tracking

⏱️ 60 minutes 📚 Advanced 🎯 Tracking System
🎯

Motor Control for Tracking

Learn how to use face coordinates to control a servo motor - making the camera follow the detected face!

From Coordinates to Angles

We have face coordinates (x, y) from the camera. Now we need to convert these into servo motor angles so the camera can follow the face!

💡 The Goal: When a face moves left, the servo should turn left. When it moves right, the servo should turn right. The servo angle should match the face position!

Calculating Servo Angle from Face Position

The camera image has a width (like 320 pixels). The face center_x tells us where the face is horizontally. We need to convert this to a servo angle (0-180 degrees).

Angle Calculation Formula:

# Camera frame width (e.g., 320 pixels) frame_width = 320 # Face center X coordinate (from detection) face_center_x = 160 # Example: face in middle # Calculate angle (0-180 degrees) # If face is at left edge (x=0) → servo at 0° # If face is at right edge (x=320) → servo at 180° # If face is in middle (x=160) → servo at 90° angle = (face_center_x / frame_width) * 180 print(f"Face at x={face_center_x}, Servo angle: {angle}°")

Understanding the Formula:

  • face_center_x / frame_width: Gives a ratio (0.0 to 1.0)
  • × 180: Converts ratio to angle (0° to 180°)
  • Left side of frame (x=0) = 0°
  • Right side of frame (x=width) = 180°
  • Center of frame = 90°

Smooth Movement

If we move the servo directly to the calculated angle, it might be jerky. We need smooth movement algorithms!

🎯

Direct Movement

Move servo directly to target angle

Simple but can be jerky

🌊

Smooth Movement

Move in small steps toward target

Smoother, more natural

Dead Zone

Only move if difference is large enough

Prevents constant small movements

Project: Camera Follows Detected Face

Let's combine face detection with servo control to make the camera follow a face!

Materials Needed:

  • Raspberry Pi
  • Raspberry Pi Camera Module
  • Servo motor (SG90 recommended)
  • Pan/tilt mechanism (or mount camera on servo)
  • Jumper wires
  • Optional: External 5V power supply for servo

Wiring Instructions:

  1. Camera: Connect to camera port on Raspberry Pi
  2. Servo Signal: Connect to GPIO 18
  3. Servo Power: Connect to 5V (or external supply)
  4. Servo Ground: Connect to GND
  5. Mount: Attach camera to servo (pan mechanism)

Complete Tracking Code:

import cv2 import RPi.GPIO as GPIO import time # Set up face detection face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') # Set up servo motor GPIO.setmode(GPIO.BCM) GPIO.setup(18, GPIO.OUT) servo_pwm = GPIO.PWM(18, 50) servo_pwm.start(0) # Set up camera cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240) # Get frame dimensions ret, frame = cap.read() frame_width = frame.shape[1] # Width of frame frame_height = frame.shape[0] # Height of frame def set_servo_angle(angle): """Move servo to specific angle (0-180 degrees)""" duty = 2 + (angle / 180) * 10 servo_pwm.ChangeDutyCycle(duty) time.sleep(0.1) # Give servo time to move servo_pwm.ChangeDutyCycle(0) # Stop signal (prevents jitter) def calculate_servo_angle(face_x, frame_width): """Convert face X position to servo angle""" # Convert face position (0 to frame_width) to angle (0 to 180) angle = (face_x / frame_width) * 180 # Clamp angle to valid range angle = max(0, min(180, angle)) return angle # Current servo position current_angle = 90 # Start at center print("Face tracking started! Press Ctrl+C to stop.") try: while True: ret, frame = cap.read() if not ret: break # Convert to grayscale gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # Detect faces faces = face_cascade.detectMultiScale(gray, 1.1, 4) if len(faces) > 0: # Get the first (or largest) face x, y, w, h = faces[0] # Calculate face center face_center_x = x + w // 2 # Calculate target servo angle target_angle = calculate_servo_angle(face_center_x, frame_width) # Smooth movement: move toward target in small steps angle_diff = target_angle - current_angle # Only move if difference is significant (dead zone) if abs(angle_diff) > 2: # 2 degree threshold # Move in small steps (smooth movement) step = 5 if angle_diff > 0 else -5 current_angle += step # Clamp to valid range current_angle = max(0, min(180, current_angle)) # Move servo set_servo_angle(current_angle) print(f"Face at x={face_center_x}, Moving servo to {current_angle}°") else: print("No face detected") time.sleep(0.1) # Small delay except KeyboardInterrupt: cap.release() servo_pwm.stop() GPIO.cleanup() print("Tracking stopped!")

Understanding the Code:

  • calculate_servo_angle(): Converts face X position to servo angle
  • Smooth movement: Moves servo in small steps (5°) instead of jumping directly
  • Dead zone: Only moves if angle difference > 2° (prevents constant tiny movements)
  • current_angle: Tracks current servo position
  • The servo gradually moves toward where the face is, creating smooth tracking!

Improving Tracking

You can improve tracking with these techniques:

🎯

Largest Face

Track the largest face when multiple detected

Speed Control

Move faster when face is far, slower when close

🛡️

Stability

Add delays and smoothing to prevent jitter

Common Mistakes to Avoid

⚠️ Watch Out For:

  • Too Fast Movement: Moving servo too quickly causes jerky motion - use small steps
  • No Dead Zone: Without dead zone, servo constantly moves from tiny differences
  • Wrong Coordinate System: Make sure you're using face center X, not top-left corner
  • Angle Out of Range: Always clamp angles to 0-180° range
  • Multiple Faces: Decide which face to track (first, largest, or closest to center)

Summary

You've learned:

  • ✅ Face coordinates can be converted to servo angles
  • ✅ Formula: angle = (face_x / frame_width) × 180
  • ✅ Smooth movement uses small steps instead of direct jumps
  • ✅ Dead zone prevents constant tiny movements
  • ✅ Tracking combines face detection with servo control
  • ✅ The camera/fan can now follow a detected face!
🎉 Amazing Progress! You can now make a servo motor follow a face! In the next lesson, you'll add a display and control button to complete the interface.

🎮 Try It: Practice Tracking!

Practice writing tracking code. Try these challenges:

📝 Challenge 1: Calculate Angle

Write a function that converts face X position to servo angle:

📝 Challenge 2: Smooth Movement

Write code that moves servo smoothly toward target angle:

💡 Tip: Remember to use smooth movement with small steps, add a dead zone to prevent constant movement, and always clamp angles to 0-180° range!

🎯 Activity: Camera Follows Detected Face

What You'll Build:

Create a system where a servo motor moves the camera to follow a detected face!

Step-by-Step Instructions:

  1. Set Up Hardware: Mount camera on servo, connect servo to GPIO 18
  2. Write Detection Code: Use face detection code from previous lesson
  3. Add Angle Calculation: Convert face X to servo angle
  4. Add Smooth Movement: Move servo in small steps
  5. Test: Stand in front of camera and move left/right
  6. Adjust: Tune step size and dead zone for smooth tracking

Testing Checklist:

  • ✅ Face is detected when you stand in front
  • ✅ Servo moves when you move left/right
  • ✅ Movement is smooth (not jerky)
  • ✅ Camera follows your face as you move
🏆 Bonus Challenge: Can you add vertical tracking too? Use a second servo for tilt (up/down) based on face Y coordinate!

💪 Practice Challenges

Challenge 1: Direct Tracking

Create a version that moves servo directly to calculated angle (no smooth movement):

# Calculate angle from face position # Move servo directly to that angle # Simpler but may be jerky

Challenge 2: Speed Control

Make servo move faster when face is far from center, slower when close:

# If face is far from center → move 10° per step # If face is close to center → move 2° per step # Creates responsive but stable tracking

Challenge 3: Largest Face Tracking

When multiple faces detected, track the largest one:

# Calculate area = width × height for each face # Find face with largest area # Track that face

Challenge 4: Center Zone

Only move servo if face is outside a "center zone" (e.g., middle 30% of screen):

# Define center zone (e.g., 35% to 65% of width) # Only track if face is outside this zone # Prevents constant small adjustments