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:
- Heftigkeits-Differential (
rudderFerocityRange): links bekommt+Heftigkeit, rechts−Heftigkeit— die zwei Flügel verweilen unterschiedlich, behalten aber eine geteilte Umkehrphase (limiarShared), daher sind Kurven reines Roll-Drehmoment, nie Desynchronisation. - Amplituden-Differential (
rudderAmplitudeDifferential): linke Amplitude ×(1+Δ), rechte ×(1−Δ) — symmetrische Divergenz um den schubgesetzten Schlag.
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:
- Motor —
SF_MOTOR: bei scharf mappt Schub 0…1 auf 1000…2000 µs; entschärft oder Link-Verlust erzwingt das Minimum (Motor gestoppt). - Ruder — identische Gleichung wie im Abschnitt oben.
- Leitwerke — zwei Familien. Klassische Profile (6/7) treiben ein separates Höhenruder:
µs = 1500 + elevatorNorm·500 + pitchPID + trim. V-Profile (3/4/5) mischen beide Kanäle elevon auf die zwei Leitwerk-Servos:
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.