Mixer-Referenz

Von Sticks und Gyro bis zu µs auf der Leitung: die vollständige Geometrie jedes wählbaren Mixers — Flügelachsen, Ruder-Mischungen, Elevons, Trims und Begrenzungen.

Diese Seite dokumentiert die Mixer-Schicht von src/lib/Ornithopter/Ornithopter.cpp und das Profilsystem von OrnithopterConfig.h. Für die umgebende Architektur beginnen Sie mit dem Architektur-Artikel ; für Puls-Timing und Trim-Bereiche siehe den Servo-Kernel Artikel.

Servo-Funktions-Tags

Jeder Ausgang jedes Mixers ist ein µs-Wert, geschrieben in _f[], indiziert durch einen ServoFunc-Tag. Tags sind Transport — sie sagen was ein Signal bedeutet, nie wo es verdrahtet ist:

Tag Name Bedeutung
0 SF_NONE Reserviert — keine Funktion (die ersten PWM-Slots bleiben für BOOT und I2C frei)
1 / 2 SF_LEFT_WING / SF_RIGHT_WING Vordere Schlagflügel (Wellenform-Kernel)
3 SF_RUDDER Kopf-/Kamm-Ruder (Wellenform) oder Flossenruder (Getriebe) — Gier- + Roll-Mischung
4 SF_MOTOR Brushless-ESC-Schub (nur Getriebe-Kernel)
5 / 6 SF_VTAIL_LEFT / SF_VTAIL_RIGHT V-Leitwerk-Flächen, elevon-gemischt (Getriebe-Kernel)
7 SF_ELEVATOR Traditionelles separates Höhenruder (Getriebe-Profile 6/7)
8 / 9 SF_BACK_LEFT_WING / SF_BACK_RIGHT_WING Hinteres Flügelpaar einer 4-Flügel-Zelle (Spiegel des vorderen Paars, eigener Trim)

Ein Laufzeit-Profil liefert die funcMap: ein Array, das PWM-Ausgangsindex → ServoFunc abbildet. Die ersten drei Slots (PWM 1…3) sind immer SF_NONE — sie gehören dem BOOT-Gurt und dem I2C-Bus — echte Servo-Funktionen beginnen also bei PWM-Index 3 (der Firmware-Kommentar erklärt: Index 3 = CH4, 4 = CH5, 5 = CH6).

Die acht Mixer-Profile

Acht Mixer-Profile existieren. Profile 0–2 treiben das Wellenform-Kernel (Schlagflügel), Profile 3–7 das Getriebe-Kernel (Motor + Leitwerke):

# Profil Kernel Servos funcMap (PWM 3 · 4 · 5)
0 SERVO_2WING Wellenform 2 Linker Flügel · Rechter Flügel · —
1 SERVO_2WING_1RUD Wellenform 3 Linker Flügel · Rechter Flügel · Ruder
2 SERVO_4WING Wellenform 4 (hinten-rechts teilt den Spiegel hinten-links) Linker Flügel · Rechter Flügel · Hinterer linker Flügel
3 GEARBOX_2VTAIL_1RUD Getriebe 3 Ruder · V-Leitwerk links · V-Leitwerk rechts
4 GEARBOX_1MOT_2VTAIL Getriebe 3 Motor · V-Leitwerk links · V-Leitwerk rechts
5 GEARBOX_1MOT_2VTAIL_1RUD Getriebe 4 (V-Leitwerk rechts teilt den linken Spiegel) Ruder · Motor · V-Leitwerk links
6 GEARBOX_1ELE_1RUD Getriebe 2 Ruder · Höhenruder · —
7 GEARBOX_1MOT_1ELE_1RUD Getriebe 3 Ruder · Motor · Höhenruder

Auswahl: Build-Flag MIXER_PROFILE (alt ORNITHOPTER_GEARBOX=1 → Profil 5), dann zur Laufzeit über die WebUI überschreibbar (setOrnithopterProfile). Der Kernel-Test ist schlicht activeProfile ≥ GEARBOX_2VTAIL_1RUD.

Flügelachsen-Mixing (Waveform-Kernel)

Alle Kanalwerte treten normalisiert in die Mixer ein: _crsfToNorm bildet das rohe 172…1811-Fenster linear auf −1…+1 ab. Steuerbefehle werden dann mit den Autoritäts-Slidern pro Profil (aileronScale, elevatorScale, 0–100 %) mal ±60° (ORNI_STEER_MAX_DEG) skaliert.

Spiegelgeometrie. Flügel-Servos sind spiegelverkehrt montiert, was die Bedeutung von Gleichtakt- und Differenz-Termen vertauscht. Der Code behandelt daher Querruder (Roll) als gleichtaktig — es addiert sich auf beide Flügel, was zu einer differenziellen physischen Auslenkung wird — und Höhenruder (Nick) als differentiell im Code, was zu einer gleichtaktigen physischen Auslenkung wird. Die Winkelgleichungen, mit ORNI_NEUTRAL_ANGLE_DEG = 100° und dem 2×-Multiplikator nur auf Abweichungsterme:

