iNavFlight / inav

INAV: Navigation-enabled flight control software
https://inavflight.github.io
GNU General Public License v3.0
3.19k stars 1.48k forks source link

Incorrect throttle mid range with reversible motors #9175

Open pguillory opened 1 year ago

pguillory commented 1 year ago

Current Behavior

With reversible motors enabled, the throttle range to allow arming on my plane is 1550 to 1650.

Screenshot 2023-07-13 at 8 41 12 PM

Steps to Reproduce

  1. Apply the above settings for reversible motors.
  2. Open the Receiver tab.
  3. Slowly raise the throttle on the transmitter from minimum to maximum (988 to 2012 in my case).
  4. Observe the FM telemetry sensor (from ELRS) change from !ERR to OK at 1550 and back to !ERR at 1650.

Expected behavior

Based on the above settings, I would expect the throttle range for arming to be either 1500 +/- X (based on Reversible Motors Neutral), or maybe 1425 to 1575 (based on Reversible Motors Deadband Low/High). Seems like the range needs to include 1500, because that's the midpoint on my transmitter and the FC and the BLHeli_32 ESC.

Suggested solution(s)

If it's expected behavior and not a bug, maybe a documentation or UI change is in order to make it more clear exactly where the throttle arming range comes from with reversible motors enabled.

Additional context

I ran dump in the CLI and grepped for 1550 and 1600 and 1650, just trying to find the setting these thresholds are coming from, and that didn't lead anywhere.

https://pastebin.com/2NSmjmVm

pguillory commented 1 year ago

Looking at calculateThrottleStatus() in rc_controls.c, I see the mid-throttle range is calculated as PWM_RANGE_MIDDLE +/- mid_throttle_deadband, where PWM_RANGE_MIDDLE is 1500 (I'm pretty sure?), and mid_throttle_deadband is the 3d_deadband_throttle config setting.

I tried changing 3d_deadband_throttle to 75 and tested the mid throttle arming range again, and found that it's now 1525 to 1675. So the effective formula is definitely 1600 +/- 3d_deadband_throttle. But... why 1600? Why not 1500?

pguillory commented 1 year ago

Further progress. It looks like the throttle value from the receiver is run through a calculation involving the min_command, max_throttle, and throttle_idle settings before it is checked against the arming range. Since I recently changed throttle_idle to 0, I tried restoring it to the default of 15, and my apparent throttle arming range is now 1442 to 1618.

Also changed max_throttle from 1900 to 2000, now my throttle arming range is 1393 to 1549.

So at least I can arm now at 1500 throttle, which is nice. But now I realize that the throttle value from my transmitter is not the same as the throttle value going to the motor/ESC. For example if my transmitter says throttle 1600, the motor output on the Outputs tab says 1620. Or another example, transmitter throttle 1300 translates to motor throttle 1338.

I'm not sure how someone would have debugged this without reading the C++ source code. The issue is that with reversible motors, arming is based on an internal value rcCommand[THROTTLE]. It's potentially very different from the throttle value shown in the transmitter or the receiver tab, due to the calculation involving min_command/max_throttle/throttle_idle. It's also potentially very different from the motor output shown in the Outputs tab, due to 1) maybe differential thrust, 2) maybe power limiting, or 3) definitely until you arm the motor output is just 3d_neutral. So there's this internal value you can't see, that needs to fall into the arming range.

Well, the other issue is that the range is 1500 +/- 3d_deadband_throttle, which is not clear at all. It's not 3d_deadband_low/3d_deadband_high, and it's nothing involving 3d_neutral.

So, to recap:

  1. Arming is based on this internal throttle command, rather than the throttle input or motor output. It makes sense that the distinct value exists, to account for power scaling and power limiting. However, if reversible motors is enabled and 3d_neutral is 1500, and the transmitter sends 1500, then the formula needs to work out such that rcCommand[THROTTLE] is also 1500. That not being the case seems like a bug to me. Power scaling should not be happening inside the deadband, right?
  2. The value of the throttle command is not shown anywhere. This wouldn't be an issue, though, if the above is fixed.
  3. The formula for the throttle command is not really documented and super complex. Also wouldn't be an issue if the midpoint issue were fixed.
  4. The UI is very misleading about the range into which the throttle command needs to fall in order to enable arming. It's not what you would think based on looking at the UI. Can the midpoint arming range just be 3d_deadband_low/3d_deadband_high, and we deprecate 3d_deadband_throttle? Something like that.
MrD-RC commented 1 year ago

IMHO, throttle is messed up in INAV. Everything should be based on a 1000-2000 throttle range. It should only be scaled on output.

breadoven commented 1 year ago

The issue here is that reversible motors use THROTTLE_STATUS_TYPE_COMMANDas the throttle value to determine "Throttle Low" which uses the mixed throttle value rcCommand[THROTTLE] rather than the raw RC stick position value. I cleaned up this code a while back:

https://github.com/iNavFlight/inav/pull/8601/files#diff-f092d782c82e8f36c4b664aacef2e02cc56c56640a837cc2a6205bc2397b0eed

Reversible motors have always used THROTTLE_STATUS_TYPE_COMMAND... not sure why because based on what you have found it doesn't make immediate sense. At the moment THROTTLE_STATUS_TYPE_COMMANDis only used in calculateThrottleStatus() to check for "Throttle Low". Using THROTTLE_STATUS_TYPE_RC instead would appear to work better and be more logical, i.e. reversible motor throttle low is simply 1500 +- the dead band. But you'd maybe need to double check what's happening in mixer.cto fully understand the reversible motor stuff because it appears a bit complicated.

LsHallo commented 1 year ago

I'm facing the same issue. The problem is I need the low throttle control from 1520-1600 for precise control. Is there any way to get the full control range from DEADBAND_HIGH to THROTTLE_MAX? My motors currently suddenly engage when I go over 1615 (or in that range).

Settings: Throttle IDLE 0% Deadband High 1515 Deadband Low 1485 Motors Neutral 1500 max_throttle 2000

Does anybody know what rxConfig()->mincheck is under normal circumstances? In throttleStickMixedValue it could skew the rcCommand[THROTTLE] value in one direction if it is not 1000.

LsHallo commented 1 year ago

setting min_check to 1000 seems to fix the weirdness. 3d_throttle_deadband of 25 and I can arm from 1476 to 1524.

TheBiggestBoon commented 7 months ago

I have been having issues with this as well. My transmitter goes from 1000 to 2000 with 1500 being the midpoint. In iNav I have bidirectional enabled with 1500 being the midpoint and a deadband of 1475 to 1525. iNav wont arm at 1500 and only arms between 1536 and 1600. The motor spins backwards at 1500 and stops at 1535, then starts spinning forward at 1600. How do I get this centered around 1500 with the proper deadband? Id like to lower the deadband to +-5.

ama9910 commented 6 months ago

Ughh.. I discovered this bug today too. With deadband set to 1450-1500-1550 and all other settings default other than reversible motors and 0% idle throttle, I can't arm until about 1620. Setting min_check to 1000 seemed to make no difference.