Advanced Level • Lesson 12

🎉 Complete Project Assembly

⏱️ 90 minutes 📚 Advanced 🎯 Final Project
🎉

Complete Project Assembly

Put it all together! Build your complete human-tracking table fan with screen display and stop button!

Project Overview

You're going to build a human-tracking table fan that:

  • 👤 Detects faces using the camera
  • 🎯 Follows the face by moving a servo motor (pan mechanism)
  • 📺 Shows status on an LCD display
  • 🔘 Has a button to start/stop tracking
  • 🌀 Includes a fan that can be controlled (optional)
🎯 Project Goal: A table fan that automatically follows you as you move, with a screen showing its status and a button to control it!

Complete Materials List

All Components Needed:

  • Raspberry Pi (any model with camera port)
  • Raspberry Pi Camera Module
  • Servo motor (SG90) - for pan/tilt mechanism
  • 16x2 LCD Display with I2C backpack
  • Push button
  • Table fan (small DC fan) - optional
  • Resistors: 220Ω (for LEDs if used), 10kΩ (for button - optional)
  • Breadboard and jumper wires
  • Pan/tilt mechanism or camera mount
  • External 5V power supply (recommended for servo)

Complete Wiring Diagram

All Connections:

  1. Camera: Connect to camera port on Raspberry Pi
  2. Servo Signal: GPIO 18 → Servo signal wire
  3. Servo Power: 5V (or external supply) → Servo red wire
  4. Servo Ground: GND → Servo black/brown wire
  5. LCD: VCC→5V, GND→GND, SDA→GPIO 2, SCL→GPIO 3
  6. Button: One side → GPIO 2, Other side → GND
  7. Fan (optional): Connect to GPIO pin via transistor/MOSFET for control

The Complete Code

Here's the complete, organized code for your human-tracking fan:

Complete Human-Tracking Fan System:

