Quad: roll & pitch fine, but persistent uncontrolled yaw spin (yaw appears inverted)

Setup

Frame:custom 3D-printed ducted Quad X, ~1.5 kg AUW, motor-to-motor diagonal 330 mm.

FC:Pixhawk 6C, ArduCopter 4.6.3, FRAME_CLASS=1 (Quad), FRAME_TYPE=1 (X).

Motors:T-Motor Velox 2207 2550 KV .

Props: HQProp 5.1×4.1×3 (5").

ESC:HAKRC BLHeli_S 40A 4-in-1. Motors are on main outputs 1–4 (via the IOMCU) — DShot and BLHeli pass-through do not work on these outputs on this board, so ESC-side direction reversal isn’t availabl e.

Battery: 4S.

Control:no RC radio and no GPS — flown from a Raspberry Pi over MAVLink using RC_CHANNELS_OVERRIDE in STABILIZE (indoor autonomous project).Tests are captive / very low over foam.

What already works

Motor position mapping verified correctwith a hand-tilt reaction test (armed, props off): pitching/rolling the frame makes the FC increase exactly the correct low-side motors on all four ax es.

Mapping:SERVO1_FUNCTION=35 (Motor3), SERVO2=33 (Motor1), SERVO3=34 (Motor2), SERVO4=36 (Motor4)— physical outputs OUT1=front-left, OUT2=front-right, OUT3=rear-left, OUT4=rear-ri ght.

Full 6-position accel cal (level 0/0 at rest), vibrations low (VibeXYZ < 20, no clipp ing).

Set for 5" props:MOT_THST_EXPO=0.20,INS_GYRO_FILTER =80.

It no longer flips on takeoff (that was an earlier motor-mapping error, now fixed).

The problem

On every takeoff the vehicle enters an uncontrolled yaw spin (~250–480 °/s); roll and pitch remain cont rollable.

Log analysis (why I think yaw is inverted)

InRATEdurin g the spin:

Actual yaw rateYis negative and growing (e.g. −28 → −96 → −193 → −215 °/s).

Desired yaw rateYDesis positive (the controller is trying to count er the spin).

Controller outputYOutis positive (correcting direction) and not saturat ed (~0.4–0.7).

So the yaw controller outputs a correction in the right direction, yet the yaw rate accelerates the wrong way — the yaw response to the FC’s command is inverted (positive feedback). Roll/pitch are unaffected. This points to the motor rotation convention being mirrored relative to what ArduCopter’s Quad X expects (all four motors turning the other way — a valid 2+2 quad but oppos ite chirality) .

My question

Given that position/thrust mapping is correct (roll/pitch good), the props currently produce lift with the present rotation (so simply reversing motors would make them push down), and the motors are on IOMCU outputs with no DShot/BLHeli pass-through — what is the cleanest fix?

1. Reverse all four motors’ rotation (swap 2 of 3 wires each) and fit opposite-handed props on all four — i.e. rebuild to the correct ro tation convention?

2. Is there a parameter / frame-type approach to tell ArduCopter the rotation is mirrored (a “props-out” convention) so I don’t have to rework all f our motors + props?

3. Anything specific to the Pixhawk 6C IOMCU outputs I should know (e.g. moving motors to FMU/AUX outputs to enable DShot + software reversal)?

Dataflash log attached (log_115). Thanks!

log_115_UnknownDate.bin (1004.2 KB)

Dshot does if configured correctly. You don’t have BRD_IO_DSHOT enabled to try it to start with. But, move them to the FMU/Aux outputs anyway..

Did you use Mission Planners Motor Test function to confirm proper motor order and direction for the Frame Type/Class? What you posted above is not definitive in this regard.

Thanks, very helpful. No — I hadn’t used Mission Planner’s Motor Test; I was checking the mixing with a custom MAVLink script (RC override + reading SERVO_OUTPUT_RAW while hand-tilting), which as you say isn’t definitive for order/direction. I’ll run MP Motor Test to confirm motor order and direction against the Quad X diagram.

I’ll also enable BRD_IO_DSHOT (and try moving the motors to the FMU/AUX outputs as you suggest) so I can reverse any wrong-direction motor in software instead of rewiring.

Quick question: on the Pixhawk 6C, which outputs are the FMU/AUX ones vs the IO main outputs, and with DShot what’s the cleanest way to reverse an individual motor’s direction (BLHeli pass-through, or SERVO_BLH_RVMASK)? Thanks!

Even better than MP motor test is ArduPilot methodic configurator motor test.
It allows correcting the order of the motors faster and simpler.

Ran MP Motor Test (props off), frame is Quad X. MP tests in geographic CW order (A=front-right/Motor1, B=rear-right/Motor4, C=rear-left/Motor2, D=front-left/Motor3). Observed vs expected:

  • Test A (expects front-right, Motor1 CCW) → rear-right motor spun, CCW
  • Test B (expects rear-right, Motor4 CW) → rear-left, CW
  • Test C (expects rear-left, Motor2 CCW) → front-left, CCW
  • Test D (expects front-left, Motor3 CW) → front-right, CW

So directions match per motor number, but every motor is offset one position clockwise (~90° rotation), and per physical position the rotation is opposite to the standard X convention (props-out). Props currently produce lift with the present rotations, motors are on IO outputs with BRD_IO_DSHOT=1 / MOT_PWM_TYPE=6 now enabled. What’s the correct fix — a FRAME_TYPE change, a SERVO_FUNCTION remap, and/or DShot motor reversal? Is the FC possibly mounted 90° off (AHRS_ORIENTATION)?

Don’t bother if you move them to the FMU outputs. Do so and then configure the Servo 9-12 outputs.
If configured properly for Dshot the RVMASK will work or just do it in the configurator.

Servo function remap is all you need to do.

Thanks! I’ll use the Methodic Configurator’s motor test to find the correct frame type variant and fix the order/direction. Will report back.

An even better idea if you are new to Ardupilot.

Thanks both! I’ll move the motors to the FMU outputs, configure SERVO9-12 for DShot, and use the Methodic Configurator’s motor test to fix the order (remap) and direction. Will report back.

Update + huge thanks :folded_hands:

Coming back to close the loop. Following your advice I ran the motor test in the ArduPilot Methodic Configurator (thanks @amilcarlucas) and did the servo-function remap instead of rewiring (thanks @dkemxr) — that made it painless.

The key insight from the thread was that my frame is built “props-out” (all four motor rotations mirrored vs a standard Quad X). Setting FRAME_TYPE = 18 (X / BF-reversed) matched the build exactly and the uncontrolled yaw spin disappeared immediately. I also enabled DShot on the IOMCU outputs (BRD_IO_DSHOT), which let me sort out motor order/direction in software.

Result: the quad now hovers cleanly. I’ve already moved on to indoor autonomy — it’s holding altitude in ALT_HOLD using a downward VL53L1X ToF as a MAVLink rangefinder, with five more ToFs feeding proximity, all bridged from a Raspberry Pi.

Thanks again to everyone who chimed in — this community is fantastic. :helicopter: