ArduPilot / ardupilot

ArduPlane, ArduCopter, ArduRover, ArduSub source
http://ardupilot.org/
GNU General Public License v3.0
10.81k stars 17.27k forks source link

Improve handling of SBUS Failsafe #9400

Closed R-Lefebvre closed 5 years ago

R-Lefebvre commented 6 years ago

FrSky SBUS Failsafe handling is buggy, and Ardupilot needs to protect for the issue.

We have seen undesired mid-flight motor shut downs because of the issue. Basically, FrSky "no pulses" failsafe actually makes the Rx transmit SBUS "Zero" which our SBUS library converts into the number 874.

There are no protections for this value, even though it is usually below the RC Min in most cases.

I have used this fix for over a year now on many helicopters and it works well:

https://github.com/R-Lefebvre/ardupilot/commit/edb6ef1c9aa3bf28526c186afc950d900a47a272

However, it must also be considered that the FrSky receivers do not always exit a failsafe event "cleanly" because it can take several frames for all the channel to return values in range, as shown here:

https://drive.google.com/file/d/0BzWH4Q7IAU5YeVN0SG1xVEdlVWs/view

If there was a previous discussion in the forum, link to it

Bug report

Issue details

Please describe the problem

Version What version was the issue encountered with

Platform [ ] All [ ] AntennaTracker [ ] Copter [ ] Plane [ ] Rover [ ] Submarine

Airframe type What type of airframe (flying wing, glider, hex, Y6, octa etc)

Hardware type What autopilot hardware was used? (Pixhawk, Cube, Pixracer, Navio2, etc)

Logs Please provide a link to any relevant logs that show the issue

tridge commented 6 years ago

874 is SBUS 0:

>>> SBUS_TARGET_MAX=1000
>>> SBUS_TARGET_MIN=1000
>>> SBUS_TARGET_MAX=2000.0
>>> SBUS_TARGET_MIN=1000.0
>>> SBUS_RANGE_MIN=200.0
>>> SBUS_RANGE_MAX=1800.0
>>> SBUS_SCALE_FACTOR=((SBUS_TARGET_MAX - SBUS_TARGET_MIN) / (SBUS_RANGE_MAX - SBUS_RANGE_MIN))
>>> SBUS_SCALE_OFFSET=int(SBUS_TARGET_MIN - (SBUS_SCALE_FACTOR * SBUS_RANGE_MIN + 0.5))
>>> int((200 * SBUS_SCALE_FACTOR +.5) + SBUS_SCALE_OFFSET)
999
>>> int((0 * SBUS_SCALE_FACTOR +.5) + SBUS_SCALE_OFFSET)
874
>>> int((1000 * SBUS_SCALE_FACTOR +.5) + SBUS_SCALE_OFFSET)
1499
>>> int((1800 * SBUS_SCALE_FACTOR +.5) + SBUS_SCALE_OFFSET)
1999
>>> 
tridge commented 6 years ago

unfortunately it is possible to send SBUS 0 (ie. 874) as a valid output on one channel while other channels are normal, tested on a FrSky X4R

160: RC_CHANNELS {time_boot_ms : 710321, chancount : 16, chan1_raw : 1424, chan2_raw : 1477, chan3_raw : 1000, chan4_raw : 874, chan5_raw : 1806, chan6_raw : 2006, chan7_raw : 1494, chan8_raw : 1494, chan9_raw : 874, chan10_raw : 874, chan11_raw : 874, chan12_raw : 874, chan13_raw : 874, chan14_raw : 874, chan15_raw : 874, chan16_raw : 874, chan17_raw : 0, chan18_raw : 0, rssi : 0}

notice chan4 is 874, other channels are non-zero. I had setup rudder channel as low range, with full left stick

olliw42 commented 6 years ago

sbus has a dedicated failsafe flag, maybe its useful ;) naively I also would guess that if there is one failsafe 0 that all channels are 0 (if the failsafe flag doesn't cover that already)

SergeyBokhantsev commented 6 years ago

I had the same issue with X8R https://github.com/ArduPilot/ardupilot/issues/7516

Nurffe commented 6 years ago

Probably somewhat same issue but other way around can be seen here where failsafe is triggered. Failsafe is set to "no pulses" but still zero is sent for certain channels (5, 9, 10, 11, 12, 14). There is no preset failsafe set in receiver itself so it's unknown why these random channels are set to zero which is then converted to 874 in FC

Here are snapshots from logs

Showing lines and timestamps for radio fs trigger 2018-09-27_12-41-39

Showing lines and timestamps for incorrect channel values 2018-09-27_12-41-10

Error state only lasts ~400ms and happens shortly after failsafe is triggered. Seeing this happen after failsafe has been recognized by FC makes me believe there might actually be something in arducopter code itself and not just receiver doing weird things. Ardu shouldn't take nonsense inputs when failsafe flag is already on

Naterater commented 5 years ago

This is probably what caused the same issue explained here: https://github.com/ArduPilot/ardupilot/issues/9389

MidwestAire commented 5 years ago

I messed with this one day and the only way I could get some channels to not rebind clean was to have the transmitter config'd for no pulses, but not the receiver. I tested with a RX8R and a X8R. Configure the receiver for no pulses by powering on the receiver with the transmitter off, then press the FS button on the Rx so the light flashes. I have not been able to get one to rebind with some channels out of range if the receiver has been config'd for no pulses. According to the documentation for the receivers, that is the proper way to configure the receiver for no pulses.

rmackay9 commented 5 years ago

This is fixed in master and Copter-3.6.5 which is going out for beta testing today. Thanks for the report!

Nurffe commented 5 years ago

This is fixed in master and Copter-3.6.5 which is going out for beta testing today. Thanks for the report!

What was fixed exactly? Could you link to commit?

rmackay9 commented 5 years ago

@Nurffe, this is the fix that went into Copter-3.6.. It's a similar but slightly different fix for master because the auxiliary switch code has been moved into the RC_Channel object in master.