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.1 Kamera

Einführung

Dieses Projekt zeigt, wie Sie mit dem Raspberry Pi Zero ein einfaches Kamerasystem mit Auslösetaste erstellen können. Wenn Sie die Taste drücken, nimmt die Kamera ein Foto auf, und eine LED blinkt zur Bestätigung der Aktion. Dieses Projekt ist eine gute Möglichkeit, praktische Erfahrung mit GPIO-Steuerung und dem Raspberry-Pi-Kameramodul zu sammeln.


Was Sie benötigen

Für dieses Projekt werden die folgenden Komponenten benötigt:

KOMPONENTENBESCHREIBUNG

KAUFLINK

Steckbrett

BUY

Jumper-Kabel

BUY

Widerstand

BUY

LED

BUY

Taste

BUY

Kameramodul

BUY

Fusion HAT+

-

Raspberry Pi

-


Schaltplan

Nachfolgend ist die GPIO-Pinbelegung für dieses Projekt dargestellt:

../_images/4.1.1_sch.png

Verdrahtungsdiagramm

  1. Um das Kameramodul bequem zu verwenden, wird Pan-Tilt montieren (für die Kamera) empfohlen.

    Bemerkung

    Das Zusammenbauen der Pan-Tilt-Halterung kann einige Pins verdecken. Daher wird empfohlen, sie nur bei Verwendung der Kamera zu montieren oder sie nach der Montage außen zu platzieren.

    ../_images/gimbal_assemble.png
  2. Folgen Sie diesem Verdrahtungsdiagramm, um die Schaltung aufzubauen:

    ../_images/4.1.1_bb.png

Beispiel ausführen

  1. Greifen Sie auf den Raspberry-Pi-Desktop zu:

    • Remote Desktop: Verwenden Sie VNC für eine vollständige Desktop-Umgebung.

    • Raspberry Pi Connect: Verwenden Sie Raspberry Pi Connect, um sicher über einen Browser auf Ihren Pi zuzugreifen.

  2. Öffnen Sie ein Terminal und wechseln Sie in den Code-Ordner:

    cd ~/ai-lab-kit/python
    
  3. Führen Sie das Skript aus, um die Kamera zu starten:

    sudo python3 4.1_Camera.py
    
  4. Nach dem Start des Programms beginnt die Kamera zu arbeiten.

    • Drücken Sie die Taste, um ein Foto aufzunehmen:

      • Die LED leuchtet auf.

      • Ein Foto wird aufgenommen und im Ordner Pictures gespeichert (zum Beispiel photo_001.jpg, photo_002.jpg).

    • Lassen Sie die Taste los:

      • Die LED erlischt.

    • Das Programm läuft weiter, bis Sie Ctrl + C drücken. Danach wird es ohne Fehlermeldung sauber beendet.

    Bemerkung

    Die QT-Vorschau erfordert eine Desktop-Umgebung. Wenn die Vorschau nicht gestartet werden kann (z. B. bei Zugriff über SSH), kann die Kamera dennoch Fotos aufnehmen und normal speichern.


Code

Hier ist der in diesem Projekt verwendete Python-Code:

#!/usr/bin/env python3

import os
import time
import threading
from picamera2 import Picamera2, Preview
from fusion_hat.pin import Pin, Mode, Pull

# Resolve the correct user's home directory (works with sudo)
REAL_USER = os.getenv("SUDO_USER") or os.getlogin()
USER_HOME = f"/home/{REAL_USER}"
PICTURES_DIR = os.path.join(USER_HOME, "Pictures")
os.makedirs(PICTURES_DIR, exist_ok=True)

# Initialize camera
camera = Picamera2()
camera.configure(camera.create_preview_configuration(main={"size": (800, 600)}))

# Photo counter with thread safety
photo_index = 1
photo_lock = threading.Lock()

# Track whether preview was started successfully
preview_started = False

# Initialize LED and button
led = Pin(17, mode=Mode.OUT)
button = Pin(4, mode=Mode.IN, pull=Pull.DOWN)

def take_photo():
   """Capture one photo and increment the index."""
   global photo_index
   with photo_lock:
      filepath = os.path.join(PICTURES_DIR, f"photo_{photo_index:03d}.jpg")
      print(f"\nCapturing: {filepath}")
      camera.capture_file(filepath)
      print("Saved.")
      photo_index += 1

