AIRASPI Build-Protokoll

Von Aron Petau12 Minuten gelesen

AI-Raspi Build-Protokoll

Dieses Dokument dokumentiert den Prozess des Baus eines maßgeschneiderten Edge-Computing-Geräts für Echtzeit-Bilderkennung und Objektdetektion. Das Ziel war es, ein portables, eigenständiges System zu schaffen, das unabhängig von Cloud-Infrastruktur funktionieren kann.

Projektziele:

Bau eines Edge-Geräts mit Bilderkennung und Objektdetektion, das Video in Echtzeit verarbeiten kann, mit dem Ziel von 30fps bei 720p-Auflösung. Portabilität und autonomer Betrieb sind kritische Anforderungen—das Gerät muss ohne aktive Internetverbindung funktionieren und einen kompakten Formfaktor für Installationsumgebungen beibehalten. Alle Berechnungen finden lokal auf dem Gerät selbst statt, was es zu einer echten Edge-Computing-Lösung ohne Cloud-Abhängigkeit macht.

Dieses Projekt wurde inspiriert von pose2art, das das kreative Potenzial der Echtzeit-Posenerkennung für interaktive Installationen demonstrierte.

Hardware

Setup

Hauptressourcen

Dieser Build wäre ohne die exzellente Dokumentation und Troubleshooting-Anleitungen aus der Community nicht möglich gewesen. Die Hauptquellen, auf die ich mich während dieses Projekts verlassen habe, waren:

Raspberry Pi OS Installation

Ich habe den Raspberry Pi Imager verwendet, um das neueste Raspberry Pi OS auf eine SD-Karte zu flashen. Die OS-Wahl ist kritisch für die Kamerakompatibilität.

Muss Debian Bookworm sein. Muss das vollständige arm64-Image (mit Desktop) sein, sonst gerät man in die Kameratreiber-Hölle.

Initiale Konfigurationseinstellungen:

Mit den erweiterten Einstellungen des Raspberry Pi Imager habe ich vor dem Flashen Folgendes konfiguriert:

System-Update

Nach dem ersten Boot ist das Aktualisieren des Systems unerlässlich. Dieser Prozess kann mit dem vollständigen Desktop-Image beträchtliche Zeit in Anspruch nehmen, stellt aber sicher, dass alle Pakete aktuell sind und Sicherheitspatches angewendet werden.

sudo apt update && sudo apt upgrade -y && sudo reboot

Vorbereitung des Systems für Coral TPU

Die PCIe-Schnittstelle des Raspberry Pi 5 erfordert eine spezifische Konfiguration, um mit der Coral Edge TPU zu funktionieren. Dieser Abschnitt war technisch am anspruchsvollsten und umfasste Kernel-Modifikationen und Device-Tree-Änderungen. Ein großes Dankeschön an Jeff Geerling für die Dokumentation dieses Prozesses—ohne sein detailliertes Troubleshooting wäre dies nahezu unmöglich gewesen.

# Kernel-Version prüfen
uname -a
# config.txt modifizieren
sudo nano /boot/firmware/config.txt

Während man in der Datei ist, folgende Zeilen hinzufügen:

kernel=kernel8.img
dtparam=pciex1
dtparam=pciex1_gen=2

Speichern und neu starten:

sudo reboot
# Kernel-Version erneut prüfen
uname -a

/boot/firmware/cmdline.txt bearbeiten

sudo nano /boot/firmware/cmdline.txt
sudo reboot

Modifizierung des Device Tree

Initialer Script-Versuch (Veraltet)

Anfangs gab es ein automatisiertes Script, das die Device-Tree-Modifikationen handhaben sollte. Jedoch erwies sich dieses Script als problematisch und verursachte Probleme während meines Builds.

vielleicht ist dieses Script das Problem? ich werde es ohne erneut versuchen

curl https://gist.githubusercontent.com/dataslayermedia/714ec5a9601249d9ee754919dea49c7e/raw/32d21f73bd1ebb33854c2b059e94abe7767c3d7e/coral-ai-pcie-edge-tpu-raspberrypi-5-setup | sh

Ja, es war das problematische Script. Ich habe einen Kommentar dokumentiert, der das Problem auf dem ursprünglichen Gist beschreibt: Mein Kommentar auf dem Gist

Manuelle Device-Tree-Modifikation (Empfohlen)