#!/usr/bin/env python3 """ Human-Tracking Table Fan Complete system with face detection, servo tracking, display, and button control """ import cv2 import RPi.GPIO as GPIO from RPLCD.i2c import CharLCD import time from datetime import datetime # ===== CONFIGURATION ===== SERVO_PIN = 18 BUTTON_PIN = 2 LCD_ADDRESS = 0x27 # May be 0x3F - check with i2cdetect -y 1 CAMERA_WIDTH = 320 CAMERA_HEIGHT = 240 # ===== SETUP FUNCTIONS ===== def setup_face_detection(): """Initialize face detection""" face_cascade = cv2.CascadeClassifier( cv2.data.haarcascades + 'haarcascade_frontalface_default.xml' ) return face_cascade def setup_servo(): """Initialize servo motor""" GPIO.setup(SERVO_PIN, GPIO.OUT) pwm = GPIO.PWM(SERVO_PIN, 50) pwm.start(0) return pwm def setup_button(): """Initialize button""" GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) def setup_display(): """Initialize LCD display""" try: lcd = CharLCD(i2c_expander='PCF8574', address=LCD_ADDRESS, port=1, cols=16, rows=2, dotsize=8) return lcd except: print("LCD not found - continuing without display") return None def setup_camera(): """Initialize camera""" cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, CAMERA_WIDTH) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, CAMERA_HEIGHT) return cap # ===== CONTROL FUNCTIONS ===== def set_servo_angle(pwm, angle): """Move servo to specific angle (0-180 degrees)""" angle = max(0, min(180, angle)) # Clamp to valid range duty = 2 + (angle / 180) * 10 pwm.ChangeDutyCycle(duty) time.sleep(0.1) pwm.ChangeDutyCycle(0) # Stop signal to prevent jitter return angle def check_button_press(last_state): """Check if button was pressed, return (new_state, was_pressed)""" current_state = GPIO.input(BUTTON_PIN) was_pressed = (last_state == GPIO.HIGH and current_state == GPIO.LOW) if was_pressed: time.sleep(0.3) # Debounce return current_state, was_pressed def calculate_servo_angle(face_x, frame_width): """Convert face X position to servo angle""" angle = (face_x / frame_width) * 180 return max(0, min(180, angle)) def update_display(lcd, tracking_active, face_detected, servo_angle): """Update LCD display with current status""" if lcd is None: return lcd.clear() # Line 1: Tracking status if tracking_active: lcd.write_string("Tracking: ON") else: lcd.write_string("Tracking: OFF") # Line 2: Face and angle lcd.cursor_pos = (1, 0) if face_detected: lcd.write_string(f"Face:YES {int(servo_angle)}°") else: lcd.write_string("Face: NO") # ===== MAIN SYSTEM ===== def main(): """Main program loop""" print("Initializing Human-Tracking Fan System...") # Initialize all components GPIO.setmode(GPIO.BCM) face_cascade = setup_face_detection() servo_pwm = setup_servo() setup_button() lcd = setup_display() cap = setup_camera() # State variables tracking_active = False current_servo_angle = 90 # Start at center last_button_state = GPIO.HIGH last_display_update = 0 # Initial display if lcd: lcd.write_string("Press button") lcd.cursor_pos = (1, 0) lcd.write_string("to start") time.sleep(2) print("System ready! Press button to start tracking.") print("Press Ctrl+C to exit.") try: while True: # Check button last_button_state, button_pressed = check_button_press(last_button_state) if button_pressed: tracking_active = not tracking_active status = "STARTED" if tracking_active else "STOPPED" print(f"Tracking {status}!") if lcd: lcd.clear() lcd.write_string(f"Tracking {status}") time.sleep(1) if tracking_active: # Read camera frame ret, frame = cap.read() if ret: # Convert to grayscale gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # Detect faces faces = face_cascade.detectMultiScale(gray, 1.1, 4) if len(faces) > 0: # Face detected - track it x, y, w, h = faces[0] face_center_x = x + w // 2 # Calculate target angle target_angle = calculate_servo_angle(face_center_x, CAMERA_WIDTH) # Smooth movement toward target angle_diff = target_angle - current_servo_angle if abs(angle_diff) > 2: # Dead zone # Move in steps step_size = 5 step = step_size if angle_diff > 0 else -step_size new_angle = current_servo_angle + step new_angle = max(0, min(180, new_angle)) current_servo_angle = set_servo_angle(servo_pwm, new_angle) # Update display every 0.5 seconds current_time = time.time() if current_time - last_display_update >= 0.5: update_display(lcd, True, True, current_servo_angle) last_display_update = current_time else: # No face detected current_time = time.time() if current_time - last_display_update >= 0.5: update_display(lcd, True, False, current_servo_angle) last_display_update = current_time else: # Tracking stopped current_time = time.time() if current_time - last_display_update >= 0.5: update_display(lcd, False, False, current_servo_angle) last_display_update = current_time time.sleep(0.1) # Main loop delay except KeyboardInterrupt: print("\nShutting down...") # Cleanup cap.release() servo_pwm.stop() if lcd: lcd.clear() lcd.write_string("Shutting down") time.sleep(2) lcd.clear() GPIO.cleanup() print("System stopped. Goodbye!") # ===== RUN PROGRAM ===== if __name__ == "__main__": main()

Code Organization:

  • Configuration Section: All settings at the top
  • Setup Functions: Initialize each component
  • Control Functions: Reusable functions for operations
  • Main Function: Main loop that coordinates everything
  • Cleanup: Properly shuts down all components

Assembly Instructions

Step-by-Step Assembly:

  1. Mount Camera: Attach camera to servo using pan/tilt mechanism
  2. Wire Servo: Connect servo to GPIO 18, power, and ground
  3. Connect LCD: Wire I2C LCD to Raspberry Pi
  4. Add Button: Connect button to GPIO 2 and GND
  5. Optional - Add Fan: Connect small DC fan if you want actual fan functionality
  6. Secure Everything: Use breadboard and secure connections
  7. Test Each Component: Test camera, servo, display, and button individually
  8. Run Complete Code: Execute the full system

