mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-02-01 21:48:28 -04:00
AP_Scripting: add forward flight motor shutdown applet
This commit is contained in:
parent
cdfda2bd9b
commit
955be569a3
176
libraries/AP_Scripting/applets/forward_flight_motor_shutdown.lua
Normal file
176
libraries/AP_Scripting/applets/forward_flight_motor_shutdown.lua
Normal file
@ -0,0 +1,176 @@
|
||||
-- This is a script that stops motors in forward flight, for use on tiltrotors and tailsitters
|
||||
-- Thanks to PteroDynamics for supporting the development of this script
|
||||
-- Set the motor numbers to stop and configure a RCx_OPTION to 300 to enable and disable
|
||||
-- Throttle thresholds also allow automatic enable and disable of stop motors
|
||||
-- slew up and down times allow to configure how fast the motors are disabled and re-enabled
|
||||
|
||||
-- Config
|
||||
|
||||
-- Motors numbers to stop
|
||||
local stop_motors = {2,4}
|
||||
|
||||
-- motors should be shutdown if throttle goes lower than this value (%), set to > 100 to disable auto enable/disable
|
||||
local throttle_off_threshold = 50
|
||||
|
||||
-- motors should be re-enabled if throttle higher than this value (%)
|
||||
local throttle_on_threshold = 75
|
||||
|
||||
local slew_down_time = 5 -- seconds
|
||||
local slew_up_time = 1 -- seconds
|
||||
|
||||
-- end of config
|
||||
|
||||
local switch = assert(rc:find_channel_for_option(300),"Lua: Could not find switch")
|
||||
|
||||
-- read spin min param, we set motors to this PWM to stop them
|
||||
local pwm_min = assert(param:get("Q_M_PWM_MIN"),"Lua: Could not read Q_M_PWM_MIN")
|
||||
local pwm_max = assert(param:get("Q_M_PWM_MAX"),"Lua: Could not read Q_M_PWM_MAX")
|
||||
|
||||
-- calculate the slew up and down steps to achieve the given slew time
|
||||
local pwm_range = pwm_max - pwm_min
|
||||
local slew_down = (-pwm_range / slew_down_time) * (10/1000)
|
||||
local slew_up = (pwm_range / slew_up_time) * (10/1000)
|
||||
|
||||
if throttle_off_threshold < 100 then
|
||||
assert((throttle_off_threshold < throttle_on_threshold) and (throttle_on_threshold < 100), "throttle on and off thresholds not configured correctly")
|
||||
end
|
||||
|
||||
-- clear vars we don't need anymore
|
||||
slew_down_time = nil
|
||||
slew_up_time = nil
|
||||
pwm_range = nil
|
||||
|
||||
|
||||
for i = 1, #stop_motors do
|
||||
-- Check for a valid motor number
|
||||
assert(stop_motors[i] >= 1 and stop_motors[i] <= 12, string.format("Lua: motor %i not valid",stop_motors[i]))
|
||||
end
|
||||
|
||||
-- find any motors enabled, populate channels to stop and channels to run
|
||||
-- run channels provide a average motor PWM to slew down from
|
||||
local stop_motor_chan = {}
|
||||
local run_motor_fun = {}
|
||||
for i = 1, 12 do
|
||||
|
||||
local output_function
|
||||
if i <= 8 then
|
||||
output_function = i+32
|
||||
else
|
||||
output_function = i+81-8
|
||||
end
|
||||
|
||||
local temp_chan = SRV_Channels:find_channel(output_function)
|
||||
|
||||
local should_stop = false
|
||||
for j = 1, #stop_motors do
|
||||
if i == stop_motors[j] then
|
||||
should_stop = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if should_stop then
|
||||
assert(temp_chan, string.format("Lua: Could not find motor %i",i))
|
||||
table.insert(stop_motor_chan, temp_chan)
|
||||
elseif temp_chan then
|
||||
table.insert(run_motor_fun, output_function)
|
||||
end
|
||||
end
|
||||
assert(#stop_motor_chan == #stop_motors, "Lua: could not find all motors to stop")
|
||||
assert(#run_motor_fun > 0, "Lua: cannot stop all motors")
|
||||
|
||||
-- keep track of last time in a VTOL mode, this allows to delay switching after a transition/assist
|
||||
local last_vtol_active = 0
|
||||
|
||||
-- current action
|
||||
local script_enabled = false
|
||||
local motors_disabled = false
|
||||
local slew
|
||||
local slew_pwm
|
||||
function update()
|
||||
|
||||
local switch_pos = switch:get_aux_switch_pos()
|
||||
if switch:get_aux_switch_pos() == 2 then
|
||||
if not script_enabled then
|
||||
gcs:send_text(0, "Lua: Forward flight motor shutdown enabled")
|
||||
end
|
||||
script_enabled = true
|
||||
else
|
||||
if script_enabled then
|
||||
gcs:send_text(0, "Lua: Forward flight motor shutdown disabled")
|
||||
end
|
||||
script_enabled = false
|
||||
end
|
||||
|
||||
if quadplane:in_vtol_mode() or quadplane:in_assisted_flight() or not arming:is_armed() then
|
||||
-- in a VTOL mode, nothing to do
|
||||
last_vtol_active = millis()
|
||||
motors_disabled = false
|
||||
return update, 1000 -- reschedule at 1hz
|
||||
end
|
||||
|
||||
-- script not enabled
|
||||
if not script_enabled then
|
||||
motors_disabled = false
|
||||
return update, 1000 -- reschedule at 1hz
|
||||
end
|
||||
|
||||
-- in forward flight and enabled with switch, if armed then check that we are at least 10s past transition
|
||||
if (millis() - last_vtol_active) < 10000 then
|
||||
-- armed and have not been in a VTOL mode for longer than 10s
|
||||
motors_disabled = false
|
||||
return update, 1000 -- reschedule at 10hz
|
||||
end
|
||||
|
||||
-- check throttle level to see if motors should be disabled or enabled
|
||||
local throttle = SRV_Channels:get_output_scaled(70)
|
||||
|
||||
if motors_disabled and (throttle > throttle_on_threshold) then
|
||||
gcs:send_text(0, "Lua: Throttle high motors enabled")
|
||||
slew = slew_up
|
||||
|
||||
elseif (not motors_disabled) and (throttle < throttle_off_threshold) then
|
||||
slew_pwm = pwm_max
|
||||
motors_disabled = true
|
||||
gcs:send_text(0, "Lua: Throttle low motors disabled")
|
||||
slew = slew_down
|
||||
end
|
||||
|
||||
if not motors_disabled then
|
||||
return update, 10
|
||||
end
|
||||
|
||||
local average_pwm = 0
|
||||
for i = 1, #run_motor_fun do
|
||||
average_pwm = average_pwm + SRV_Channels:get_output_pwm(run_motor_fun[i])
|
||||
end
|
||||
average_pwm = average_pwm / #run_motor_fun
|
||||
|
||||
slew_pwm = slew_pwm + slew
|
||||
if (slew > 0) and (slew_pwm > average_pwm) then
|
||||
-- slewed back up past the output of other motors, stop overriding
|
||||
motors_disabled = false
|
||||
slew_pwm = pwm_max
|
||||
return update, 1000
|
||||
end
|
||||
|
||||
-- never slew lower than min
|
||||
slew_pwm = math.max(slew_pwm, pwm_min)
|
||||
|
||||
-- never output higher than other motors
|
||||
local output_pwm = math.min(slew_pwm, average_pwm)
|
||||
|
||||
-- make sure a integer
|
||||
output_pwm = math.floor(output_pwm + 0.5)
|
||||
|
||||
for i = 1, #stop_motor_chan do
|
||||
-- override for 15ms, should be called every 10ms when active
|
||||
-- using timeout means if the script dies the timeout will expire and all motors will come back
|
||||
-- we cant leave the vehicle in a un-flyable state
|
||||
SRV_Channels:set_output_pwm_chan_timeout(stop_motor_chan[i],output_pwm,15)
|
||||
end
|
||||
|
||||
return update, 10 -- reschedule at 100hz
|
||||
end
|
||||
|
||||
return update() -- run immediately before starting to reschedule
|
Loading…
Reference in New Issue
Block a user