Referencia de mezcladores

De palancas y giroscopio a µs en el hilo: la geometría completa de cada mezclador que PteronautOS puede seleccionar — ejes de ala, mezclas de timón, elevones, trims y límites.

Esta página documenta la capa de mezclador de src/lib/Ornithopter/Ornithopter.cpp y el sistema de perfiles de OrnithopterConfig.h. Para la arquitectura circundante, empiece por el artículo Arquitectura ; para temporización de pulso y rangos de trim, véase el Servo Kernel artículo.

Etiquetas de función de servo

Cada salida de cada mezclador es un valor µs escrito en _f[], indexado por una etiqueta ServoFunc. Las etiquetas son transporte — dicen qué significa una señal, nunca dónde está cableada:

Etiqueta Nombre Significado
0 SF_NONE Reservado — sin función (los primeros slots PWM quedan libres para BOOT e I2C)
1 / 2 SF_LEFT_WING / SF_RIGHT_WING Alas batientes delanteras (kernel de forma de onda)
3 SF_RUDDER Timón de cabeza/cresta (forma de onda) o timón de aleta (caja) — mezcla de guiñada + alabeo
4 SF_MOTOR Acelerador ESC brushless (solo kernel de caja)
5 / 6 SF_VTAIL_LEFT / SF_VTAIL_RIGHT Superficies de cola en V, mezcla de elevón (kernel de caja)
7 SF_ELEVATOR Elevador separado tradicional (perfiles de caja 6/7)
8 / 9 SF_BACK_LEFT_WING / SF_BACK_RIGHT_WING Par de alas traseras de una aeronave de 4 alas (espejo del par delantero, trim propio)

Un perfil en ejecución proporciona el funcMap: un array que mapea índice de salida PWM → ServoFunc. Los tres primeros slots (PWM 1…3) son siempre SF_NONE — pertenecen a la correa BOOT y al bus I2C — así que las funciones reales de servo comienzan en el índice PWM 3 (el comentario del firmware lo detalla: índice 3 = CH4, 4 = CH5, 5 = CH6).

Los ocho perfiles de mezclador

Existen ocho perfiles de mezclador. Los perfiles 0–2 accionan el kernel de forma de onda (alas batientes), los perfiles 3–7 el kernel de caja de engranajes (motor + colas):

# Perfil Kernel Servos funcMap (PWM 3 · 4 · 5)
0 SERVO_2WING forma de onda 2 Ala izquierda · Ala derecha · —
1 SERVO_2WING_1RUD forma de onda 3 Ala izquierda · Ala derecha · Timón
2 SERVO_4WING forma de onda 4 (trasera-derecha comparte el espejo de la trasera-izquierda) Ala izquierda · Ala derecha · Ala trasera izquierda
3 GEARBOX_2VTAIL_1RUD caja 3 Timón · Cola V izquierda · Cola V derecha
4 GEARBOX_1MOT_2VTAIL caja 3 Motor · Cola V izquierda · Cola V derecha
5 GEARBOX_1MOT_2VTAIL_1RUD caja 4 (cola V derecha comparte el espejo izquierdo) Timón · Motor · Cola V izquierda
6 GEARBOX_1ELE_1RUD caja 2 Timón · Elevador · —
7 GEARBOX_1MOT_1ELE_1RUD caja 3 Timón · Motor · Elevador

Selección: bandera de compilación MIXER_PROFILE (legado ORNITHOPTER_GEARBOX=1 → perfil 5), luego anulable en ejecución vía WebUI (setOrnithopterProfile). La prueba de kernel es simplemente activeProfile ≥ GEARBOX_2VTAIL_1RUD.

Mezcla de ejes del ala (kernel de onda)

Todos los valores de canal entran normalizados a los mezcladores: _crsfToNorm mapea la ventana cruda 172…1811 linealmente a −1…+1. Los comandos de dirección se escalan luego por los deslizadores de autoridad por perfil (aileronScale, elevatorScale, 0–100%) por ±60° (ORNI_STEER_MAX_DEG).

Geometría en espejo. Los servos de ala van montados en espejo, lo que intercambia el significado de los términos de modo común y diferencial. El código trata por tanto el alerón (alabeo) como común — se suma a ambas alas, volviéndose una deflexión física diferencial — y el elevador (cabeceo) como diferencial en código, volviéndose una deflexión física común. Las ecuaciones de ángulo, con ORNI_NEUTRAL_ANGLE_DEG = 100° y el multiplicador 2× aplicado sólo a los términos de desviación:

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 son las deflexiones instantáneas de batida del ala izquierda y derecha, cada una producto de su propia amplitud y una onda moldeada por ferocidad. Elevador arriba refuerza la batida descendente; abajo la ascendente (ferocidad asimétrica). La guiñada divide las alas de dos formas complementarias:

Los ángulos se limitan a 0…180° y se convierten a pulsos con la envolvente configurable servoMinUs…servoMaxUs (por defecto 988…2012): µs = mín + ángulo·(máx−mín)/180, más el trim por función. Los offsets de centro de planeo/aleteo (glideAngleDeg, flappingAngleDeg, ±15°) entran como términos estáticos en su rama respectiva — así los centros de planeo y aleteo pueden ajustarse independientemente por perfil.

Mezcla del timón (ambos kernels)

El mezclador de timón es compartido verbatim por ambos kernels — una ecuación, dos aeronaves:

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]

Por defecto: rudderYawWeight = 65%, rudderRollWeight = 35% (ajustables en ejecución en la WebUI, almacenados por backup). El acoplamiento de alabeo en el timón es lo que deja a un pterosaurio pesado de ala mantener giros coordinados sin gimnasia de hilo de guiñada; reduzca el peso de alabeo si el timón de cabeza se siente demasiado agresivo en alabeo.

Mezcla de cola y elevones (caja reductora)

El kernel de caja se ejecuta sin estado en cada tick. Sus tres sub-mezcladores:

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

En el kernel de caja, Zephyrus inyecta ambas correcciones PID de alabeo y cabeceo en los servos de cola (alabeo en antifase, cabeceo en modo común), cada una limitada a ±250 µs (ZEPHYR_GEARBOX_CLAMP_US). Un fallo de giroscopio puede por tanto menear, pero jamás calar, un servo de cola.

Inyección Céfiros, trims y failsafe

Existen tres puntos de inyección distintos según el kernel y el eje:

Eje Kernel de forma de onda Kernel de caja
Timón / guiñada gyroRudderCorrection añadido a los µs del timón de cresta gyroRudderCorrection añadido a los µs del timón de aleta
Alabeo (alerón) — (las alas de forma de onda no llevan PID de alabeo) gyroAileronCorrection, antifase en cola V, limitado a ±250 µs
Cabeceo (elevador) — (inyectado como modulación de onda en la capa Zephyrus) gyroElevatorCorrection, modo común, limitado a ±250 µs

Trims y límites. Cada función tiene un trim por servo con signo (servoTrimUs[tag], por defecto 0, ±300 µs) añadido al final, y cada valor pasa por _clampServo — un límite de seguridad absoluto de 500…2500 µs que supera a todo. En failsafe o enlace caído, todas las funciones vuelven a 1500 µs y un motor de caja al mínimo, de modo que el modelo siempre planea a neutral.

¿Listo para la capa práctica? El Ajuste de Forma de Onda tutorial muestra cómo se sienten estos números desde los sticks, y el Arquitectura artículo muestra dónde se sitúa cada mezclador en la tubería.