Testing and Debugging

When building complex systems, test each part separately first!

1️⃣

Test Components

Test each component individually

Camera, servo, display, button

2️⃣

Test Functions

Test each function separately

Face detection, servo control, display

3️⃣

Test Integration

Test components working together

Face detection + servo, button + display

4️⃣

Test Complete System

Test everything together

Full system operation

Common Issues and Solutions

⚠️ Troubleshooting:

  • Camera not detected: Enable in raspi-config, check cable connection
  • Servo not moving: Check wiring, power supply, PWM frequency (50 Hz)
  • LCD not showing: Check I2C address with i2cdetect, verify wiring
  • Button not working: Check GPIO pin, pull-up resistor, debounce delay
  • System too slow: Lower camera resolution, reduce display update frequency
  • Servo jitter: Add pwm.ChangeDutyCycle(0) after movement

Code Organization Tips

Best Practices:

  • Use Functions: Break code into reusable functions
  • Add Comments: Explain what each section does
  • Configuration at Top: Put all settings in one place
  • Error Handling: Use try/except for robust code
  • Cleanup: Always cleanup GPIO and close camera

Summary

You've built a complete human-tracking system! You've learned:

  • ✅ How to combine multiple hardware components
  • ✅ Face detection using OpenCV
  • ✅ Servo motor control for tracking
  • ✅ Display integration for status
  • ✅ Button control for user interaction
  • ✅ State management for system control
  • ✅ Code organization and structure
  • ✅ Testing and debugging techniques
🎉 CONGRATULATIONS! 🎉

You've completed the entire course! You've gone from programming basics to building a complete human-tracking system. You're now ready to create amazing hardware projects with Raspberry Pi and Python!

🎮 Try It: Complete System!

Now it's time to build the complete system. Follow the assembly instructions and test everything!

📝 Final Checklist:

  • ✅ All components wired correctly
  • ✅ Camera enabled and working
  • ✅ Servo moves smoothly
  • ✅ LCD displays status
  • ✅ Button toggles tracking
  • ✅ Face detection works
  • ✅ Servo follows face
  • ✅ Display updates in real-time

🎯 Activity: Complete Human-Tracking Fan Project

What You'll Build:

Assemble and test your complete human-tracking table fan system!

Final Assembly Steps:

  1. Gather All Components: Make sure you have everything
  2. Wire Everything: Follow the complete wiring diagram
  3. Mount Hardware: Secure camera on servo, mount display
  4. Write Complete Code: Use the full system code
  5. Test Each Component: Verify each part works
  6. Test Integration: Test components working together
  7. Final Testing: Test complete system operation
  8. Refine and Improve: Adjust settings for best performance

Final System Features:

  • ✅ Detects faces in real-time
  • ✅ Servo follows detected face smoothly
  • ✅ LCD shows tracking status and angle
  • ✅ Button starts/stops tracking
  • ✅ System responds to user control
  • ✅ Clean shutdown with Ctrl+C
🏆 Project Complete! You've built a working human-tracking system! This is a real-world project that combines computer vision, motor control, displays, and user input - exactly what professional projects do!

💪 Final Challenges

Challenge 1: Add Vertical Tracking

Add a second servo for tilt (up/down) tracking using face Y coordinate:

# Add second servo on GPIO 23 # Calculate tilt angle from face Y position # Control both pan (horizontal) and tilt (vertical)

Challenge 2: Add Fan Control

Control a small DC fan - turn it on when face is detected, off when no face:

# Use GPIO pin to control fan via transistor # Fan ON when face detected # Fan OFF when no face or tracking stopped

Challenge 3: Improve Display

Add more information to display:

  • Frame rate (FPS)
  • Number of faces detected
  • Tracking time/uptime

Challenge 4: Save Settings

Save user preferences (like tracking speed, dead zone size) to a file so they persist between runs.