🎉
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:
- Camera: Connect to camera port on Raspberry Pi
- Servo Signal: GPIO 18 → Servo signal wire
- Servo Power: 5V (or external supply) → Servo red wire
- Servo Ground: GND → Servo black/brown wire
- LCD: VCC→5V, GND→GND, SDA→GPIO 2, SCL→GPIO 3
- Button: One side → GPIO 2, Other side → GND
- 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:
- Mount Camera: Attach camera to servo using pan/tilt mechanism
- Wire Servo: Connect servo to GPIO 18, power, and ground
- Connect LCD: Wire I2C LCD to Raspberry Pi
- Add Button: Connect button to GPIO 2 and GND
- Optional - Add Fan: Connect small DC fan if you want actual fan functionality
- Secure Everything: Use breadboard and secure connections
- Test Each Component: Test camera, servo, display, and button individually
- 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:
- Gather All Components: Make sure you have everything
- Wire Everything: Follow the complete wiring diagram
- Mount Hardware: Secure camera on servo, mount display
- Write Complete Code: Use the full system code
- Test Each Component: Verify each part works
- Test Integration: Test components working together
- Final Testing: Test complete system operation
- 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.