2015-07-02 18:15:09 -03:00
/*
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
/*
2015-07-15 08:21:13 -03:00
* AP_MotorsMulticopter . cpp - ArduCopter multicopter motors library
2015-07-02 18:15:09 -03:00
* Code by Randy Mackay and Robert Lefebvre . DIYDrones . com
*
*/
2015-07-15 08:21:13 -03:00
# include "AP_MotorsMulticopter.h"
2015-08-11 03:28:44 -03:00
# include <AP_HAL/AP_HAL.h>
2016-05-01 19:00:45 -03:00
2015-07-02 18:15:09 -03:00
extern const AP_HAL : : HAL & hal ;
// parameters for the motor class
2015-10-25 14:03:46 -03:00
const AP_Param : : GroupInfo AP_MotorsMulticopter : : var_info [ ] = {
2015-07-02 18:15:09 -03:00
// 0 was used by TB_RATIO
// 1,2,3 were used by throttle curve
2016-06-09 00:42:38 -03:00
// 5 was SPIN_ARMED
2015-07-02 18:15:09 -03:00
// @Param: YAW_HEADROOM
// @DisplayName: Matrix Yaw Min
2017-05-15 20:21:53 -03:00
// @Description: Yaw control is given at least this pwm in microseconds range
2015-07-02 18:15:09 -03:00
// @Range: 0 500
2017-05-02 10:45:39 -03:00
// @Units: PWM
2015-07-02 18:15:09 -03:00
// @User: Advanced
2015-07-15 08:21:13 -03:00
AP_GROUPINFO ( " YAW_HEADROOM " , 6 , AP_MotorsMulticopter , _yaw_headroom , AP_MOTORS_YAW_HEADROOM_DEFAULT ) ,
2015-07-02 18:15:09 -03:00
// 7 was THR_LOW_CMP
// @Param: THST_EXPO
// @DisplayName: Thrust Curve Expo
// @Description: Motor thrust curve exponent (from 0 for linear to 1.0 for second order curve)
// @Range: 0.25 0.8
// @User: Advanced
2015-07-15 08:21:13 -03:00
AP_GROUPINFO ( " THST_EXPO " , 8 , AP_MotorsMulticopter , _thrust_curve_expo , AP_MOTORS_THST_EXPO_DEFAULT ) ,
2015-07-02 18:15:09 -03:00
2016-05-21 03:51:36 -03:00
// @Param: SPIN_MAX
// @DisplayName: Motor Spin maximum
// @Description: Point at which the thrust saturates expressed as a number from 0 to 1 in the entire output range
// @Values: 0.9:Low, 0.95:Default, 1.0:High
2015-07-02 18:15:09 -03:00
// @User: Advanced
2016-05-22 06:02:19 -03:00
AP_GROUPINFO ( " SPIN_MAX " , 9 , AP_MotorsMulticopter , _spin_max , AP_MOTORS_SPIN_MAX_DEFAULT ) ,
2015-07-02 18:15:09 -03:00
2016-05-21 03:51:36 -03:00
// @Param: BAT_VOLT_MAX
2015-07-02 18:15:09 -03:00
// @DisplayName: Battery voltage compensation maximum voltage
// @Description: Battery voltage compensation maximum voltage (voltage above this will have no additional scaling effect on thrust). Recommend 4.4 * cell count, 0 = Disabled
// @Range: 6 35
2017-05-02 10:45:39 -03:00
// @Units: V
2015-07-02 18:15:09 -03:00
// @User: Advanced
2016-05-21 03:51:36 -03:00
AP_GROUPINFO ( " BAT_VOLT_MAX " , 10 , AP_MotorsMulticopter , _batt_voltage_max , AP_MOTORS_BAT_VOLT_MAX_DEFAULT ) ,
2015-07-02 18:15:09 -03:00
2016-05-21 03:51:36 -03:00
// @Param: BAT_VOLT_MIN
2015-07-02 18:15:09 -03:00
// @DisplayName: Battery voltage compensation minimum voltage
// @Description: Battery voltage compensation minimum voltage (voltage below this will have no additional scaling effect on thrust). Recommend 3.5 * cell count, 0 = Disabled
// @Range: 6 35
2017-05-02 10:45:39 -03:00
// @Units: V
2015-07-02 18:15:09 -03:00
// @User: Advanced
2016-05-21 03:51:36 -03:00
AP_GROUPINFO ( " BAT_VOLT_MIN " , 11 , AP_MotorsMulticopter , _batt_voltage_min , AP_MOTORS_BAT_VOLT_MIN_DEFAULT ) ,
2015-07-02 18:15:09 -03:00
2016-05-21 03:51:36 -03:00
// @Param: BAT_CURR_MAX
2015-07-02 18:15:09 -03:00
// @DisplayName: Motor Current Max
// @Description: Maximum current over which maximum throttle is limited (0 = Disabled)
// @Range: 0 200
2017-05-02 10:45:39 -03:00
// @Units: A
2015-07-02 18:15:09 -03:00
// @User: Advanced
2016-05-21 03:51:36 -03:00
AP_GROUPINFO ( " BAT_CURR_MAX " , 12 , AP_MotorsMulticopter , _batt_current_max , AP_MOTORS_BAT_CURR_MAX_DEFAULT ) ,
2015-07-02 18:15:09 -03:00
2016-03-21 11:21:19 -03:00
// 13, 14 were used by THR_MIX_MIN, THR_MIX_MAX
2015-08-06 08:39:49 -03:00
2016-04-13 18:48:54 -03:00
// @Param: PWM_TYPE
// @DisplayName: Output PWM type
2016-11-29 06:10:41 -04:00
// @Description: This selects the output PWM type, allowing for normal PWM continuous output, OneShot or brushed motor output
2017-06-16 08:23:37 -03:00
// @Values: 0:Normal,1:OneShot,2:OneShot125,3:Brushed
2016-04-13 03:33:20 -03:00
// @User: Advanced
2016-11-29 19:49:17 -04:00
// @RebootRequired: True
2016-04-13 18:48:54 -03:00
AP_GROUPINFO ( " PWM_TYPE " , 15 , AP_MotorsMulticopter , _pwm_type , PWM_TYPE_NORMAL ) ,
2016-05-21 03:47:46 -03:00
// @Param: PWM_MIN
// @DisplayName: PWM output miniumum
2017-05-15 20:21:53 -03:00
// @Description: This sets the min PWM output value in microseconds that will ever be output to the motors, 0 = use input RC3_MIN
2017-05-02 10:45:39 -03:00
// @Units: PWM
2016-05-21 03:47:46 -03:00
// @Range: 0 2000
// @User: Advanced
AP_GROUPINFO ( " PWM_MIN " , 16 , AP_MotorsMulticopter , _pwm_min , 0 ) ,
// @Param: PWM_MAX
// @DisplayName: PWM output maximum
2017-05-15 20:21:53 -03:00
// @Description: This sets the max PWM value in microseconds that will ever be output to the motors, 0 = use input RC3_MAX
2017-05-02 10:45:39 -03:00
// @Units: PWM
2016-05-21 03:47:46 -03:00
// @Range: 0 2000
// @User: Advanced
AP_GROUPINFO ( " PWM_MAX " , 17 , AP_MotorsMulticopter , _pwm_max , 0 ) ,
2016-06-09 03:34:47 -03:00
// @Param: SPIN_MIN
// @DisplayName: Motor Spin minimum
2016-09-02 23:12:31 -03:00
// @Description: Point at which the thrust starts expressed as a number from 0 to 1 in the entire output range. Should be higher than MOT_SPIN_ARM.
2016-06-09 03:34:47 -03:00
// @Values: 0.0:Low, 0.15:Default, 0.3:High
// @User: Advanced
2016-05-22 06:02:19 -03:00
AP_GROUPINFO ( " SPIN_MIN " , 18 , AP_MotorsMulticopter , _spin_min , AP_MOTORS_SPIN_MIN_DEFAULT ) ,
2016-06-09 03:34:47 -03:00
2016-06-09 00:42:38 -03:00
// @Param: SPIN_ARM
// @DisplayName: Motor Spin armed
2016-09-02 23:12:31 -03:00
// @Description: Point at which the motors start to spin expressed as a number from 0 to 1 in the entire output range. Should be lower than MOT_SPIN_MIN.
2016-06-09 00:42:38 -03:00
// @Values: 0.0:Low, 0.1:Default, 0.2:High
// @User: Advanced
2016-05-22 06:02:19 -03:00
AP_GROUPINFO ( " SPIN_ARM " , 19 , AP_MotorsMulticopter , _spin_arm , AP_MOTORS_SPIN_ARM_DEFAULT ) ,
2016-06-09 00:42:38 -03:00
2016-06-08 08:54:32 -03:00
// @Param: BAT_CURR_TC
// @DisplayName: Motor Current Max Time Constant
// @Description: Time constant used to limit the maximum current
// @Range: 0 10
2017-05-02 10:45:39 -03:00
// @Units: s
2016-06-08 08:54:32 -03:00
// @User: Advanced
AP_GROUPINFO ( " BAT_CURR_TC " , 20 , AP_MotorsMulticopter , _batt_current_time_constant , AP_MOTORS_BAT_CURR_TC_DEFAULT ) ,
2016-03-22 10:57:26 -03:00
// @Param: THST_HOVER
// @DisplayName: Thrust Hover Value
// @Description: Motor thrust needed to hover expressed as a number from 0 to 1
2016-09-07 03:27:44 -03:00
// @Range: 0.2 0.8
2016-03-22 10:57:26 -03:00
// @User: Advanced
AP_GROUPINFO ( " THST_HOVER " , 21 , AP_MotorsMulticopter , _throttle_hover , AP_MOTORS_THST_HOVER_DEFAULT ) ,
2016-06-09 02:21:04 -03:00
// @Param: HOVER_LEARN
// @DisplayName: Hover Value Learning
// @Description: Enable/Disable automatic learning of hover throttle
2016-06-16 02:28:49 -03:00
// @Values: 0:Disabled, 1:Learn, 2:LearnAndSave
2016-06-09 02:21:04 -03:00
// @User: Advanced
2016-06-16 02:28:49 -03:00
AP_GROUPINFO ( " HOVER_LEARN " , 22 , AP_MotorsMulticopter , _throttle_hover_learn , HOVER_LEARN_AND_SAVE ) ,
2016-06-09 02:21:04 -03:00
2016-11-18 21:48:22 -04:00
// @Param: SAFE_DISARM
// @DisplayName: Motor PWM output disabled when disarmed
// @Description: Disables motor PWM output when disarmed
// @Values: 0:PWM enabled while disarmed, 1:PWM disabled while disarmed
// @User: Advanced
AP_GROUPINFO ( " SAFE_DISARM " , 23 , AP_MotorsMulticopter , _disarm_disable_pwm , 0 ) ,
2017-01-09 03:31:56 -04:00
// @Param: YAW_SV_ANGLE
// @DisplayName: Yaw Servo Max Lean Angle
// @Description: Yaw servo's maximum lean angle
// @Range: 5 80
2017-05-02 10:45:39 -03:00
// @Units: deg
2017-01-09 03:31:56 -04:00
// @Increment: 1
// @User: Standard
2017-02-07 19:46:44 -04:00
AP_GROUPINFO_FRAME ( " YAW_SV_ANGLE " , 35 , AP_MotorsMulticopter , _yaw_servo_angle_max_deg , 30 , AP_PARAM_FRAME_TRICOPTER ) ,
2017-02-13 06:35:30 -04:00
// @Param: SPOOL_TIME
// @DisplayName: Spool up time
// @Description: Time in seconds to spool up the motors from zero to min throttle.
// @Range: 0 2
2017-05-02 10:45:39 -03:00
// @Units: s
2017-02-13 06:35:30 -04:00
// @Increment: 0.1
// @User: Advanced
AP_GROUPINFO ( " SPOOL_TIME " , 36 , AP_MotorsMulticopter , _spool_up_time , AP_MOTORS_SPOOL_UP_TIME_DEFAULT ) ,
2017-04-17 07:05:18 -03:00
// @Param: BOOST_SCALE
// @DisplayName: Motor boost scale
// @Description: This is a scaling factor for vehicles with a vertical booster motor used for extra lift. It is used with electric multicopters that have an internal combusion booster motor for longer endurance. The output to the BoostThrottle servo function is set to the current motor thottle times this scaling factor. A higher scaling factor will put more of the load on the booster motor. A value of 1 will set the BoostThrottle equal to the main throttle.
// @Range: 0 5
// @Increment: 0.1
// @User: Advanced
AP_GROUPINFO ( " BOOST_SCALE " , 37 , AP_MotorsMulticopter , _boost_scale , 0 ) ,
2017-06-02 16:56:37 -03:00
// 38 RESERVED for BAT_POW_MAX
2017-01-09 03:31:56 -04:00
2015-07-02 18:15:09 -03:00
AP_GROUPEND
} ;
// Constructor
2015-07-15 08:21:13 -03:00
AP_MotorsMulticopter : : AP_MotorsMulticopter ( uint16_t loop_rate , uint16_t speed_hz ) :
2015-07-02 18:15:09 -03:00
AP_Motors ( loop_rate , speed_hz ) ,
2016-08-08 01:28:28 -03:00
_spool_mode ( SHUT_DOWN ) ,
_spin_up_ratio ( 0.0f ) ,
2015-07-15 08:21:13 -03:00
_lift_max ( 1.0f ) ,
2016-08-08 01:28:28 -03:00
_throttle_limit ( 1.0f ) ,
2016-11-18 21:48:22 -04:00
_throttle_thrust_max ( 0.0f ) ,
_disarm_safety_timer ( 0 )
2015-07-02 18:15:09 -03:00
{
AP_Param : : setup_object_defaults ( this , var_info ) ;
2015-07-15 08:21:13 -03:00
// disable all motors by default
memset ( motor_enabled , false , sizeof ( motor_enabled ) ) ;
2015-07-02 18:15:09 -03:00
// setup battery voltage filtering
_batt_voltage_filt . set_cutoff_frequency ( AP_MOTORS_BATT_VOLT_FILT_HZ ) ;
_batt_voltage_filt . reset ( 1.0f ) ;
2016-05-21 03:47:46 -03:00
2017-02-28 12:56:07 -04:00
// default throttle range
_throttle_radio_min = 1100 ;
_throttle_radio_max = 1900 ;
2015-07-02 18:15:09 -03:00
} ;
// output - sends commands to the motors
2015-07-15 08:21:13 -03:00
void AP_MotorsMulticopter : : output ( )
2015-07-02 18:15:09 -03:00
{
// update throttle filter
update_throttle_filter ( ) ;
// calc filtered battery voltage and lift_max
update_lift_max_from_batt_voltage ( ) ;
2016-01-19 01:49:46 -04:00
// run spool logic
output_logic ( ) ;
// calculate thrust
output_armed_stabilizing ( ) ;
2016-05-01 19:00:45 -03:00
// apply any thrust compensation for the frame
thrust_compensation ( ) ;
2016-01-19 01:49:46 -04:00
// convert rpy_thrust values to pwm
output_to_motors ( ) ;
2017-04-17 07:05:18 -03:00
// output any booster throttle
output_boost_throttle ( ) ;
2015-07-02 18:15:09 -03:00
} ;
2017-04-17 07:05:18 -03:00
// output booster throttle, if any
void AP_MotorsMulticopter : : output_boost_throttle ( void )
{
if ( _boost_scale > 0 ) {
float throttle = constrain_float ( get_throttle ( ) * _boost_scale , 0 , 1 ) ;
SRV_Channels : : set_output_scaled ( SRV_Channel : : k_boost_throttle , throttle * 1000 ) ;
}
}
2016-02-17 23:04:35 -04:00
// sends minimum values out to the motors
void AP_MotorsMulticopter : : output_min ( )
{
set_desired_spool_state ( DESIRED_SHUT_DOWN ) ;
2016-06-04 02:54:00 -03:00
_spool_mode = SHUT_DOWN ;
2016-02-17 23:04:35 -04:00
output ( ) ;
}
2015-07-02 18:15:09 -03:00
// update the throttle input filter
2015-07-15 08:21:13 -03:00
void AP_MotorsMulticopter : : update_throttle_filter ( )
2015-07-02 18:15:09 -03:00
{
if ( armed ( ) ) {
_throttle_filter . apply ( _throttle_in , 1.0f / _loop_rate ) ;
2016-01-21 21:23:12 -04:00
// constrain filtered throttle
if ( _throttle_filter . get ( ) < 0.0f ) {
_throttle_filter . reset ( 0.0f ) ;
}
if ( _throttle_filter . get ( ) > 1.0f ) {
_throttle_filter . reset ( 1.0f ) ;
}
2015-07-02 18:15:09 -03:00
} else {
_throttle_filter . reset ( 0.0f ) ;
}
}
2015-12-18 23:40:10 -04:00
// return current_limit as a number from 0 ~ 1 in the range throttle_min to throttle_max
float AP_MotorsMulticopter : : get_current_limit_max_throttle ( )
{
// return maximum if current limiting is disabled
if ( _batt_current_max < = 0 ) {
_throttle_limit = 1.0f ;
return 1.0f ;
}
2016-01-21 02:17:13 -04:00
// remove throttle limit if disarmed
if ( ! _flags . armed ) {
2015-12-18 23:40:10 -04:00
_throttle_limit = 1.0f ;
return 1.0f ;
}
2016-06-08 09:00:49 -03:00
// calculate the maximum current to prevent voltage sag below _batt_voltage_min
float batt_current_max = MIN ( _batt_current_max , _batt_current + ( _batt_voltage - _batt_voltage_min ) / _batt_resistance ) ;
float batt_current_ratio = _batt_current / batt_current_max ;
2015-12-18 23:40:10 -04:00
2016-06-08 08:54:32 -03:00
float loop_interval = 1.0f / _loop_rate ;
_throttle_limit + = ( loop_interval / ( loop_interval + _batt_current_time_constant ) ) * ( 1.0f - batt_current_ratio ) ;
2015-12-18 23:40:10 -04:00
// throttle limit drops to 20% between hover and full throttle
_throttle_limit = constrain_float ( _throttle_limit , 0.2f , 1.0f ) ;
// limit max throttle
2016-03-22 10:57:26 -03:00
return get_throttle_hover ( ) + ( ( 1.0 - get_throttle_hover ( ) ) * _throttle_limit ) ;
2015-12-18 23:40:10 -04:00
}
2015-12-03 02:49:19 -04:00
// apply_thrust_curve_and_volt_scaling - returns throttle in the range 0 ~ 1
float AP_MotorsMulticopter : : apply_thrust_curve_and_volt_scaling ( float thrust ) const
{
float throttle_ratio = thrust ;
// apply thrust curve - domain 0.0 to 1.0, range 0.0 to 1.0
2016-05-22 06:53:22 -03:00
if ( _thrust_curve_expo > 0.0f ) {
if ( ! is_zero ( _batt_voltage_filt . get ( ) ) ) {
throttle_ratio = ( ( _thrust_curve_expo - 1.0f ) + safe_sqrt ( ( 1.0f - _thrust_curve_expo ) * ( 1.0f - _thrust_curve_expo ) + 4.0f * _thrust_curve_expo * _lift_max * thrust ) ) / ( 2.0f * _thrust_curve_expo * _batt_voltage_filt . get ( ) ) ;
} else {
throttle_ratio = ( ( _thrust_curve_expo - 1.0f ) + safe_sqrt ( ( 1.0f - _thrust_curve_expo ) * ( 1.0f - _thrust_curve_expo ) + 4.0f * _thrust_curve_expo * _lift_max * thrust ) ) / ( 2.0f * _thrust_curve_expo ) ;
}
2015-12-03 02:49:19 -04:00
}
2016-05-22 06:53:22 -03:00
return constrain_float ( throttle_ratio , 0.0f , 1.0f ) ;
2015-12-03 02:49:19 -04:00
}
2015-07-02 18:15:09 -03:00
// update_lift_max from battery voltage - used for voltage compensation
2015-07-15 08:21:13 -03:00
void AP_MotorsMulticopter : : update_lift_max_from_batt_voltage ( )
2015-07-02 18:15:09 -03:00
{
// sanity check battery_voltage_min is not too small
// if disabled or misconfigured exit immediately
if ( ( _batt_voltage_max < = 0 ) | | ( _batt_voltage_min > = _batt_voltage_max ) | | ( _batt_voltage < 0.25f * _batt_voltage_min ) ) {
_batt_voltage_filt . reset ( 1.0f ) ;
_lift_max = 1.0f ;
return ;
}
2015-11-27 13:11:58 -04:00
_batt_voltage_min = MAX ( _batt_voltage_min , _batt_voltage_max * 0.6f ) ;
2015-07-02 18:15:09 -03:00
2017-05-23 01:08:36 -03:00
// contrain resting voltage estimate (resting voltage is actual voltage with sag removed based on current draw and resistance)
_batt_voltage_resting_estimate = constrain_float ( _batt_voltage_resting_estimate , _batt_voltage_min , _batt_voltage_max ) ;
2015-07-02 18:15:09 -03:00
// filter at 0.5 Hz
2017-05-23 01:08:36 -03:00
float batt_voltage_filt = _batt_voltage_filt . apply ( _batt_voltage_resting_estimate / _batt_voltage_max , 1.0f / _loop_rate ) ;
2015-07-02 18:15:09 -03:00
// calculate lift max
2016-05-22 06:53:22 -03:00
_lift_max = batt_voltage_filt * ( 1 - _thrust_curve_expo ) + _thrust_curve_expo * batt_voltage_filt * batt_voltage_filt ;
2015-07-02 18:15:09 -03:00
}
2015-07-15 08:21:13 -03:00
float AP_MotorsMulticopter : : get_compensation_gain ( ) const
2015-07-02 18:15:09 -03:00
{
// avoid divide by zero
if ( _lift_max < = 0.0f ) {
return 1.0f ;
}
float ret = 1.0f / _lift_max ;
2016-01-22 14:41:19 -04:00
# if AP_MOTORS_DENSITY_COMP == 1
2015-07-02 18:15:09 -03:00
// air density ratio is increasing in density / decreasing in altitude
if ( _air_density_ratio > 0.3f & & _air_density_ratio < 1.5f ) {
ret * = 1.0f / constrain_float ( _air_density_ratio , 0.5f , 1.25f ) ;
}
2016-01-22 14:41:19 -04:00
# endif
2015-07-02 18:15:09 -03:00
return ret ;
}
2015-12-03 02:47:51 -04:00
int16_t AP_MotorsMulticopter : : calc_thrust_to_pwm ( float thrust_in ) const
{
2016-05-26 10:13:49 -03:00
thrust_in = constrain_float ( thrust_in , 0.0f , 1.0f ) ;
2016-05-22 06:02:19 -03:00
return get_pwm_output_min ( ) + ( get_pwm_output_max ( ) - get_pwm_output_min ( ) ) * ( _spin_min + ( _spin_max - _spin_min ) * apply_thrust_curve_and_volt_scaling ( thrust_in ) ) ;
2016-06-09 03:34:47 -03:00
}
2016-06-08 06:10:54 -03:00
int16_t AP_MotorsMulticopter : : calc_spin_up_to_pwm ( ) const
{
2016-05-22 06:02:19 -03:00
return get_pwm_output_min ( ) + constrain_float ( _spin_up_ratio , 0.0f , 1.0f ) * _spin_min * ( get_pwm_output_max ( ) - get_pwm_output_min ( ) ) ;
}
2016-05-21 03:47:46 -03:00
// get minimum or maximum pwm value that can be output to motors
2016-05-21 23:02:42 -03:00
int16_t AP_MotorsMulticopter : : get_pwm_output_min ( ) const
2016-05-21 03:47:46 -03:00
{
2016-05-21 23:01:04 -03:00
// return _pwm_min if both PWM_MIN and PWM_MAX parameters are defined and valid
2016-05-21 03:47:46 -03:00
if ( ( _pwm_min > 0 ) & & ( _pwm_max > 0 ) & & ( _pwm_max > _pwm_min ) ) {
return _pwm_min ;
}
return _throttle_radio_min ;
}
// get maximum pwm value that can be output to motors
2016-05-21 23:02:42 -03:00
int16_t AP_MotorsMulticopter : : get_pwm_output_max ( ) const
2016-05-21 03:47:46 -03:00
{
2016-05-21 23:01:04 -03:00
// return _pwm_max if both PWM_MIN and PWM_MAX parameters are defined and valid
2016-05-21 03:47:46 -03:00
if ( ( _pwm_min > 0 ) & & ( _pwm_max > 0 ) & & ( _pwm_max > _pwm_min ) ) {
return _pwm_max ;
}
return _throttle_radio_max ;
2015-12-03 02:47:51 -04:00
}
2015-07-02 18:15:09 -03:00
// set_throttle_range - sets the minimum throttle that will be sent to the engines when they're not off (i.e. to prevents issues with some motors spinning and some not at very low throttle)
// also sets throttle channel minimum and maximum pwm
2016-06-09 03:34:47 -03:00
void AP_MotorsMulticopter : : set_throttle_range ( int16_t radio_min , int16_t radio_max )
2015-07-02 18:15:09 -03:00
{
2016-05-21 03:47:46 -03:00
// sanity check
2017-02-09 23:14:28 -04:00
if ( radio_max < = radio_min ) {
return ;
2016-05-21 03:47:46 -03:00
}
2017-02-09 23:14:28 -04:00
_throttle_radio_min = radio_min ;
_throttle_radio_max = radio_max ;
hal . rcout - > set_esc_scaling ( get_pwm_output_min ( ) , get_pwm_output_max ( ) ) ;
2015-07-02 18:15:09 -03:00
}
2016-03-22 10:57:26 -03:00
// update the throttle input filter. should be called at 100hz
void AP_MotorsMulticopter : : update_throttle_hover ( float dt )
{
2016-06-16 02:28:49 -03:00
if ( _throttle_hover_learn ! = HOVER_LEARN_DISABLED ) {
2016-06-25 01:34:26 -03:00
// we have chosen to constrain the hover throttle to be within the range reachable by the third order expo polynomial.
_throttle_hover = constrain_float ( _throttle_hover + ( dt / ( dt + AP_MOTORS_THST_HOVER_TC ) ) * ( get_throttle ( ) - _throttle_hover ) , AP_MOTORS_THST_HOVER_MIN , AP_MOTORS_THST_HOVER_MAX ) ;
2016-06-09 02:21:04 -03:00
}
2016-03-22 10:57:26 -03:00
}
2016-06-04 02:51:00 -03:00
// run spool logic
2016-01-19 01:49:46 -04:00
void AP_MotorsMulticopter : : output_logic ( )
{
2016-11-18 21:48:22 -04:00
if ( _flags . armed ) {
_disarm_safety_timer = 100 ;
} else if ( _disarm_safety_timer ! = 0 ) {
_disarm_safety_timer - - ;
}
2016-01-19 01:49:46 -04:00
// force desired and current spool mode if disarmed or not interlocked
if ( ! _flags . armed | | ! _flags . interlock ) {
2016-02-02 08:13:43 -04:00
_spool_desired = DESIRED_SHUT_DOWN ;
2016-06-04 02:54:00 -03:00
_spool_mode = SHUT_DOWN ;
2016-01-19 01:49:46 -04:00
}
2017-02-13 06:35:30 -04:00
if ( _spool_up_time < 0.05 ) {
// prevent float exception
_spool_up_time . set ( 0.05 ) ;
}
2016-06-04 02:54:00 -03:00
switch ( _spool_mode ) {
2016-01-19 01:49:46 -04:00
case SHUT_DOWN :
// Motors should be stationary.
// Servos set to their trim values or in a test condition.
// set limits flags
limit . roll_pitch = true ;
limit . yaw = true ;
limit . throttle_lower = true ;
limit . throttle_upper = true ;
// make sure the motors are spooling in the correct direction
2016-03-25 06:06:02 -03:00
if ( _spool_desired ! = DESIRED_SHUT_DOWN ) {
2016-06-04 02:54:00 -03:00
_spool_mode = SPIN_WHEN_ARMED ;
2016-01-19 01:49:46 -04:00
break ;
}
// set and increment ramp variables
2016-06-08 06:10:54 -03:00
_spin_up_ratio = 0.0f ;
2016-01-19 01:49:46 -04:00
_throttle_thrust_max = 0.0f ;
break ;
2016-03-25 06:06:02 -03:00
case SPIN_WHEN_ARMED : {
2016-01-19 01:49:46 -04:00
// Motors should be stationary or at spin when armed.
2016-03-25 06:06:02 -03:00
// Servos should be moving to correct the current attitude.
2016-01-19 01:49:46 -04:00
// set limits flags
limit . roll_pitch = true ;
limit . yaw = true ;
limit . throttle_lower = true ;
limit . throttle_upper = true ;
// set and increment ramp variables
2017-02-13 06:35:30 -04:00
float spool_step = 1.0f / ( _spool_up_time * _loop_rate ) ;
2016-03-25 06:04:52 -03:00
if ( _spool_desired = = DESIRED_SHUT_DOWN ) {
2016-06-08 06:10:54 -03:00
_spin_up_ratio - = spool_step ;
2016-03-25 06:04:52 -03:00
// constrain ramp value and update mode
2016-06-08 06:10:54 -03:00
if ( _spin_up_ratio < = 0.0f ) {
_spin_up_ratio = 0.0f ;
2016-06-04 02:54:00 -03:00
_spool_mode = SHUT_DOWN ;
2016-03-25 06:04:52 -03:00
}
} else if ( _spool_desired = = DESIRED_THROTTLE_UNLIMITED ) {
2016-06-08 06:10:54 -03:00
_spin_up_ratio + = spool_step ;
2016-03-25 06:04:52 -03:00
// constrain ramp value and update mode
2016-06-08 06:10:54 -03:00
if ( _spin_up_ratio > = 1.0f ) {
_spin_up_ratio = 1.0f ;
2016-06-04 02:54:00 -03:00
_spool_mode = SPOOL_UP ;
2016-03-25 06:04:52 -03:00
}
} else { // _spool_desired == SPIN_WHEN_ARMED
2016-06-08 06:10:54 -03:00
float spin_up_armed_ratio = 0.0f ;
2016-05-22 06:02:19 -03:00
if ( _spin_min > 0.0f ) {
spin_up_armed_ratio = _spin_arm / _spin_min ;
2016-03-25 06:04:52 -03:00
}
2016-06-08 06:10:54 -03:00
_spin_up_ratio + = constrain_float ( spin_up_armed_ratio - _spin_up_ratio , - spool_step , spool_step ) ;
2016-01-19 01:49:46 -04:00
}
_throttle_thrust_max = 0.0f ;
break ;
}
case SPOOL_UP :
// Maximum throttle should move from minimum to maximum.
2016-04-13 17:45:19 -03:00
// Servos should exhibit normal flight behavior.
2016-01-19 01:49:46 -04:00
// initialize limits flags
limit . roll_pitch = false ;
limit . yaw = false ;
limit . throttle_lower = false ;
limit . throttle_upper = false ;
// make sure the motors are spooling in the correct direction
2016-03-25 06:06:02 -03:00
if ( _spool_desired ! = DESIRED_THROTTLE_UNLIMITED ) {
2016-06-04 02:54:00 -03:00
_spool_mode = SPOOL_DOWN ;
2016-01-19 01:49:46 -04:00
break ;
}
// set and increment ramp variables
2016-06-08 06:10:54 -03:00
_spin_up_ratio = 1.0f ;
2017-02-13 06:35:30 -04:00
_throttle_thrust_max + = 1.0f / ( _spool_up_time * _loop_rate ) ;
2016-01-19 01:49:46 -04:00
// constrain ramp value and update mode
if ( _throttle_thrust_max > = MIN ( get_throttle ( ) , get_current_limit_max_throttle ( ) ) ) {
_throttle_thrust_max = get_current_limit_max_throttle ( ) ;
2016-06-04 02:54:00 -03:00
_spool_mode = THROTTLE_UNLIMITED ;
2016-01-19 01:49:46 -04:00
} else if ( _throttle_thrust_max < 0.0f ) {
_throttle_thrust_max = 0.0f ;
}
break ;
case THROTTLE_UNLIMITED :
// Throttle should exhibit normal flight behavior.
2016-04-13 17:45:19 -03:00
// Servos should exhibit normal flight behavior.
2016-01-19 01:49:46 -04:00
// initialize limits flags
limit . roll_pitch = false ;
limit . yaw = false ;
limit . throttle_lower = false ;
limit . throttle_upper = false ;
// make sure the motors are spooling in the correct direction
2016-03-25 06:06:02 -03:00
if ( _spool_desired ! = DESIRED_THROTTLE_UNLIMITED ) {
2016-06-04 02:54:00 -03:00
_spool_mode = SPOOL_DOWN ;
2016-01-19 01:49:46 -04:00
break ;
}
// set and increment ramp variables
2016-06-08 06:10:54 -03:00
_spin_up_ratio = 1.0f ;
2016-01-19 01:49:46 -04:00
_throttle_thrust_max = get_current_limit_max_throttle ( ) ;
break ;
case SPOOL_DOWN :
// Maximum throttle should move from maximum to minimum.
2016-04-13 17:45:19 -03:00
// Servos should exhibit normal flight behavior.
2016-01-19 01:49:46 -04:00
// initialize limits flags
limit . roll_pitch = false ;
limit . yaw = false ;
limit . throttle_lower = false ;
limit . throttle_upper = false ;
// make sure the motors are spooling in the correct direction
2016-03-25 06:06:02 -03:00
if ( _spool_desired = = DESIRED_THROTTLE_UNLIMITED ) {
2016-06-04 02:54:00 -03:00
_spool_mode = SPOOL_UP ;
2016-01-19 01:49:46 -04:00
break ;
}
// set and increment ramp variables
2016-06-08 06:10:54 -03:00
_spin_up_ratio = 1.0f ;
2017-02-13 06:35:30 -04:00
_throttle_thrust_max - = 1.0f / ( _spool_up_time * _loop_rate ) ;
2016-01-19 01:49:46 -04:00
// constrain ramp value and update mode
if ( _throttle_thrust_max < = 0.0f ) {
_throttle_thrust_max = 0.0f ;
}
if ( _throttle_thrust_max > = get_current_limit_max_throttle ( ) ) {
_throttle_thrust_max = get_current_limit_max_throttle ( ) ;
2016-03-21 11:21:19 -03:00
} else if ( is_zero ( _throttle_thrust_max ) ) {
2016-06-04 02:54:00 -03:00
_spool_mode = SPIN_WHEN_ARMED ;
2016-01-19 01:49:46 -04:00
}
break ;
}
}
2016-05-21 03:47:46 -03:00
// passes throttle directly to all motors for ESC calibration.
2016-05-21 23:02:42 -03:00
// throttle_input is in the range of 0 ~ 1 where 0 will send get_pwm_output_min() and 1 will send get_pwm_output_max()
2016-05-21 03:47:46 -03:00
void AP_MotorsMulticopter : : set_throttle_passthrough_for_esc_calibration ( float throttle_input )
2015-07-02 18:15:09 -03:00
{
if ( armed ( ) ) {
2016-05-21 23:02:42 -03:00
uint16_t pwm_out = get_pwm_output_min ( ) + constrain_float ( throttle_input , 0.0f , 1.0f ) * ( get_pwm_output_max ( ) - get_pwm_output_min ( ) ) ;
2015-07-02 18:15:09 -03:00
// send the pilot's input directly to each enabled motor
2015-09-28 23:59:46 -03:00
for ( uint16_t i = 0 ; i < AP_MOTORS_MAX_NUM_MOTORS ; i + + ) {
2015-07-02 18:15:09 -03:00
if ( motor_enabled [ i ] ) {
2016-05-21 03:47:46 -03:00
rc_write ( i , pwm_out ) ;
2015-07-02 18:15:09 -03:00
}
}
}
2015-07-15 08:21:13 -03:00
}
2016-05-01 00:07:00 -03:00
// output a thrust to all motors that match a given motor mask. This
// is used to control tiltrotor motors in forward flight. Thrust is in
// the range 0 to 1
void AP_MotorsMulticopter : : output_motor_mask ( float thrust , uint8_t mask )
{
for ( uint8_t i = 0 ; i < AP_MOTORS_MAX_NUM_MOTORS ; i + + ) {
if ( motor_enabled [ i ] ) {
int16_t motor_out ;
if ( mask & ( 1U < < i ) ) {
motor_out = calc_thrust_to_pwm ( thrust ) ;
} else {
2016-05-21 23:02:42 -03:00
motor_out = get_pwm_output_min ( ) ;
2016-05-01 00:07:00 -03:00
}
rc_write ( i , motor_out ) ;
}
}
}
2016-06-09 02:21:04 -03:00
// save parameters as part of disarming
void AP_MotorsMulticopter : : save_params_on_disarm ( )
{
// save hover throttle
2016-06-16 02:28:49 -03:00
if ( _throttle_hover_learn = = HOVER_LEARN_AND_SAVE ) {
2016-06-09 02:21:04 -03:00
_throttle_hover . save ( ) ;
}
}