Skip to content

Let the motor test drive DSHOT motors below the configured idle - #11908

Open
Raffi1202 wants to merge 1 commit into
iNavFlight:maintenance-10.xfrom
Raffi1202:fix/motor-test-below-idle
Open

Raffi1202 wants to merge 1 commit into
iNavFlight:maintenance-10.xfrom
Raffi1202:fix/motor-test-below-idle

Conversation

@Raffi1202

@Raffi1202 Raffi1202 commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Problem

In the Outputs tab motor test, a DSHOT motor does not spin when its slider is set below "Motors IDLE power" but above the point where the motor would normally start (reporter's example: idle 15 %, slider 10 %). With MULTISHOT the same slider position spins the motor; only DSHOT is affected. Reported in #9634 on a SpeedyBee F405 V3 running INAV 7.0.0.

Cause

src/main/flight/mixer.c:551 (maintenance-10.x): for non-reversible DSHOT, writeMotors() passes throttleIdleValue as the stop threshold to handleOutputScaling(), which sends DSHOT_DISARM_COMMAND for any input below that threshold (mixer.c:426). While disarmed, motor[i] is motor_disarmed[i] (mixer.c:652), written directly by MSP_SET_MOTOR (src/main/fc/fc_msp.c:2522). The analog non-reversible branch forwards motor[i] unchanged (mixer.c:589), so only DSHOT turns a below-idle test value into a stop command.

Change

One line in writeMotors(): the DSHOT stop threshold is throttleIdleValue only while armed; while disarmed it is motorZeroCommand + 1, so a disarmed value above mincommand is scaled to a DSHOT throttle. handleOutputScaling() still clamps the result to DSHOT_MIN_THROTTLE..DSHOT_MAX_THROTTLE, so the DSHOT command range 1-47 cannot be produced, and motorZeroCommand still yields the stop command. Armed behaviour (failsafe, turtle mode, motor stop) is unchanged.

Test

Not run on hardware or SITL (writeMotors() is compiled out for SITL). Cause verified by reading mixer.c:426/551/589/652 and fc_msp.c:2522 on maintenance-10.x. Not built: there is no fork CI run for fix/motor-test-below-idle, and the upstream firmware build for 3ee1df0 (https://github.com/iNavFlight/inav/actions/runs/34513097267) is waiting for maintainer approval with 0 jobs. Qodo review of 3ee1df0 reported no issues.

Flash / RAM

Not measured yet. The upstream firmware CI has not been released for this PR, so no size report exists.

Docs

No documentation change needed: docs/Controls.md and docs/Settings.md describe throttle_idle as the minimum throttle while armed, which is unchanged; no firmware doc describes the disarmed motor-test output.

The DSHOT output turned every value below the configured motor idle into
the DSHOT stop command, while the analog protocols hand such a value to
the ESC unchanged. In the motor test a slider below "Motors IDLE power"
therefore did nothing with DSHOT but turned the motor with MULTISHOT.

The idle value describes the lowest throttle in flight, it does not mean
"motor off". The value the mixer writes when a motor shall not turn is
motorZeroCommand, which is also what motor stop, the disarmed state and
areMotorsRunning() use. Use that as the stop threshold, so DSHOT scales
every request above min_command just like the analog protocols do. The
scaled output is still clamped to DSHOT_MIN_THROTTLE, so it can never
reach the DSHOT command range below 48.

Fixes iNavFlight#9634
@Raffi1202
Raffi1202 marked this pull request as ready for review September 11, 2026 15:50
@qodo-code-review

Copy link
Copy Markdown
Contributor

ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Allow DSHOT motor tests below configured idle

🐞 Bug fix 🕐 10-20 Minutes

Grey Divider

AI Description

• Allows disarmed DSHOT motor tests to spin below configured idle.
• Uses the mixer stop value while preserving armed output behavior.
• Keeps explicit stops and DSHOT command-range protection unchanged.
Diagram

graph TD
  A["Motor Test"] --> B["Disarmed Values"] --> C["writeMotors"] --> D{"Armed?"}
  D -->|Yes| E["Idle Threshold"] --> G["DSHOT Output"]
  D -->|No| F["Stop Threshold"] --> G
Loading
High-Level Assessment

The arming-state-dependent threshold is the narrowest appropriate fix. It corrects disarmed bench testing without changing failsafe, turtle mode, or transition behavior while armed; using the mixer stop threshold unconditionally would broaden risk unnecessarily. Targeted output-scaling tests would still be valuable when suitable test infrastructure becomes available.

Files changed (1) +5 / -1

Bug fix (1) +5 / -1
mixer.cUse mixer stop threshold for disarmed DSHOT output +5/-1

Use mixer stop threshold for disarmed DSHOT output

• Changes non-reversible DSHOT scaling to use the configured idle threshold only while armed. While disarmed, only motorZeroCommand is treated as stopped, allowing motor-test values above mincommand but below idle to produce valid DSHOT throttle output.

src/main/flight/mixer.c

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can switch off images and animations for a plain-text comment

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

In Motor Test, the motor don't spin if the command is lower than configured 'Motors IDLE power'

2 participants