From 3ee1df011decd6e040efa596b650aae132531317 Mon Sep 17 00:00:00 2001 From: Raphael Hunziker Date: Thu, 10 Sep 2026 20:05:17 +0200 Subject: [PATCH] mixer: stop DSHOT motors on the mixer stop value, not below idle 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 #9634 --- src/main/flight/mixer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/flight/mixer.c b/src/main/flight/mixer.c index 9743be74dd3..134ebcab5cc 100644 --- a/src/main/flight/mixer.c +++ b/src/main/flight/mixer.c @@ -546,9 +546,13 @@ void FAST_CODE writeMotors(void) } } else { + // While disarmed only the mixer stop value means motor off, so the + // motor test can drive a motor below the configured idle. Armed + // behaviour is unchanged: there the configured idle stays the + // threshold, so failsafe and turtle mode are not affected. motorValue = handleOutputScaling( motor[i], - throttleIdleValue, + ARMING_FLAG(ARMED) ? throttleIdleValue : (motorZeroCommand + 1), DSHOT_DISARM_COMMAND, motorConfig()->mincommand, getMaxThrottle(),