Anstatt mich auf das automatisierte Script zu verlassen, folgte ich Jeff Geerlings manuellem Ansatz. Diese Methode gibt vollständige Kontrolle über den Prozess und hilft zu verstehen, was tatsächlich unter der Haube passiert.

In der Zwischenzeit wurde das Script aktualisiert und wird nun wieder empfohlen.

Der Device-Tree-Modifikationsprozess umfasst das Sichern des aktuellen Device-Tree-Blobs (DTB), das Dekompilieren in ein lesbares Format, das Bearbeiten der MSI-Parent-Referenz zur Behebung von PCIe-Kompatibilitätsproblemen und dann das Zurückkompilieren in Binärformat. Hier ist der schrittweise Prozess:

1. Device Tree sichern und dekompilieren

# Aktuelles dtb sichern
sudo cp /boot/firmware/bcm2712-rpi-5-b.dtb /boot/firmware/bcm2712-rpi-5-b.dtb.bak

# Aktuelles dtb dekompilieren (Warnungen ignorieren)
dtc -I dtb -O dts /boot/firmware/bcm2712-rpi-5-b.dtb -o ~/test.dts

# Datei bearbeiten
nano ~/test.dts

# Zeile ändern: msi-parent = <0x2f>; (unter `pcie@110000`)
# Zu: msi-parent = <0x66>;
# Dann Datei speichern.

# dtb rekompilieren und zurück ins Firmware-Verzeichnis verschieben
dtc -I dts -O dtb ~/test.dts -o ~/test.dtb
sudo mv ~/test.dtb /boot/firmware/bcm2712-rpi-5-b.dtb

# Neustart für Änderungen
sudo reboot

Hinweis: msi-parent scheint heutzutage den Wert <0x2c> zu haben, hat mich ein paar Stunden gekostet.

2. Änderungen verifizieren

Nach dem Neustart prüfen, dass die Coral TPU vom System erkannt wird:

lspci -nn | grep 089a

Die Ausgabe sollte ähnlich sein: 0000:01:00.0 System peripheral [0880]: Global Unichip Corp. Coral Edge TPU [1ac1:089a]

Installation des Apex-Treibers

Mit dem ordnungsgemäß konfigurierten Device Tree ist der nächste Schritt die Installation von Googles Apex-Treiber für die Coral Edge TPU. Dieser Treiber ermöglicht die Kommunikation zwischen Betriebssystem und TPU-Hardware.

Gemäß den offiziellen Anweisungen von coral.ai:

echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list

curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -

sudo apt-get update

sudo apt-get install gasket-dkms libedgetpu1-std

sudo sh -c "echo 'SUBSYSTEM==\"apex\", MODE=\"0660\", GROUP=\"apex\"' >> /etc/udev/rules.d/65-apex.rules"

sudo groupadd apex

sudo adduser $USER apex

sudo reboot

Diese Sequenz:

  1. Fügt Googles Paket-Repository und GPG-Schlüssel hinzu
  2. Installiert das gasket DKMS-Modul (Kernel-Treiber) und Edge-TPU-Runtime-Bibliothek
  3. Erstellt udev-Regeln für Geräteberechtigungen
  4. Erstellt eine apex-Gruppe und fügt den Benutzer hinzu
  5. Neustart zum Laden des Treibers

Nach dem Neustart Installation verifizieren:

lspci -nn | grep 089a

Dies sollte die verbundene Coral TPU als PCIe-Gerät anzeigen.

Als Nächstes bestätigen, dass der Device-Node mit entsprechenden Berechtigungen existiert:

ls -l /dev/apex_0

Wenn die Ausgabe /dev/apex_0 mit entsprechenden Gruppenberechtigungen zeigt, war die Installation erfolgreich. Falls nicht, udev-Regeln und Gruppenzugehörigkeit überprüfen.

Testen mit Beispielmodellen

Um zu verifizieren, dass die TPU korrekt funktioniert, verwenden wir Googles Beispiel-Klassifizierungsskript mit einem vortrainierten MobileNet-Modell:

# Python-Pakete installieren
sudo apt-get install python3-pycoral

# Beispiel-Code und Modelle herunterladen
mkdir -p ~/coral && cd ~/coral
git clone https://github.com/google-coral/pycoral.git
cd pycoral