def main():
   global preview_started

   # Start preview only when a GUI display is available (remote SSH often has no DISPLAY)
   preview_started = False
   if os.getenv("DISPLAY"):
      try:
            camera.start_preview(Preview.QT)
            preview_started = True
      except Exception as e:
            preview_started = False
            print(f"Preview start failed (continue without preview): {e}")
   else:
      print("No DISPLAY detected (running headless without preview).")

   camera.start()

   print("Camera is running.")
   print("Press the button to take a photo.")
   print(f"Photos will be saved to: {PICTURES_DIR}")
   print("Press Ctrl+C to exit.\n")

   try:
      while True:
            if button.value():         # Button pressed (HIGH)
               led.on()               # LED on
               take_photo()           # Take photo
               time.sleep(0.3)        # Simple debounce (avoid multiple shots)
               while button.value():  # Wait until button is released
                  time.sleep(0.01)
               led.off()              # LED off after release

            time.sleep(0.01)

   except KeyboardInterrupt:
      print("\nExiting...")

   finally:
      # Turn off LED
      try:
            led.off()
      except Exception:
            pass

      # Stop the camera first
      try:
            camera.stop()
      except Exception:
            pass

      # Stop preview only if it was started
      if preview_started:
            try:
               camera.stop_preview()
            except Exception:
               pass

      try:
            camera.close()
      except Exception:
            pass

if __name__ == "__main__":
   main()

Code verstehen

  1. Importe und Zweck

    import os
    import time
    import threading
    from picamera2 import Picamera2, Preview
    from fusion_hat.pin import Pin, Mode, Pull
    

    Diese Module sind für folgende Aufgaben zuständig:

    • os: zum Umgang mit Umgebungsvariablen und Dateipfaden.

    • time: für Zeitverzögerungen und um die Hauptschleife am Laufen zu halten.

    • threading: sorgt dafür, dass das Aufnehmen von Fotos thread-sicher erfolgt.

    • Picamera2 und Preview: zur Steuerung der Raspberry-Pi-Kamera und der Vorschau-Modi.

    • Pin, Mode und Pull: zur Steuerung der LED und zum Auslesen des Tasters über das Fusion HAT.

  2. Bestimmen des Speicherverzeichnisses (funktioniert mit sudo)

    REAL_USER = os.getenv("SUDO_USER") or os.getlogin()
    USER_HOME = f"/home/{REAL_USER}"
    PICTURES_DIR = os.path.join(USER_HOME, "Pictures")
    os.makedirs(PICTURES_DIR, exist_ok=True)
    

    Dieser Abschnitt stellt sicher, dass Fotos immer im Verzeichnis ~/Pictures des tatsächlichen Benutzers gespeichert werden:

    • Wenn das Skript mit sudo ausgeführt wird, verweist SUDO_USER auf den ursprünglichen Benutzer.

    • Wenn sudo nicht verwendet wird, wird der aktuell angemeldete Benutzer verwendet.

    • Der Ordner Pictures wird automatisch erstellt, falls er noch nicht existiert.

  3. Initialisierung und Konfiguration der Kamera

    camera = Picamera2()
    camera.configure(camera.create_preview_configuration(main={"size": (800, 600)}))
    

    Die Kamera wird initialisiert und für Vorschau und Fotoaufnahme konfiguriert:

    • Es wird eine Vorschauauflösung von 800 × 600 verwendet.

    • Diese Konfiguration funktioniert sowohl mit als auch ohne sichtbares Vorschaufenster.

  4. Fotoindex und Thread-Sicherheit

    photo_index = 1
    photo_lock = threading.Lock()
    
    • photo_index speichert die aktuelle Bildnummer.

    • photo_lock verhindert, dass mehrere Tastendrücke gleichzeitig überlappende Fotoaufnahmen auslösen.

  5. Status der Vorschau

    preview_started = False
    

    Dieses Flag speichert, ob ein Vorschaufenster erfolgreich gestartet wurde, sodass das Programm nur dann versucht, die Vorschau zu beenden, wenn sie tatsächlich existiert.

  6. LED- und Tasterkonfiguration

    led = Pin(17, mode=Mode.OUT)
    button = Pin(4, mode=Mode.IN, pull=Pull.DOWN)
    
    • Die LED ist mit GPIO 17 verbunden und als Ausgang konfiguriert.

    • Der Taster ist mit GPIO 4 verbunden und als Eingang mit internem Pull-Down-Widerstand konfiguriert.

    • Ein HIGH-Signal bedeutet, dass die Taste gedrückt wurde.

  7. Funktion zum Aufnehmen eines Fotos

    def take_photo():
       """Capture one photo and increment the index."""
       global photo_index
       with photo_lock:
          filepath = os.path.join(PICTURES_DIR, f"photo_{photo_index:03d}.jpg")
          print(f"\nCapturing: {filepath}")
          camera.capture_file(filepath)
          print("Saved.")
          photo_index += 1
    

    Diese Funktion:

    • erstellt einen Dateinamen wie photo_001.jpg.

    • nimmt ein Bild mit der Kamera auf.

    • erhöht den Fotoindex, sodass das nächste Bild einen neuen Namen erhält.

  8. Bedingte Vorschau für lokale und entfernte Nutzung

    preview_started = False
    if os.getenv("DISPLAY"):
       try:
             camera.start_preview(Preview.QT)
             preview_started = True
       except Exception as e:
             preview_started = False
             print(f"Preview start failed (continue without preview): {e}")
    else:
       print("No DISPLAY detected (running headless without preview).")
    
    • Wenn eine grafische Desktop-Umgebung verfügbar ist, wird eine QT-Vorschau gestartet.

    • Wenn das Programm über SSH ohne Anzeige ausgeführt wird, wird die Vorschau übersprungen.

    • Die Fotoaufnahme funktioniert in beiden Fällen normal.

  9. Hauptschleife und Tasterlogik

    try:
       while True:
             if button.value():         # Button pressed (HIGH)
                led.on()               # LED on
                take_photo()           # Take photo
                time.sleep(0.3)        # Simple debounce (avoid multiple shots)
                while button.value():  # Wait until button is released
                   time.sleep(0.01)
                led.off()              # LED off after release
    
             time.sleep(0.01)
    

    Innerhalb der Hauptschleife:

    • Beim Drücken der Taste wird die LED eingeschaltet.

    • Sofort wird ein Foto aufgenommen.

    • Das Programm wartet, bis die Taste losgelassen wird, um Mehrfachaufnahmen zu vermeiden.

    • Nach dem Loslassen der Taste wird die LED ausgeschaltet.

  10. Sauberes Beenden und Freigabe der Ressourcen

    except KeyboardInterrupt:
       print("\nExiting...")
    
    finally:
       # Turn off LED
       try:
             led.off()
       except Exception:
    
    ...
    

    Wenn Ctrl+C gedrückt wird:

    • Die LED wird ausgeschaltet.

    • Die Kamerapipeline wird gestoppt.

    • Die Vorschau wird nur beendet, wenn sie zuvor gestartet wurde.

    • Die Kameraressourcen werden sauber freigegeben.

    Dadurch wird sichergestellt, dass das Programm ohne Fehler beendet wird – sowohl bei lokaler Ausführung mit Bildschirm als auch im Headless-Modus.


