Mikrocontroller und der Raspberry Pi
Strido hat zwei Computer. Ein Raspberry Pi 5 läuft mit Linux und ROS 2 und entscheidet, wohin die Beine sollen. Ein Mikrocontroller Seeed XIAO ESP32-S3 führt ein kleines Programm aus, das diese Ziele alle 5 ms in Servopulse umsetzt und den Roboter sicher hält. Diese Seite erklärt, warum die Arbeit so aufgeteilt ist und wie die Daten zwischen beiden fließen.
In Strido
- Raspberry Pi 5, 4 GB mit Active Cooler (
pi5_4gb,pi5_cooler): ROS 2 Jazzy in Docker oder nativ, mitgait_node/policy_node,mcu_bridge,sllidar_ros2und optionalcamera_ros(ros2/strido_control,ros2/strido_bringup). - Seeed XIAO ESP32-S3 (
xiao_esp32s3): Firmware infirmware/strido_esp32s3(PlatformIO, Arduino-ESP32 3.x). Die Pins stehen insrc/board_config.h, gespiegelt in und geprüft gegenhardware/electronics.yaml. - PCA9685 16-Kanal-PWM-Treiber (
pca9685, Adafruit-815-Layout) an I²C-Adresse 0x40: erzeugt die 12 Servopulse. - Verbindung: USB-CDC-Seriell, Pi USB-A → XIAO USB-C (W14), Gerätename
/dev/strido_mcuausros2/strido_bringup/config/99-strido.rules.
Zwei Arten von Computer
| Raspberry Pi 5 | XIAO ESP32-S3 | |
|---|---|---|
| Prozessor | Broadcom BCM2712, 4 × Arm Cortex-A76 mit 2,4 GHz | Espressif ESP32-S3, 2 × Xtensa LX7 mit bis zu 240 MHz |
| Speicher | 4 GB RAM, Betriebssystem auf einer 64-GB-microSD | 8 MB PSRAM, 8 MB Flash |
| Betriebssystem | Linux (Ubuntu Server 24.04 oder Raspberry Pi OS) | FreeRTOS unter dem Arduino-Core |
| Stärke | große Software: ROS 2, Docker, Python, neuronale Policy, LiDAR- und Kameratreiber | vorhersagbares Timing, sofortiger Start, direkte Steuerung von Pins und Bussen |
| Schwäche | Timing nicht garantiert; Booten dauert einige zehn Sekunden; SD-Karte kann durch Stromausfall beschädigt werden | wenig Speicher, keine Betriebssystemdienste, kein ROS |
| Leistung | typisch 5–7 W, Spitze 12 W mit Kühler | etwa 1 W inklusive LCD, IMU und PCA9685-Logik |
Ein Mikrocontroller (MCU) ist ein kompletter Computer auf einem Chip, gebaut, um dauerhaft ein Programm auszuführen und innerhalb von Mikrosekunden auf Hardware-Ereignisse zu reagieren. Ein Einplatinencomputer wie der Pi ist ein kleiner PC: Ein Allzweck-Betriebssystem teilt die CPU zwischen vielen Prozessen auf.
Echtzeit vs. „im Mittel schnell“
Eine Regelschleife ist echtzeitfähig, wenn sie ihre Deadline in jedem Zyklus einhält, nicht nur im Mittel. Die Servoschleife in Strido hat eine Deadline von 5 ms (kControlPeriodUs = 5000): Periode und Schleifenrate sind Kehrwerte,
Linux ist schnell, aber nicht deterministisch. Der Scheduler, ein USB-Interrupt, ein Schreibvorgang auf die SD-Karte, Pythons Garbage Collector oder ein ausgelasteter ROS-Node können einen Prozess um mehrere Millisekunden verzögern. Ein verspätetes Servo-Update zeigt sich als Ruck im Bein. Ein eingefrorener Prozess auf dem Pi darf außerdem niemals zwölf Servos mit 3,43 N·m dauerhaft auf ihrem letzten Befehl halten lassen.
Der XIAO führt nur seine eigene Firmware aus, aufgeteilt in zwei FreeRTOS-Tasks auf getrennten Kernen (src/main.cpp):
| Task | Kern | Priorität | Periode | Aufgabe |
|---|---|---|---|---|
controlTask | 1 | 3 (höher) | 5 ms | IMU lesen, Orientierung aktualisieren, INA260 alle 100 ms lesen, Sicherheits-Zustandsautomat ausführen, 12 Servopulse berechnen und schreiben |
commsTask | 0 | 2 | ~1 ms Polling | eingehende Frames parsen, alle 10 ms einen STATE-Frame senden (100 Hz), LCD-Gesicht alle 50 ms aktualisieren |
Durch die Aufteilung auf die Kerne kann ein Schwall serieller Daten das Servo-Update nie verzögern.
Warum beide und nicht nur einer
- Nur der Pi? Der Pi müsste Pulse erzeugen und die Sicherheit aus Linux heraus gewährleisten, ohne Timing-Garantie. Ein Absturz oder Neustart des Pi würde die Servos in einem unbekannten Zustand lassen.
- Nur der ESP32? Er kann weder ROS 2, Nav2, den LiDAR-Treiber, den Kamera-Stack noch die gelernte Policy mit ihrer numpy-Laufzeit ausführen.
- Beide: Jeder macht, was er gut kann. Der Pi plant mit 100 Hz (
gait_node,rate_hz: 100) oder 50 Hz (policy_node). Der XIAO führt mit 200 Hz aus und verantwortet alles Sicherheitskritische.
Was der XIAO selbstständig garantiert
Dies gilt unabhängig davon, was der Pi gerade tut (docs/software.md, safety.h):
- Watchdog: 200 ms kein Gelenkbefehl → Pose halten; weitere 2 s → kraftlos (Ausgänge aus). Nur Gelenkbefehle speisen den Watchdog; stirbt also der Gait-Node, hält der Roboter zuerst und wird dann kraftlos.
- Verriegelter Not-Halt:
/strido/estopzieht den Output-Enable-Pin des PCA9685 auf High. Alle Pulse stoppen sofort, und der Halt bleibt verriegelt, bis er freigegeben wird. - Akkuabschaltung: Warnung bei 6,8 V; nach 5 Messwerten unter 6,4 V kraftlos schalten und Fahren verweigern.
- Grenzen: Jedes Ziel wird auf 6 rad/s ratenbegrenzt und auf die Gelenk- und Kniekurbelgrenzen aus dem CAD-Bewegungsbereich-Sweep begrenzt. Nicht-endliche Werte (NaN) werden verworfen.
- Kein INA260, kein Fahren: Ohne Power-Monitor gibt es keine Abschaltung.
Der PWM-Treiber PCA9685
Warum erzeugt der ESP32 die zwölf Pulse nicht direkt?
- Pins. Der XIAO bietet 11 Pads (D0–D10). Neun sind bereits belegt, für das LCD (6), I²C (2) und die Output-Enable-Leitung (1). Zwölf weitere Pulsausgänge sind nicht verfügbar.
- Entlastung. Der PCA9685 hält pro Kanal einen 12-Bit-Ein/Aus-Zählwert und wiederholt die Pulse selbstständig mit 200 Hz. Die Firmware schreibt nur dann einen neuen Wert, wenn sich ein Ziel ändert.
- Eine Abschaltleitung. Sein Low-aktiver OE-Pin (Output Enable) schaltet alle 16 Ausgänge auf einmal ab, in Hardware.
- Kontinuität mit Upstream. Strido behält die Kanalbelegung des Upstream-Yertle bei (Kanäle 4–15), sodass Verkabelungswissen übertragbar bleibt.
Der OE-Pull-up
Die PCA9685-Platine zieht OE auf Low, was „Ausgänge an“ bedeutet. Während der XIAO zurückgesetzt wird oder im Bootloader steht, ist sein Pin D3 offen, und die Servos würden dem folgen, was der PCA9685 zuletzt hielt. Ein 2,2-kΩ-Widerstand von OE nach VCC hält die Ausgänge aus, bis die Firmware sie aktiv freigibt. Der Smoke-Test prüft das: Im Bootloader muss OE ≥ 2,4 V messen (docs/electronics.md, Kabelbaum-Schritt 8).
Datenfluss
Ein Zyklus, von Anfang bis Ende:
- Planen.
gait_nodewandelt den Geschwindigkeitsbefehl in 12 Gelenkwinkel in Radiant um, Go2-Reihenfolge FL, FR, RL, RR × Hüfte, Oberschenkel, Unterschenkel. - Senden.
mcu_bridgepackt sie in einenJOINT_COMMAND-Frame: Sequenznummer, Modus, 12 × float32. Er fügt eine CRC16-Prüfsumme hinzu, COBS-kodiert den Frame und schreibt ihn nach/dev/strido_mcu. - Ausführen. Bei seinem nächsten 5-ms-Takt:
- begrenzt der XIAO die Änderungsrate der Ziele;
- rechnet er den Unterschenkelwinkel über das Koppelgetriebemodell in den Kniekurbelwinkel um (
jointsToActuators); - begrenzt er auf die Gelenkgrenzen;
- rechnet er jeden Winkel mit der Kalibrierung pro Gelenk in einen Puls um;
- schreibt er die Pulse in den PCA9685.
- Melden. Alle 10 ms sendet der XIAO eine 103 Byte große
STATE-Payload: die angewendeten Gelenkwinkel, das Orientierungsquaternion, Gyroskop- und Beschleunigungsmesswerte, Busspannung, Strom und Status-Flags.mcu_bridgeveröffentlicht sie als ROS-Topics.
Da beide Seiten eine gemeinsame Protokolldefinition nutzen (packages/strido-core/src/strido/protocol.py ⇄ firmware/.../protocol.h), funktionieren dieselben Frames aus ROS, aus strido-cli auf einem Laptop und aus dem NT-X-Adapter.
Selbsttest
- Was passiert mit den Servos 200 ms und 2,2 s nach einem Absturz von
gait_node? - Nennen Sie zwei Gründe, warum die Servopulse von einem PCA9685 statt direkt vom XIAO kommen.
- Warum läuft der Regel-Task auf einem eigenen Kern mit höherer Priorität als der Kommunikations-Task?
- Was verhindert der 2,2-kΩ-Widerstand am OE-Pin des PCA9685?
- Welche Komponente rechnet den Unterschenkelwinkel in einen Kniekurbelwinkel um, und warum geschieht das nicht auf dem Pi?
Antworten
- Nach 200 ms ohne Befehle halten die Servos die letzte Pose. Nach weiteren 2 s (insgesamt 2,2 s) werden sie kraftlos, die Ausgänge sind aus.
- Zwei beliebige von: Der XIAO hat zu wenige freie Pins; der PCA9685 wiederholt die Pulse in Hardware; sein OE-Pin schaltet alle Ausgänge auf einmal ab; er behält die Upstream-Kanalbelegung bei.
- Damit serieller Datenverkehr und LCD-Updates die 5-ms-Servo-Deadline nie verzögern können.
- Dass Servos angesteuert werden, während der XIAO zurückgesetzt wird oder im Bootloader steht, wenn sein Pin D3 OE nicht aktiv auf High hält.
- Die XIAO-Firmware (
jointsToActuatorsinservo_map.cpp). Geschieht dies direkt neben Begrenzung und Pulserzeugung, kann die MCU die Kniekurbelgrenzen selbst durchsetzen, egal was der Pi sendet. Dieselbe Mathematik existiert auch instrido-corefür die Simulation.