# Vogel-Klassifizierungsbeispiel ausführen
python3 examples/classify_image.py \
  --model test_data/mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite \
  --labels test_data/inat_bird_labels.txt \
  --input test_data/parrot.jpg

Die Ausgabe sollte Inferenz-Ergebnisse mit Konfidenzwerten zeigen, was bestätigt, dass die Edge TPU korrekt funktioniert.

Docker-Installation

Docker bietet Containerisierung für die Anwendungen, die wir ausführen werden (Frigate, MediaMTX, etc.). Dies hält Abhängigkeiten isoliert und macht das Deployment wesentlich sauberer.

Docker mit dem offiziellen Convenience-Script von docker.com installieren:

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER

Nach der Installation ab- und wieder anmelden, damit Änderungen der Gruppenzugehörigkeit wirksam werden.

Docker so konfigurieren, dass es automatisch beim Booten startet:

sudo systemctl enable docker.service
sudo systemctl enable containerd.service

Edge TPU testen (Optional)

Um zu verifizieren, dass die Edge TPU innerhalb eines Docker-Containers funktioniert, können wir ein Test-Image bauen. Dies ist besonders nützlich, wenn man plant, die TPU mit containerisierten Anwendungen zu nutzen.

Test-Verzeichnis und Dockerfile erstellen:

mkdir coraltest
cd coraltest
sudo nano Dockerfile

In die neue Datei einfügen:

FROM debian:10

WORKDIR /home
ENV HOME /home
RUN cd ~
RUN apt-get update
RUN apt-get install -y git nano python3-pip python-dev pkg-config wget usbutils curl

RUN echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" \
| tee /etc/apt/sources.list.d/coral-edgetpu.list
RUN curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
RUN apt-get update
RUN apt-get install -y edgetpu-examples
RUN apt-get install libedgetpu1-std
CMD /bin/bash

Test-Container bauen und ausführen, Coral-Gerät durchreichen:

# Docker-Container bauen
docker build -t "coral" .

# Docker-Container ausführen
docker run -it --device /dev/apex_0:/dev/apex_0 coral /bin/bash

Innerhalb des Containers ein Inferenz-Beispiel ausführen:

# Inferenz-Beispiel innerhalb des Containers ausführen
python3 /usr/share/edgetpu/examples/classify_image.py --model /usr/share/edgetpu/examples/models/mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite --label /usr/share/edgetpu/examples/models/inat_bird_labels.txt --image /usr/share/edgetpu/examples/images/bird.bmp

Man sollte Inferenz-Ergebnisse mit Konfidenzwerten von der Edge TPU sehen. Falls nicht, einen sauberen Neustart des Systems versuchen.

Portainer (Optional)

Portainer bietet eine webbasierte GUI für die Verwaltung von Docker-Containern, Images und Volumes. Obwohl nicht erforderlich, macht es das Container-Management deutlich komfortabler.

Dies ist optional, gibt einem eine Browser-GUI für die verschiedenen Docker-Container.

Portainer installieren:

docker volume create portainer_data
docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest

Portainer im Browser aufrufen und Admin-Passwort setzen:

VNC-Setup (Optional)

VNC bietet Remote-Desktop-Zugriff auf den Headless-Raspberry Pi. Dies ist besonders nützlich zum Testen von Kameras und Debuggen von visuellen Problemen, ohne einen physischen Monitor anzuschließen.

Dies ist optional, nützlich zum Testen der Kameras auf dem Headless-Gerät. Man könnte einen Monitor anschließen, aber ich finde VNC bequemer.

VNC über das Raspberry Pi Konfigurationstool aktivieren:

sudo raspi-config

Navigieren zu: Interface OptionsVNCEnable

Verbindung über VNC Viewer

RealVNC Viewer auf dem Computer installieren (verfügbar für macOS, Windows und Linux).

Mit der Adresse verbinden: airaspi.local:5900

Man wird nach Benutzernamen und Passwort des Raspberry Pi gefragt. Nach der Verbindung hat man vollen Remote-Desktop-Zugriff zum Testen von Kameras und Debuggen.

Frigate NVR Setup

Frigate ist ein vollständiger Network Video Recorder (NVR) mit Echtzeit-Objektdetektion, angetrieben von der Coral Edge TPU. Es ist das Herzstück dieses Edge-AI-Systems.

Docker Compose Konfiguration