Fehlerbehebung

  1. Foto wird nicht aufgenommen:

    • Ursache: Der Taster ist falsch angeschlossen oder die Kamera wurde nicht initialisiert.

    • Lösung:

      • Stellen Sie sicher, dass der Taster mit GPIO-Pin 4 und GND verbunden ist.

      • Prüfen Sie, ob die Kamera korrekt angeschlossen und über raspi-config aktiviert ist.

  2. LED blinkt nicht:

    • Ursache: Falsche Verdrahtung der LED oder falsche GPIO-Konfiguration.

    • Lösung:

      • Stellen Sie sicher, dass die LED mit GPIO-Pin 17 über einen passenden Widerstand verbunden ist.

      • Testen Sie die LED separat, um sicherzustellen, dass sie funktioniert.

  3. Skript stürzt mit einem Kamerafehler ab:

    • Ursache: Das Kameramodul wird nicht erkannt oder wird von einem anderen Prozess verwendet.

    • Lösung:

      • Stellen Sie sicher, dass die Kamera korrekt angeschlossen ist, und starten Sie den Raspberry Pi neu.

      • Prüfen Sie auf Konflikte mit sudo lsof /dev/video*.


Erweiterungsideen

  1. Mehrere Fotos: Erlauben Sie das Aufnehmen mehrerer Fotos in einer Sitzung, jeweils mit einem eindeutigen Dateinamen:

    counter = 0
    camera.capture_file(f'{user_home}/photo_{counter}.jpg')
    counter += 1
    
  2. Videoaufnahme: Erweitern Sie die Funktion, sodass beim Drücken der Taste ein Video aufgenommen wird:

    camera.start_recording(f'{user_home}/my_video.h264')
    time.sleep(10)
    camera.stop_recording()
    
  3. LED-Statusanzeige: Verwenden Sie die LED, um den Status der Kamera anzuzeigen:

    • Dauerlicht: Kamera bereit.

    • Blinken: Foto wird aufgenommen.

  4. Fotoverwaltung: Organisieren Sie aufgenommene Fotos in Ordnern nach Datum oder Ereignis.

  5. Zeitrafferfotografie: Nehmen Sie in regelmäßigen Abständen Fotos auf, um einen Zeitraffer zu erstellen:

    for i in range(10):
        camera.capture_file(f'{user_home}/timelapse_{i}.jpg')
        time.sleep(5)
    

Fazit

Dieses Projekt zeigt eine grundlegende Kameraanwendung mit einem tastergesteuerten Auslösemechanismus. Es kombiniert GPIO-Steuerung mit der Picamera2-Bibliothek und demonstriert, wie interaktive Raspberry-Pi-Projekte erstellt werden können. Experimentieren Sie weiter, um zusätzliche Funktionen zu integrieren und noch vielseitigere Anwendungen zu entwickeln.