angleLeft  = NEUTRAL + (aileron + elevator + flapCentre − degL) · 2
angleRight = NEUTRAL + (aileron − elevator − flapCentre + degR) · 2

flapping:  degL/R = amplitudeL/R · shapedWave(rawPhase, ferocityL/R, …)
glide:     degL = degR = 0 → static glide offset takes over

degL/degR sind die momentanen Schlag-Auslenkungen des linken und rechten Flügels, jeweils das Produkt aus eigener Amplitude und einer heftigkeitsgeformten Welle. Höhenruder hoch stärkt den Abschlag; tief den Aufschlag (asymmetrische Heftigkeit). Gieren teilt die Flügel auf zwei komplementäre Weisen:

Winkel werden auf 0…180° begrenzt und mit der konfigurierbaren Hülle servoMinUs…servoMaxUs (Standard 988…2012) in Pulse gewandelt: µs = min + Winkel·(max−min)/180, plus Funktions-Trim. Die Gleit-/Flatterzentrum-Offsets (glideAngleDeg, flappingAngleDeg, ±15°) gehen als statische Terme in ihren jeweiligen Zweig ein — so lassen sich Gleit- und Flatterzentren pro Flugprofil unabhängig tunen.

Ruder-Mixing (beide Kernel)

Der Ruder-Mixer wird von beiden Kerneln wörtlich geteilt — eine Gleichung, zwei Zellen:

mix  = rudderNorm · rudderYawWeight  +  aileronNorm · rudderRollWeight
mix  = clamp(mix, −1 … +1)
µs   = 1500 + mix · 500            (rudder centre ± 500 µs)
       + gyroRudderCorrection       (Zephyrus, when enabled)
       + servoTrimUs[SF_RUDDER]

Standard: rudderYawWeight = 65%, rudderRollWeight = 35% (zur Laufzeit in der WebUI tunbar, pro Backup gespeichert). Die Roll-Kopplung auf dem Ruder lässt einen flügelschweren Pterosaurier koordinierte Kurven ohne Gierfaden-Akrobatik halten; reduzieren Sie das Roll-Gewicht, wenn das Kopf-Ruder im Roll zu aggressiv wirkt.

Leitwerks- & Elevon-Mixing (Getriebe)

Das Getriebe-Kernel läuft zustandslos jeden Tick. Seine drei Sub-Mixer:

VtailLeft  = 1500 + (aileron + elevator)·scale + rollPID + pitchPID + trimL
VtailRight = 1500 + (aileron − elevator)·scale − rollPID + pitchPID + trimR
scale = 500 µs;  both aileron/elevator sums clamped to −1…+1 first

Auf dem Getriebe-Kernel speist Zephyrus beide Roll- und Nick-PID-Korrekturen in die Leitwerk-Servos ein (Roll gegenphasig, Nick gleichtaktig), jeweils hart auf ±250 µs begrenzt (ZEPHYR_GEARBOX_CLAMP_US). Ein Gyro-Glitch kann daher wackeln, aber nie einen Leitwerk-Servo blockieren.

Zephyrus-Einspeisung, Trims & Failsafe

Je nach Kernel und Achse existieren drei verschiedene Einspeisepunkte:

Achse Wellenform-Kernel Getriebe-Kernel
Ruder / Gieren gyroRudderCorrection zu den Kamm-Ruder-µs addiert gyroRudderCorrection zu den Flossenruder-µs addiert
Roll (Querruder) — (Wellenform-Flügel tragen kein Roll-PID) gyroAileronCorrection, gegenphasig über das V-Leitwerk, ±250 µs begrenzt
Nick (Höhenruder) — (als Wellenmodulation in der Zephyrus-Schicht eingespeist) gyroElevatorCorrection, gleichtaktig, ±250 µs begrenzt

Trims & Grenzen. Jede Funktion hat einen vorzeichenbehafteten Trim pro Servo (servoTrimUs[tag], Standard 0, ±300 µs), zuletzt addiert, und jeder Wert passiert _clampServo — eine absolute 500…2500 µs-Sicherheitsklemme, die alles überstimmt. Bei Failsafe oder Link-Verlust kehren alle Funktionen auf 1500 µs und ein Getriebemotor auf Minimum zurück, sodass das Modell stets zu Neutral gleitet.

Bereit für die Praxis-Schicht? Das Wellenform-Tuning -Tutorial zeigt, wie sich diese Zahlen an den Sticks anfühlen, und der Architektur Artikel zeigt, wo jeder Mixer in der Pipeline sitzt.