Dieses Setup verwendet Docker Compose, um den Frigate-Container mit allen notwendigen Konfigurationen zu definieren. Wenn man Portainer verwendet, kann man dies als Custom Stack hinzufügen.

Wichtig: Die Pfade müssen auf die eigenen Pfade angepasst werden.

version: "3.9"
services:
  frigate:
    container_name: frigate
    privileged: true # dies ist möglicherweise nicht für alle Setups notwendig
    restart: unless-stopped
    image: ghcr.io/blakeblackshear/frigate:stable
    shm_size: "64mb" # für Kameras basierend auf obiger Berechnung aktualisieren
    devices:
      - /dev/apex_0:/dev/apex_0 # reicht PCIe Coral durch, Treiberanweisungen hier folgen https://coral.ai/docs/m2/get-started/#2a-on-linux

    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /home/aron/frigate/config.yml:/config/config.yml # durch eigene Config-Datei ersetzen
      - /home/aron/frigate/storage:/media/frigate # durch eigenes Storage-Verzeichnis ersetzen
      - type: tmpfs # Optional: 1GB Speicher, reduziert SSD/SD-Karten-Verschleiß
        target: /tmp/cache
        tmpfs:
          size: 1000000000
    ports:
      - "5000:5000"
      - "8554:8554" # RTSP feeds
      - "8555:8555/tcp" # WebRTC über tcp
      - "8555:8555/udp" # WebRTC über udp
    environment:
      FRIGATE_RTSP_PASSWORD: "******"

Wichtige Konfigurationspunkte in dieser Docker-Compose-Datei:

Frigate-Konfigurationsdatei

Frigate benötigt eine YAML-Konfigurationsdatei, um Kameras, Detektoren und Detektionszonen zu definieren. Diese Datei am Pfad erstellen, der in der docker-compose-Datei angegeben wurde (z.B. /home/aron/frigate/config.yml).

Dies ist nur einmal notwendig. Danach kann man die Konfiguration in der GUI ändern.

Hier ist eine funktionierende Konfiguration mit der Coral TPU:

mqtt:
  enabled: False

detectors:
  cpu1:
    type: cpu
    num_threads: 3
  coral_pci:
    type: edgetpu
    device: pci

cameras:
  cam1: # <++++++ Kamera benennen
    ffmpeg:
      hwaccel_args: preset-rpi-64-h264
      inputs:
        - path: rtsp://192.168.1.58:8900/cam1
          roles:
            - detect
  cam2: # <++++++ Kamera benennen
    ffmpeg:
      hwaccel_args: preset-rpi-64-h264
      inputs:
        - path: rtsp://192.168.1.58:8900/cam2
          roles:
            - detect
    detect:
      enabled: True # <+++- Detektion deaktivieren bis funktionierende Kamera-Feeds vorhanden
      width: 1280 # <+++- für Kameraauflösung aktualisieren
      height: 720 # <+++- für Kameraauflösung aktualisieren

Diese Konfiguration:

MediaMTX Setup

MediaMTX ist ein Echtzeit-Medienserver, der das Streaming von den Raspberry-Pi-Kameras zu Frigate handhabt. Es ist notwendig, weil Frigate libcamera (den modernen Raspberry Pi Kamera-Stack) nicht direkt unterstützt.

MediaMTX direkt auf dem System installieren (nicht via Docker - die Docker-Version hat Kompatibilitätsprobleme mit libcamera).

Chip-Architektur beim Download doppelt prüfen - dies verursachte mir erhebliche Kopfschmerzen beim Setup.

MediaMTX herunterladen und installieren:

mkdir mediamtx
cd mediamtx
wget https://github.com/bluenviron/mediamtx/releases/download/v1.5.0/mediamtx_v1.5.0_linux_arm64v8.tar.gz

tar xzvf mediamtx_v1.5.0_linux_arm64v8.tar.gz && rm mediamtx_v1.5.0_linux_arm64v8.tar.gz

MediaMTX-Konfiguration

Die mediamtx.yml-Datei bearbeiten, um Kamera-Streams zu konfigurieren. Die untenstehende Konfiguration verwendet rpicam-vid (Raspberry Pis modernes Kamera-Tool), das durch FFmpeg geleitet wird, um RTSP-Streams zu erstellen.

Folgendes zum paths-Abschnitt in mediamtx.yml hinzufügen:

