Bemerkung
Hallo, willkommen in der SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasten-Community auf Facebook! Tauchen Sie mit anderen Enthusiasten tiefer in Raspberry Pi, Arduino und ESP32 ein.
Warum beitreten?
Expertenunterstützung: Lösen Sie Probleme nach dem Kauf und technische Herausforderungen mit Hilfe unserer Community und unseres Teams.
Lernen & Teilen: Tauschen Sie Tipps und Tutorials aus, um Ihre Fähigkeiten zu verbessern.
Exklusive Vorschauen: Erhalten Sie frühzeitigen Zugang zu neuen Produktankündigungen und Sneak Peeks.
Sonderrabatte: Genießen Sie exklusive Rabatte auf unsere neuesten Produkte.
Festliche Aktionen und Gewinnspiele: Nehmen Sie an Gewinnspielen und Feiertagsaktionen teil.
👉 Bereit, mit uns zu entdecken und zu gestalten? Klicken Sie auf [here] und treten Sie noch heute bei!
4.16 Pan-Tilt-Kamerasteuerungssystem
Einführung
In diesem Projekt erstellen Sie ein Kamerasteuerungssystem, das mithilfe eines Joysticks schwenken (horizontale Bewegung) und neigen (vertikale Bewegung) kann. Das System ermöglicht es Ihnen, die Richtung einer auf Servomotoren montierten Kamera fernzusteuern, das Kamerabild in Echtzeit anzuzeigen und mit einem Druck auf den Joystick-Button Fotos aufzunehmen. Dieses Projekt eignet sich ideal für Überwachungsanwendungen, Fotoprojekte oder zum Erlernen der Steuerung von Servomotoren und der Integration einer Kamera.
Was Sie benötigen
Die folgenden Komponenten werden für dieses Projekt benötigt:
KOMPONENTENBESCHREIBUNG |
KAUFLINK |
|---|---|
- |
|
- |
|
Raspberry Pi |
- |
Schaltplan
Verdrahtungsdiagramm
Um das Kameramodul bequem zu verwenden, wird Pan-Tilt montieren (für die Kamera) empfohlen.
Bemerkung
Der Zusammenbau der Pan-Tilt-Halterung kann einige Pins verdecken. Daher wird empfohlen, sie nur zu montieren, wenn die Kamera verwendet wird, oder sie nach dem Zusammenbau außen zu platzieren.
Folgen Sie diesem Verdrahtungsdiagramm, um die Schaltung aufzubauen:
Beispiel ausführen
Greifen Sie auf den Raspberry-Pi-Desktop zu:
Remote Desktop: Verwenden Sie VNC für eine vollständige Desktop-Erfahrung.
Raspberry Pi Connect: Verwenden Sie Raspberry Pi Connect, um sicher über einen Browser auf Ihren Pi zuzugreifen.
Öffnen Sie ein Terminal und wechseln Sie in den Code-Ordner:
cd ~/ai-lab-kit/python
Starten Sie das Skript, um die Kamera zu aktivieren:
sudo python3 pan_tilt_camera.py
Nach dem Start des Skripts wird das Pan-Tilt-Kamerasystem initialisiert und Kamera sowie Servomotoren werden gestartet.
Wenn ein Display verfügbar ist, wird eine Live-Kameravorschau angezeigt; andernfalls läuft das Programm normal im Headless-Modus.
Wenn Sie den Joystick nach links oder rechts bewegen, dreht sich die Kamera horizontal (Pan). Wenn Sie ihn nach oben oder unten bewegen, neigt sich die Kamera vertikal (Tilt).
Wenn der Joystick-Button gedrückt wird, nimmt die Kamera ein Foto auf und speichert es im Verzeichnis
Pictures/camera_pan_tiltmit einem einfachen fortlaufenden Dateinamen wiephoto_001.jpg.Das System läuft weiter und reagiert auf Benutzereingaben, bis Sie das Programm mit Ctrl + C beenden.
Code
Unten steht das Python-Skript, das in diesem Projekt verwendet wird:
#!/usr/bin/env python3
import os, time
from picamera2 import Picamera2, Preview
from fusion_hat.adc import ADC
from fusion_hat.pin import Pin, Mode, Pull
from fusion_hat.servo import Servo
# Servo channels for pan (horizontal) and tilt (vertical)
PAN_CHANNEL, TILT_CHANNEL = 2, 3
# Joystick ADC pins (X/Y axis) and button pin
X_PIN, Y_PIN = "A1", "A0"
BTN_PIN = 17
# Angle limits to protect servos
PAN_MIN, PAN_MAX = -90, 90
TILT_MIN, TILT_MAX = -45, 45
# Deadzone ignores small joystick movement
DEADZONE = 15
MOVE_SPEED = 3
LOOP_DELAY = 0.05
# Photo save directory (works with sudo)
REAL_USER = os.getenv("SUDO_USER") or os.getlogin()
PHOTO_DIR = os.path.join(f"/home/{REAL_USER}", "Pictures", "camera_pan_tilt")
os.makedirs(PHOTO_DIR, exist_ok=True)
# Initialize servos
pan_servo = Servo(PAN_CHANNEL)
tilt_servo = Servo(TILT_CHANNEL)
# Initialize joystick and button (active-low)
x_adc = ADC(X_PIN)
y_adc = ADC(Y_PIN)
joystick_button = Pin(BTN_PIN, mode=Mode.IN, pull=Pull.UP) # pressed -> 0
# Initialize camera
camera = Picamera2()
camera.configure(camera.create_preview_configuration(main={"size": (1280, 720)}))
preview_started = False
photo_count = 1
current_pan = 0
current_tilt = 0
last_button_state = 1 # Used for edge detection
def clamp(v, vmin, vmax):
# Limit value to a safe range
return max(vmin, min(vmax, v))
def map_value(value, in_min, in_max, out_min, out_max):
# Map ADC value to a new range
return (value - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
def apply_deadzone(v, dz):
# Ignore small joystick movement
return 0 if (-dz < v < dz) else v
def read_joystick():
# Read joystick X/Y position
x = map_value(x_adc.read(), 0, 4095, -100, 100)
y = map_value(y_adc.read(), 0, 4095, -100, 100)
return x, y
def check_button_press():
# Detect button press (HIGH -> LOW)
global last_button_state
current_state = joystick_button.value()
if last_button_state == 1 and current_state == 0:
last_button_state = current_state
return True
last_button_state = current_state
return False
def take_photo():
# Capture and save one photo
global photo_count
filename = f"photo_{photo_count:03d}.jpg"
filepath = os.path.join(PHOTO_DIR, filename)
camera.capture_file(filepath)
print("Saved:", filepath)
photo_count += 1
def start_preview_if_available():
# Start camera preview only if a display is available
global preview_started
preview_started = False
if os.getenv("DISPLAY"):
try:
camera.start_preview(Preview.QT)
preview_started = True
except Exception:
preview_started = False
def cleanup():
# Safely stop camera and release resources
try:
camera.stop()
except Exception:
pass
if preview_started:
try:
camera.stop_preview()
except Exception:
pass
try:
camera.close()
except Exception:
pass
def main():
global current_pan, current_tilt
start_preview_if_available()
camera.start()
# Center camera at startup
pan_servo.angle(0)
tilt_servo.angle(0)
try:
while True:
# Read joystick and move camera
x, y = read_joystick()
x = apply_deadzone(x, DEADZONE)
y = apply_deadzone(y, DEADZONE)
new_pan = current_pan + (MOVE_SPEED if x > DEADZONE else -MOVE_SPEED if x < -DEADZONE else 0)
new_tilt = current_tilt + (MOVE_SPEED if y > DEADZONE else -MOVE_SPEED if y < -DEADZONE else 0)
new_pan = clamp(new_pan, PAN_MIN, PAN_MAX)
new_tilt = clamp(new_tilt, TILT_MIN, TILT_MAX)
if new_pan != current_pan:
current_pan = new_pan
pan_servo.angle(current_pan)
if new_tilt != current_tilt:
current_tilt = new_tilt
tilt_servo.angle(current_tilt)
# Take photo when button is pressed
if check_button_press():
take_photo()
time.sleep(LOOP_DELAY)
except KeyboardInterrupt:
pass
finally:
cleanup()
if __name__ == "__main__":
main()
Code verstehen
Hardware-Initialisierung
Zwei Servomotoren werden initialisiert, um die horizontale (Pan) und vertikale (Tilt) Bewegung der Kamera zu steuern
Der Joystick verwendet ADC-Kanäle, um die analogen X- und Y-Werte auszulesen, sowie einen GPIO-Pin, um Tastendrücke zu erkennen
Das Kameramodul wird initialisiert und für den Vorschau-Modus konfiguriert und unterstützt sowohl Anzeige- als auch Headless-Betrieb
Joystick-Auslesen und Verarbeitung
read_joystick()liest die rohen Analogwerte der X- und Y-Achsen des Joysticksmap_value()wandelt ADC-Werte (0–4095) in einen nutzbaren Bereich von −100 bis 100 umapply_deadzone()filtert kleine Joystickbewegungen heraus, um unerwünschtes Kameradriften zu verhindern
Steuerung der Kamerabewegung
Joystick-Eingaben werden in schrittweise Änderungen der Pan- und Tilt-Winkel umgesetzt
clamp()stellt sicher, dass die Winkel innerhalb sicherer Grenzen bleiben, um die Servomotoren zu schützenDie Servos werden nur aktualisiert, wenn sich der Winkel ändert, wodurch eine gleichmäßige und stabile Bewegung erreicht wird
Erkennung von Tastendrücken
Der Joystick-Button ist als Active-Low-Eingang mit Pull-up-Widerstand konfiguriert
check_button_press()erkennt einen Tastendruck mittels Flankenerkennung (HIGH → LOW)Dadurch wird sichergestellt, dass pro Tastendruck nur ein Foto aufgenommen wird, selbst wenn die Taste länger gedrückt gehalten wird
Fotoaufnahme und Speicherung
take_photo()nimmt mit dem Kameramodul ein Bild aufFotos werden mit fortlaufenden Dateinamen gespeichert (z. B.
photo_001.jpg)Alle Bilder werden im Verzeichnis
Pictures/camera_pan_tiltdes Benutzers gespeichert
Behandlung der Kameravorschau
Eine Live-Kameravorschau wird nur gestartet, wenn eine grafische Anzeige verfügbar ist
Das Skript funktioniert weiterhin normal, wenn es ohne Anzeige ausgeführt wird
Hauptschleife und Aufräumen
Die Hauptschleife liest kontinuierlich die Joystick-Eingaben und reagiert in Echtzeit
Wenn das Programm mit
Ctrl + Cbeendet wird, wird die Kamera sicher gestopptAlle Hardware-Ressourcen werden ordnungsgemäß freigegeben, um ein sauberes Herunterfahren zu gewährleisten
Fehlerbehebung
Servos bewegen sich nicht:
Ursache: Falsche Servo-Verbindungen oder Stromversorgungsprobleme
Lösung:
Überprüfen Sie, ob die Servos mit den richtigen Kanälen (2 und 3) verbunden sind
Stellen Sie sicher, dass das Fusion HAT korrekt mit Strom versorgt wird
Kontrollieren Sie die Servo-Verkabelung auf lose Verbindungen
Kameravorschau wird nicht angezeigt:
Ursache: Kameramodul nicht erkannt oder falsche Konfiguration
Lösung:
Stellen Sie sicher, dass das Kamerakabel sicher mit dem CSI-Port verbunden ist
Prüfen Sie, ob die Kamera in der Raspberry-Pi-Konfiguration aktiviert ist
Überprüfen Sie die Kompatibilität des Kameramoduls
Joystick reagiert nicht:
Ursache: Falsche Pin-Zuweisung oder ADC-Probleme
Lösung:
Überprüfen Sie die Joystick-Verbindungen zu A0, A1 und GPIO 17
Testen Sie die ADC-Werte mit einfachen
print-AusgabenPrüfen Sie, ob der ADC des Fusion HAT funktioniert
Fotos werden nicht gespeichert:
Ursache: Berechtigungsprobleme oder Verzeichnisprobleme
Lösung:
Überprüfen Sie, ob das Verzeichnis
Picturesim Home-Verzeichnis des Benutzers existiertKontrollieren Sie die Schreibrechte für das Fotoverzeichnis
Versuchen Sie das Skript mit
sudoauszuführen, falls weiterhin Berechtigungsprobleme auftreten
Unruhige Servobewegungen:
Ursache: Spannungsschwankungen oder Timing-Probleme in der Software
Lösung:
Stellen Sie eine stabile Stromversorgung für das Fusion HAT sicher
Passen Sie
MOVE_SPEEDund Verzögerungswerte anFügen Sie bei Bedarf Kondensatoren zu den Servo-Stromleitungen hinzu
Erweiterungsideen
Videoaufnahme: Fügen Sie eine Videoaufnahmefunktion mit Start/Stopp-Steuerung hinzu:
def start_recording(): timestamp = time.strftime("%Y%m%d_%H%M%S") video_path = os.path.join(VIDEO_DIR, f"video_{timestamp}.mp4") camera.start_recording(video_path) print(f"Recording started: {video_path}") def stop_recording(): camera.stop_recording() print("Recording stopped")
Voreingestellte Positionen: Erstellen Sie voreingestellte Kamerapositionen für schnellen Zugriff:
PRESETS = { 'center': (0, 0), 'left': (-45, 0), 'right': (45, 0), 'up': (0, 30), 'down': (0, -30) } def goto_preset(preset_name): if preset_name in PRESETS: pan, tilt = PRESETS[preset_name] pan_servo.angle(pan) tilt_servo.angle(tilt)
Fazit
Dieses Projekt zeigt, wie man mit Raspberry Pi, Servomotoren und einem Kameramodul ein leistungsfähiges Pan-Tilt-Kamerasteuerungssystem erstellt. Es kombiniert Hardwaresteuerung, Echtzeit-Videoverarbeitung und Benutzerinteraktion zu einem integrierten System. Das Projekt bildet eine solide Grundlage für weiterführende Anwendungen wie Überwachungssysteme, Fotografie-Roboter oder interaktive Installationen.