Référence des mixers

Des manches et du gyroscope aux µs sur le fil : la géométrie complète de chaque mixer sélectionnable — axes d'aile, mélanges de dérive, elevons, trims et limites.

Cette page documente la couche mixeur de src/lib/Ornithopter/Ornithopter.cpp et le système de profils de OrnithopterConfig.h. Pour l'architecture environnante, commencez par l' article Architecture ; pour la temporisation des impulsions et les plages de trim, voir l' Noyau servo article.

Étiquettes de fonction de servo

Chaque sortie de chaque mixeur est une valeur µs écrite dans _f[], indexée par une étiquette ServoFunc. Les étiquettes sont du transport — elles disent ce que signifie un signal, jamais il est câblé :

Étiquette Nom Signification
0 SF_NONE Réservé — aucune fonction (les premiers créneaux PWM restent libres pour BOOT et I2C)
1 / 2 SF_LEFT_WING / SF_RIGHT_WING Ailes battantes avant (noyau forme d'onde)
3 SF_RUDDER Gouvernail de tête/crête (forme d'onde) ou de dérive (boîte) — mélange lacet + roulis
4 SF_MOTOR Gaz d'ESC brushless (noyau boîte uniquement)
5 / 6 SF_VTAIL_LEFT / SF_VTAIL_RIGHT Empennages en V, mélange élevon (noyau boîte)
7 SF_ELEVATOR Profondeur séparée classique (profils boîte 6/7)
8 / 9 SF_BACK_LEFT_WING / SF_BACK_RIGHT_WING Paire d'ailes arrière d'une cellule 4 ailes (miroir de la paire avant, trim propre)

Un profil d'exécution fournit la funcMap : un tableau qui mappe l'index de sortie PWM → ServoFunc. Les trois premiers créneaux (PWM 1…3) sont toujours SF_NONE — ils appartiennent à la sangle BOOT et au bus I2C — donc les vraies fonctions de servo commencent à l'index PWM 3 (le commentaire du firmware l'explicite : index 3 = CH4, 4 = CH5, 5 = CH6).

Les huit profils de mixer

Huit profils de mixeur existent. Les profils 0–2 pilotent le noyau forme d'onde (ailes battantes), les profils 3–7 le noyau boîte de vitesses (moteur + empennages) :

# Profil Noyau Servos funcMap (PWM 3 · 4 · 5)
0 SERVO_2WING forme d'onde 2 Aile gauche · Aile droite · —
1 SERVO_2WING_1RUD forme d'onde 3 Aile gauche · Aile droite · Gouverne
2 SERVO_4WING forme d'onde 4 (arrière-droite partage le miroir arrière-gauche) Aile gauche · Aile droite · Aile arrière gauche
3 GEARBOX_2VTAIL_1RUD boîte 3 Gouverne · V-gauche · V-droite
4 GEARBOX_1MOT_2VTAIL boîte 3 Moteur · V-gauche · V-droite
5 GEARBOX_1MOT_2VTAIL_1RUD boîte 4 (V-droite partage le miroir gauche) Gouverne · Moteur · V-gauche
6 GEARBOX_1ELE_1RUD boîte 2 Gouverne · Profondeur · —
7 GEARBOX_1MOT_1ELE_1RUD boîte 3 Gouverne · Moteur · Profondeur

Sélection : drapeau de build MIXER_PROFILE (ancien ORNITHOPTER_GEARBOX=1 → profil 5), puis remplaçable à l'exécution via la WebUI (setOrnithopterProfile). Le test de noyau est simplement activeProfile ≥ GEARBOX_2VTAIL_1RUD.

Mixage des axes d'aile (kernel onde)

Toutes les valeurs de canaux entrent normalisées dans les mixeurs : _crsfToNorm mappe linéairement la fenêtre brute 172…1811 vers −1…+1. Les commandes de pilotage sont ensuite mises à l'échelle par les curseurs d'autorité par profil (aileronScale, elevatorScale, 0–100 %) fois ±60° (ORNI_STEER_MAX_DEG).

Géométrie en miroir. Les servos d'aile sont montés en miroir, ce qui inverse le sens des termes de mode commun et différentiel. Le code traite donc l'aileron (roulis) comme commun — il s'ajoute aux deux ailes, devenant une déflexion physique différentielle — et la profondeur (tangage) comme différentielle dans le code, devenant une déflexion physique commune. Les équations d'angle, avec ORNI_NEUTRAL_ANGLE_DEG = 100° et le multiplicateur 2× appliqué seulement aux termes d'écart :

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 sont les déflexions de course instantanées de l'aile gauche et droite, chacune le produit de sa propre amplitude et d'une onde façonnée par la férocité. Profondeur vers le haut renforce la course descendante ; vers le bas la montante (férocité asymétrique). Le lacet divise les ailes de deux façons complémentaires :

Les angles sont bornés 0…180° et convertis en impulsions avec l'enveloppe configurable servoMinUs…servoMaxUs (défauts 988…2012) : µs = min + angle·(max−min)/180, plus le trim par fonction. Les décalages de centre de plané/battement (glideAngleDeg, flappingAngleDeg, ±15°) entrent comme termes statiques sur leur branche respective — les centres de plané et de battement peuvent donc être réglés indépendamment par profil de vol.

Mixage de la dérive (les deux kernels)

Le mixeur de gouverne est partagé verbatim par les deux noyaux — une équation, deux cellules :

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]

Défauts : rudderYawWeight = 65%, rudderRollWeight = 35% (réglables à l'exécution dans la WebUI, stockés par sauvegarde). Le couplage de roulis sur la gouverne permet à un ptérosaure lourd d'aile de tenir des virages coordonnés sans acrobatie de fil de lacet ; réduisez le poids de roulis si la gouverne de tête semble trop agressive en roulis.

Mixage empennage et elevons (boîte à engrenages)

Le noyau boîte s'exécute sans état à chaque tick. Ses trois sous-mixeurs :

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

Sur le noyau boîte, Zephyrus injecte les deux corrections PID de roulis et tangage dans les servos d'empennage (roulis en opposition de phase, tangage en mode commun), chacune bornée dur à ±250 µs (ZEPHYR_GEARBOX_CLAMP_US). Un glitch de gyro peut donc faire osciller, mais jamais caler, un servo d'empennage.

Injection Zéphyros, trims et failsafe

Trois points d'injection différents existent selon le noyau et l'axe :

Axe Noyau forme d'onde Noyau boîte
Gouverne / lacet gyroRudderCorrection ajouté aux µs du gouvernail de crête gyroRudderCorrection ajouté aux µs du gouvernail de dérive
Roulis (aileron) — (les ailes à forme d'onde ne portent pas de PID de roulis) gyroAileronCorrection, opposition de phase sur empennage V, borné ±250 µs
Tangage (profondeur) — (injecté comme modulation d'onde dans la couche Zephyrus) gyroElevatorCorrection, mode commun, borné ±250 µs

Trims & limites. Chaque fonction a un trim signé par servo (servoTrimUs[tag], défaut 0, ±300 µs) ajouté en dernier, et chaque valeur passe _clampServo — une borne de sécurité absolue 500…2500 µs qui prime sur tout. En failsafe ou liaison perdue, toutes les fonctions reviennent à 1500 µs et un moteur de boîte au minimum, si bien que le modèle plane toujours vers le neutre.

Prêt pour la couche pratique ? Le Réglage de la forme d'onde montre comment ces nombres se ressentent aux manches, et l' Architecture montre où chaque mixeur se situe dans le pipeline.