paths:
 cam1:
   runOnInit: bash -c 'rpicam-vid -t 0 --camera 0 --nopreview --codec yuv420 --width 1280 --height 720 --inline --listen -o - | ffmpeg -f rawvideo -pix_fmt yuv420p -s:v 1280x720 -i /dev/stdin -c:v libx264 -preset ultrafast -tune zerolatency -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH'
   runOnInitRestart: yes
 cam2:
   runOnInit: bash -c 'rpicam-vid -t 0 --camera 1 --nopreview --codec yuv420 --width 1280 --height 720 --inline --listen -o - | ffmpeg -f rawvideo -pix_fmt yuv420p -s:v 1280x720 -i /dev/stdin -c:v libx264 -preset ultrafast -tune zerolatency -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH'
   runOnInitRestart: yes

Diese Konfiguration:

Port-Konfiguration

Standard-RTSP-Port ändern, um Konflikte mit Frigate zu vermeiden:

In mediamtx.yml ändern:

rtspAddress: :8554

Zu:

rtspAddress: :8900

Sonst gibt es einen Port-Konflikt mit Frigate.

MediaMTX starten

MediaMTX im Vordergrund ausführen, um zu verifizieren, dass es funktioniert:

./mediamtx

Wenn keine Fehler auftreten, Streams mit VLC oder einem anderen RTSP-Client verifizieren:

Hinweis: Standard-RTSP-Port ist 8554, aber wir haben ihn in der Konfiguration auf 8900 geändert.

Aktueller Status und Performance

Was funktioniert

Das System streamt erfolgreich von beiden Kameras mit 30fps und 720p-Auflösung. Die Coral Edge TPU führt Objektdetektion mit minimaler Latenz durch - die TPU selbst kommt nicht ins Schwitzen und behält durchgehend hohe Performance bei.

Laut Frigate-Dokumentation kann die TPU bis zu 10 Kameras handhaben, es gibt also erheblichen Spielraum für Erweiterung.

Aktuelle Probleme

Es gibt jedoch mehrere signifikante Probleme, die das System behindern:

1. Frigate Display-Limitierungen

Frigate begrenzt die Display-FPS auf 5, was deprimierend anzusehen ist, besonders da die TPU nicht einmal ins Schwitzen kommt. Die Hardware ist eindeutig zu viel mehr fähig, aber Software-Limitierungen halten sie zurück.

2. Stream-Stabilitätsprobleme

Der Stream ist völlig unberechenbar und droppt ständig Frames. Ich habe manchmal Detektions-FPS von nur 0,2 beobachtet, aber die TPU-Geschwindigkeit sollte definitiv nicht der Flaschenhals sein. Eine mögliche Lösung könnte sein, die Kameras an ein separates Gerät anzuschließen und von dort zu streamen.

3. Coral-Software-Aufgabe

Das größte Problem ist, dass Google das Coral-Ökosystem scheinbar aufgegeben hat, obwohl sie gerade neue Hardware dafür veröffentlicht haben. Ihr aktuellster Python-Build unterstützt nur Python 3.9.

Speziell scheint pycoral das Problem zu sein - ohne ein ordentliches Update bin ich auf Debian 10 mit Python 3.7.3 beschränkt. Das ist mies. Es gibt Custom-Wheels, aber nichts, das plug-and-play zu sein scheint.

Dies schränkt die Fähigkeit, moderne Software und Bibliotheken mit dem System zu nutzen, erheblich ein.

Reflexionen und Lessons Learned

Hardware-Entscheidungen

Die M.2 E Key-Wahl

Die Entscheidung, die M.2 E Key-Version zu nehmen, um Geld zu sparen, anstatt mehr für die USB-Version auszugeben, war ein riesiger Fehler. Bitte tu dir selbst einen Gefallen und gib die zusätzlichen 40 Euro aus.

Technisch ist sie wahrscheinlich schneller und besser für Dauerbetrieb, aber ich habe den Vorteil davon noch nicht gespürt. Die USB-Version hätte wesentlich mehr Flexibilität und einfacheres Debugging geboten.

Zukünftige Entwicklung

Mehrere Verbesserungen und Experimente sind geplant, um dieses System zu erweitern:

Dokumentation und visuelle Hilfsmittel

Mobile-Stream-Integration

MediaMTX libcamera-Unterstützung

Frigate-Konfigurationsverfeinerung

Speichererweiterung

Datenexport-Fähigkeiten

Dual-TPU-Zugriff