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:
- Diferencial de ferocidad (
rudderFerocityRange): la izquierda recibe+ferocidad, la derecha−ferocidad— las dos alas dwellan distinto pero mantienen una fase de reversión compartida (limiarShared), así los giros son par de alabeo puro, nunca desincronización. - Diferencial de amplitud (
rudderAmplitudeDifferential): amplitud izquierda ×(1+Δ), derecha ×(1−Δ) — divergencia simétrica en torno a la batida fijada por el acelerador.
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:
- Motor —
SF_MOTOR: al armar, acelerador 0…1 mapea a 1000…2000 µs; desarmado o enlace caído fuerza el mínimo (motor parado). - Timón — ecuación idéntica a la sección anterior.
- Colas — dos familias. Los perfiles clásicos (6/7) accionan un elevador separado:
µs = 1500 + elevatorNorm·500 + pitchPID + trim. Los perfiles en V (3/4/5) mezclan en elevón ambos canales en los dos servos de cola:
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.