mixer_module always use MIN/MAX/DIS/FAIL parameters

This commit is contained in:
Daniel Agar 2021-10-21 20:20:15 -04:00
parent 6938d24ec7
commit 62714d6c5d
No known key found for this signature in database
GPG Key ID: FD3CBA98017A69DE
19 changed files with 50 additions and 1189 deletions

View File

@ -15,7 +15,7 @@ param set-default RTL_RETURN_ALT 30
param set-default RTL_DESCEND_ALT 10
param set-default PWM_MAIN_MAX 1950
param set-default PWM_MAIN_MIN 1075
param set-default PWM_MAIN_MIN1 1075
param set-default PWM_MAIN_RATE 400
param set-default GPS_UBX_DYNMODEL 6

View File

@ -7,4 +7,3 @@ bool lockdown # Set to true if actuators are forced to being disabled (due to e
bool manual_lockdown # Set to true if manual throttle kill switch is engaged
bool force_failsafe # Set to true if the actuators are forced to the failsafe position
bool in_esc_calibration_mode # IO/FMU should ignore messages from the actuator controls topics
bool soft_stop # Set to true if we need to ESCs to remove the idle constraint

View File

@ -118,11 +118,6 @@ struct pwm_output_values {
#endif // not PX4_PWM_ALTERNATE_RANGES
/**
* Do not output a channel with this value
*/
#define PWM_IGNORE_THIS_CHANNEL UINT16_MAX
/**
* Servo output signal type, value is actual servo output pulse
* width in microseconds.
@ -170,15 +165,9 @@ typedef uint16_t servo_position_t;
/** start DSM bind */
#define DSM_BIND_START _PX4_IOC(_PWM_SERVO_BASE, 10)
/** set the PWM value for failsafe */
#define PWM_SERVO_SET_FAILSAFE_PWM _PX4_IOC(_PWM_SERVO_BASE, 12)
/** get the PWM value for failsafe */
#define PWM_SERVO_GET_FAILSAFE_PWM _PX4_IOC(_PWM_SERVO_BASE, 13)
/** set the PWM value when disarmed - should be no PWM (zero) by default */
#define PWM_SERVO_SET_DISARMED_PWM _PX4_IOC(_PWM_SERVO_BASE, 14)
/** get the PWM value when disarmed */
#define PWM_SERVO_GET_DISARMED_PWM _PX4_IOC(_PWM_SERVO_BASE, 15)
@ -197,21 +186,9 @@ typedef uint16_t servo_position_t;
/** get the TRIM value the output will send */
#define PWM_SERVO_GET_TRIM_PWM _PX4_IOC(_PWM_SERVO_BASE, 21)
/** set the lockdown override flag to enable outputs in HIL */
#define PWM_SERVO_SET_DISABLE_LOCKDOWN _PX4_IOC(_PWM_SERVO_BASE, 23)
/** get the lockdown override flag to enable outputs in HIL */
#define PWM_SERVO_GET_DISABLE_LOCKDOWN _PX4_IOC(_PWM_SERVO_BASE, 24)
/** force safety switch off (to disable use of safety switch) */
#define PWM_SERVO_SET_FORCE_SAFETY_OFF _PX4_IOC(_PWM_SERVO_BASE, 25)
/** force failsafe mode (failsafe values are set immediately even if failsafe condition not met) */
#define PWM_SERVO_SET_FORCE_FAILSAFE _PX4_IOC(_PWM_SERVO_BASE, 26)
/** make failsafe non-recoverable (termination) if it occurs */
#define PWM_SERVO_SET_TERMINATION_FAILSAFE _PX4_IOC(_PWM_SERVO_BASE, 27)
/** force safety switch on (to enable use of safety switch) */
#define PWM_SERVO_SET_FORCE_SAFETY_ON _PX4_IOC(_PWM_SERVO_BASE, 28)

View File

@ -44,10 +44,6 @@ LinuxPWMOut::LinuxPWMOut() :
_cycle_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")),
_interval_perf(perf_alloc(PC_INTERVAL, MODULE_NAME": interval"))
{
if (!_mixing_output.useDynamicMixing()) {
_mixing_output.setAllMinValues(PWM_DEFAULT_MIN);
_mixing_output.setAllMaxValues(PWM_DEFAULT_MAX);
}
}
LinuxPWMOut::~LinuxPWMOut()
@ -161,128 +157,6 @@ void LinuxPWMOut::update_params()
return;
}
int32_t pwm_min_default = PWM_DEFAULT_MIN;
int32_t pwm_max_default = PWM_DEFAULT_MAX;
int32_t pwm_disarmed_default = 0;
const char *prefix;
if (_class_instance == CLASS_DEVICE_PRIMARY) {
prefix = "PWM_MAIN";
param_get(param_find("PWM_MAIN_MIN"), &pwm_min_default);
param_get(param_find("PWM_MAIN_MAX"), &pwm_max_default);
param_get(param_find("PWM_MAIN_DISARM"), &pwm_disarmed_default);
} else if (_class_instance == CLASS_DEVICE_SECONDARY) {
prefix = "PWM_AUX";
param_get(param_find("PWM_AUX_MIN"), &pwm_min_default);
param_get(param_find("PWM_AUX_MAX"), &pwm_max_default);
param_get(param_find("PWM_AUX_DISARM"), &pwm_disarmed_default);
} else if (_class_instance == CLASS_DEVICE_TERTIARY) {
prefix = "PWM_EXTRA";
param_get(param_find("PWM_EXTRA_MIN"), &pwm_min_default);
param_get(param_find("PWM_EXTRA_MAX"), &pwm_max_default);
param_get(param_find("PWM_EXTRA_DISARM"), &pwm_disarmed_default);
} else {
PX4_ERR("invalid class instance %d", _class_instance);
return;
}
char str[17];
for (unsigned i = 0; i < MAX_ACTUATORS; i++) {
// PWM_MAIN_MINx
{
sprintf(str, "%s_MIN%u", prefix, i + 1);
int32_t pwm_min = -1;
if (param_get(param_find(str), &pwm_min) == PX4_OK && pwm_min >= 0) {
_mixing_output.minValue(i) = math::constrain(pwm_min, PWM_LOWEST_MIN, PWM_HIGHEST_MIN);
if (pwm_min != _mixing_output.minValue(i)) {
int32_t pwm_min_new = _mixing_output.minValue(i);
param_set(param_find(str), &pwm_min_new);
}
} else {
_mixing_output.minValue(i) = pwm_min_default;
}
}
// PWM_MAIN_MAXx
{
sprintf(str, "%s_MAX%u", prefix, i + 1);
int32_t pwm_max = -1;
if (param_get(param_find(str), &pwm_max) == PX4_OK && pwm_max >= 0) {
_mixing_output.maxValue(i) = math::constrain(pwm_max, PWM_LOWEST_MAX, PWM_HIGHEST_MAX);
if (pwm_max != _mixing_output.maxValue(i)) {
int32_t pwm_max_new = _mixing_output.maxValue(i);
param_set(param_find(str), &pwm_max_new);
}
} else {
_mixing_output.maxValue(i) = pwm_max_default;
}
}
// PWM_MAIN_FAILx
{
sprintf(str, "%s_FAIL%u", prefix, i + 1);
int32_t pwm_failsafe = -1;
if (param_get(param_find(str), &pwm_failsafe) == PX4_OK && pwm_failsafe >= 0) {
_mixing_output.failsafeValue(i) = math::constrain(pwm_failsafe, 0, PWM_HIGHEST_MAX);
if (pwm_failsafe != _mixing_output.failsafeValue(i)) {
int32_t pwm_fail_new = _mixing_output.failsafeValue(i);
param_set(param_find(str), &pwm_fail_new);
}
}
}
// PWM_MAIN_DISx
{
sprintf(str, "%s_DIS%u", prefix, i + 1);
int32_t pwm_dis = -1;
if (param_get(param_find(str), &pwm_dis) == PX4_OK && pwm_dis >= 0) {
_mixing_output.disarmedValue(i) = math::constrain(pwm_dis, 0, PWM_HIGHEST_MAX);
if (pwm_dis != _mixing_output.disarmedValue(i)) {
int32_t pwm_dis_new = _mixing_output.disarmedValue(i);
param_set(param_find(str), &pwm_dis_new);
}
} else {
_mixing_output.disarmedValue(i) = pwm_disarmed_default;
}
}
// PWM_MAIN_REVx
{
sprintf(str, "%s_REV%u", prefix, i + 1);
int32_t pwm_rev = 0;
if (param_get(param_find(str), &pwm_rev) == PX4_OK) {
uint16_t &reverse_pwm_mask = _mixing_output.reverseOutputMask();
if (pwm_rev >= 1) {
reverse_pwm_mask = reverse_pwm_mask | (2 << i);
} else {
reverse_pwm_mask = reverse_pwm_mask & ~(2 << i);
}
}
}
}
if (_mixing_output.mixers()) {
int16_t values[MAX_ACTUATORS] {};

View File

@ -124,10 +124,6 @@ PCA9685Wrapper::PCA9685Wrapper(int schd_rate_limit) :
_cycle_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")),
_schd_rate_limit(schd_rate_limit)
{
if (!_mixing_output.useDynamicMixing()) {
_mixing_output.setAllMinValues(PWM_DEFAULT_MIN);
_mixing_output.setAllMaxValues(PWM_DEFAULT_MAX);
}
}
PCA9685Wrapper::~PCA9685Wrapper()
@ -179,151 +175,6 @@ void PCA9685Wrapper::updatePWMParams()
return;
}
// update pwm params
const char *pname_format_pwm_ch_max[2] = {"PWM_MAIN_MAX%d", "PWM_AUX_MAX%d"};
const char *pname_format_pwm_ch_min[2] = {"PWM_MAIN_MIN%d", "PWM_AUX_MIN%d"};
const char *pname_format_pwm_ch_fail[2] = {"PWM_MAIN_FAIL%d", "PWM_AUX_FAIL%d"};
const char *pname_format_pwm_ch_dis[2] = {"PWM_MAIN_DIS%d", "PWM_AUX_DIS%d"};
const char *pname_format_pwm_ch_rev[2] = {"PWM_MAIN_REV%d", "PWM_AUX_REV%d"};
int32_t default_pwm_max = PWM_DEFAULT_MAX,
default_pwm_min = PWM_DEFAULT_MIN,
default_pwm_fail = PWM_DEFAULT_MIN,
default_pwm_dis = PWM_MOTOR_OFF;
param_t param_h = param_find("PWM_MAIN_MAX");
if (param_h != PARAM_INVALID) {
param_get(param_h, &default_pwm_max);
} else {
PX4_DEBUG("PARAM_INVALID: %s", "PWM_MAIN_MAX");
}
param_h = param_find("PWM_MAIN_MIN");
if (param_h != PARAM_INVALID) {
param_get(param_h, &default_pwm_min);
} else {
PX4_DEBUG("PARAM_INVALID: %s", "PWM_MAIN_MIN");
}
param_h = param_find("PWM_MAIN_RATE");
if (param_h != PARAM_INVALID) {
int32_t pval = 0;
param_get(param_h, &pval);
if (_last_fetched_Freq != pval) {
_last_fetched_Freq = pval;
_targetFreq = (float)pval; // update only if changed
}
} else {
PX4_DEBUG("PARAM_INVALID: %s", "PWM_MAIN_RATE");
}
for (int i = 0; i < PCA9685_PWM_CHANNEL_COUNT; i++) {
char pname[16];
uint8_t param_group, param_index;
if (i <= 7) { // Main channel
param_group = 0;
param_index = i + 1;
} else { // AUX
param_group = 1;
param_index = i - 8 + 1;
}
sprintf(pname, pname_format_pwm_ch_max[param_group], param_index);
param_h = param_find(pname);
if (param_h != PARAM_INVALID) {
int32_t pval = 0;
param_get(param_h, &pval);
if (pval != -1) {
_mixing_output.maxValue(i) = pval;
} else {
_mixing_output.maxValue(i) = default_pwm_max;
}
} else {
PX4_DEBUG("PARAM_INVALID: %s", pname);
}
sprintf(pname, pname_format_pwm_ch_min[param_group], param_index);
param_h = param_find(pname);
if (param_h != PARAM_INVALID) {
int32_t pval = 0;
param_get(param_h, &pval);
if (pval != -1) {
_mixing_output.minValue(i) = pval;
} else {
_mixing_output.minValue(i) = default_pwm_min;
}
} else {
PX4_DEBUG("PARAM_INVALID: %s", pname);
}
sprintf(pname, pname_format_pwm_ch_fail[param_group], param_index);
param_h = param_find(pname);
if (param_h != PARAM_INVALID) {
int32_t pval = 0;
param_get(param_h, &pval);
if (pval != -1) {
_mixing_output.failsafeValue(i) = pval;
} else {
_mixing_output.failsafeValue(i) = default_pwm_fail;
}
} else {
PX4_DEBUG("PARAM_INVALID: %s", pname);
}
sprintf(pname, pname_format_pwm_ch_dis[param_group], param_index);
param_h = param_find(pname);
if (param_h != PARAM_INVALID) {
int32_t pval = 0;
param_get(param_h, &pval);
if (pval != -1) {
_mixing_output.disarmedValue(i) = pval;
} else {
_mixing_output.disarmedValue(i) = default_pwm_dis;
}
} else {
PX4_DEBUG("PARAM_INVALID: %s", pname);
}
sprintf(pname, pname_format_pwm_ch_rev[param_group], param_index);
param_h = param_find(pname);
if (param_h != PARAM_INVALID) {
uint16_t &reverse_pwm_mask = _mixing_output.reverseOutputMask();
int32_t pval = 0;
param_get(param_h, &pval);
reverse_pwm_mask &= (0xfffe << i); // clear this bit
reverse_pwm_mask |= (((uint16_t)(pval != 0)) << i); // set to new val
} else {
PX4_DEBUG("PARAM_INVALID: %s", pname);
}
}
if (_mixing_output.mixers()) { // only update trims if mixer loaded
updatePWMParamTrim();
}

View File

@ -56,10 +56,6 @@ PWMOut::PWMOut(int instance, uint8_t output_base) :
_cycle_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")),
_interval_perf(perf_alloc(PC_INTERVAL, MODULE_NAME": interval"))
{
if (!_mixing_output.useDynamicMixing()) {
_mixing_output.setAllMinValues(PWM_DEFAULT_MIN);
_mixing_output.setAllMaxValues(PWM_DEFAULT_MAX);
}
}
PWMOut::~PWMOut()
@ -487,10 +483,6 @@ void PWMOut::Run()
}
}
if (_pwm_initialized && _current_update_rate == 0 && !_mixing_output.useDynamicMixing()) {
update_current_rate();
}
// check at end of cycle (updateSubscriptions() can potentially change to a different WorkQueue thread)
_mixing_output.updateSubscriptions(true, true);
@ -505,9 +497,6 @@ void PWMOut::update_params()
return;
}
int32_t pwm_min_default = PWM_DEFAULT_MIN;
int32_t pwm_max_default = PWM_DEFAULT_MAX;
int32_t pwm_disarmed_default = 0;
int32_t pwm_rate_default = 50;
int32_t pwm_default_channels = 0;
@ -516,28 +505,20 @@ void PWMOut::update_params()
if (_class_instance == CLASS_DEVICE_PRIMARY) {
prefix = "PWM_MAIN";
param_get(param_find("PWM_MAIN_MIN"), &pwm_min_default);
param_get(param_find("PWM_MAIN_MAX"), &pwm_max_default);
param_get(param_find("PWM_MAIN_DISARM"), &pwm_disarmed_default);
param_get(param_find("PWM_MAIN_RATE"), &pwm_rate_default);
param_get(param_find("PWM_MAIN_OUT"), &pwm_default_channels);
} else if (_class_instance == CLASS_DEVICE_SECONDARY) {
prefix = "PWM_AUX";
param_get(param_find("PWM_AUX_MIN"), &pwm_min_default);
param_get(param_find("PWM_AUX_MAX"), &pwm_max_default);
param_get(param_find("PWM_AUX_DISARM"), &pwm_disarmed_default);
param_get(param_find("PWM_AUX_RATE"), &pwm_rate_default);
param_get(param_find("PWM_AUX_OUT"), &pwm_default_channels);
} else if (_class_instance == CLASS_DEVICE_TERTIARY) {
prefix = "PWM_EXTRA";
param_get(param_find("PWM_EXTRA_MIN"), &pwm_min_default);
param_get(param_find("PWM_EXTRA_MAX"), &pwm_max_default);
param_get(param_find("PWM_EXTRA_DISARM"), &pwm_disarmed_default);
param_get(param_find("PWM_EXTRA_RATE"), &pwm_rate_default);
param_get(param_find("PWM_EXTRA_OUT"), &pwm_default_channels);
} else {
PX4_ERR("invalid class instance %d", _class_instance);
@ -558,106 +539,6 @@ void PWMOut::update_params()
char str[17];
for (unsigned i = 0; i < _num_outputs; i++) {
// PWM_MAIN_MINx
{
sprintf(str, "%s_MIN%u", prefix, i + 1);
int32_t pwm_min = -1;
if (param_get(param_find(str), &pwm_min) == PX4_OK) {
if (pwm_min >= 0 && pwm_min != 1000) {
_mixing_output.minValue(i) = math::constrain(pwm_min, (int32_t) PWM_LOWEST_MIN, (int32_t) PWM_HIGHEST_MIN);
if (pwm_min != _mixing_output.minValue(i)) {
int32_t pwm_min_new = _mixing_output.minValue(i);
param_set(param_find(str), &pwm_min_new);
}
} else if (pwm_default_channel_mask & 1 << i) {
_mixing_output.minValue(i) = pwm_min_default;
}
}
}
// PWM_MAIN_MAXx
{
sprintf(str, "%s_MAX%u", prefix, i + 1);
int32_t pwm_max = -1;
if (param_get(param_find(str), &pwm_max) == PX4_OK) {
if (pwm_max >= 0 && pwm_max != 2000) {
_mixing_output.maxValue(i) = math::constrain(pwm_max, (int32_t) PWM_LOWEST_MAX, (int32_t) PWM_HIGHEST_MAX);
if (pwm_max != _mixing_output.maxValue(i)) {
int32_t pwm_max_new = _mixing_output.maxValue(i);
param_set(param_find(str), &pwm_max_new);
}
} else if (pwm_default_channel_mask & 1 << i) {
_mixing_output.maxValue(i) = pwm_max_default;
}
}
}
// PWM_MAIN_FAILx
{
sprintf(str, "%s_FAIL%u", prefix, i + 1);
int32_t pwm_failsafe = -1;
if (param_get(param_find(str), &pwm_failsafe) == PX4_OK) {
if (pwm_failsafe >= 0) {
_mixing_output.failsafeValue(i) = math::constrain(pwm_failsafe, (int32_t) 0, (int32_t) PWM_HIGHEST_MAX);
if (pwm_failsafe != _mixing_output.failsafeValue(i)) {
int32_t pwm_fail_new = _mixing_output.failsafeValue(i);
param_set(param_find(str), &pwm_fail_new);
}
}
}
}
// PWM_MAIN_DISx
{
sprintf(str, "%s_DIS%u", prefix, i + 1);
int32_t pwm_dis = -1;
if (param_get(param_find(str), &pwm_dis) == PX4_OK) {
if (pwm_dis >= 0 && pwm_dis != 900) {
_mixing_output.disarmedValue(i) = math::constrain(pwm_dis, (int32_t) 0, (int32_t) PWM_HIGHEST_MAX);
if (pwm_dis != _mixing_output.disarmedValue(i)) {
int32_t pwm_dis_new = _mixing_output.disarmedValue(i);
param_set(param_find(str), &pwm_dis_new);
}
} else if (pwm_default_channel_mask & 1 << i) {
_mixing_output.disarmedValue(i) = pwm_disarmed_default;
}
}
if (_mixing_output.disarmedValue(i) > 0) {
num_disarmed_set++;
}
}
// PWM_MAIN_REVx
{
sprintf(str, "%s_REV%u", prefix, i + 1);
int32_t pwm_rev = 0;
if (param_get(param_find(str), &pwm_rev) == PX4_OK) {
uint16_t &reverse_pwm_mask = _mixing_output.reverseOutputMask();
if (pwm_rev >= 1) {
reverse_pwm_mask = reverse_pwm_mask | (1 << i);
} else {
reverse_pwm_mask = reverse_pwm_mask & ~(1 << i);
}
}
}
}
if (_mixing_output.mixers()) {
int16_t values[FMU_MAX_ACTUATORS] {};
@ -736,40 +617,6 @@ int PWMOut::pwm_ioctl(file *filp, int cmd, unsigned long arg)
*(uint32_t *)arg = _pwm_alt_rate_channels;
break;
case PWM_SERVO_SET_FAILSAFE_PWM: {
struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
/* discard if too many values are sent */
if (pwm->channel_count > FMU_MAX_ACTUATORS || _mixing_output.useDynamicMixing()) {
ret = -EINVAL;
break;
}
for (unsigned i = 0; i < pwm->channel_count; i++) {
if (pwm->values[i] == 0) {
/* ignore 0 */
} else if (pwm->values[i] > PWM_HIGHEST_MAX) {
_mixing_output.failsafeValue(i) = PWM_HIGHEST_MAX;
}
#if PWM_LOWEST_MIN > 0
else if (pwm->values[i] < PWM_LOWEST_MIN) {
_mixing_output.failsafeValue(i) = PWM_LOWEST_MIN;
}
#endif
else {
_mixing_output.failsafeValue(i) = pwm->values[i];
}
}
break;
}
case PWM_SERVO_GET_FAILSAFE_PWM: {
struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
@ -781,50 +628,6 @@ int PWMOut::pwm_ioctl(file *filp, int cmd, unsigned long arg)
break;
}
case PWM_SERVO_SET_DISARMED_PWM: {
struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
/* discard if too many values are sent */
if (pwm->channel_count > FMU_MAX_ACTUATORS || _mixing_output.useDynamicMixing()) {
ret = -EINVAL;
break;
}
for (unsigned i = 0; i < pwm->channel_count; i++) {
if (pwm->values[i] == 0) {
/* ignore 0 */
} else if (pwm->values[i] > PWM_HIGHEST_MAX) {
_mixing_output.disarmedValue(i) = PWM_HIGHEST_MAX;
}
#if PWM_LOWEST_MIN > 0
else if (pwm->values[i] < PWM_LOWEST_MIN) {
_mixing_output.disarmedValue(i) = PWM_LOWEST_MIN;
}
#endif
else {
_mixing_output.disarmedValue(i) = pwm->values[i];
}
}
/*
* update the counter
* this is needed to decide if disarmed PWM output should be turned on or not
*/
_num_disarmed_set = 0;
for (unsigned i = 0; i < FMU_MAX_ACTUATORS; i++) {
if (_mixing_output.disarmedValue(i) > 0) {
_num_disarmed_set++;
}
}
break;
}
case PWM_SERVO_GET_DISARMED_PWM: {
struct pwm_output_values *pwm = (struct pwm_output_values *)arg;

View File

@ -178,7 +178,6 @@ private:
static int checkcrc(int argc, char *argv[]);
static int bind(int argc, char *argv[]);
static int lockdown(int argc, char *argv[]);
static int monitor();
static constexpr int PX4IO_MAX_ACTUATORS = 8;
@ -239,12 +238,6 @@ private:
MixingOutput _mixing_output{"PWM_MAIN", PX4IO_MAX_ACTUATORS, *this, MixingOutput::SchedulingPolicy::Auto, true};
bool _pwm_min_configured{false};
bool _pwm_max_configured{false};
bool _pwm_fail_configured{false};
bool _pwm_dis_configured{false};
bool _pwm_rev_configured{false};
/**
* Update IO's arming-related state
*/
@ -366,11 +359,6 @@ PX4IO::PX4IO(device::Device *interface) :
OutputModuleInterface(MODULE_NAME, px4::serial_port_to_wq(PX4IO_SERIAL_DEVICE)),
_interface(interface)
{
if (!_mixing_output.useDynamicMixing()) {
_mixing_output.setAllMinValues(PWM_DEFAULT_MIN);
_mixing_output.setAllMaxValues(PWM_DEFAULT_MAX);
}
_mixing_output.setLowrateSchedulingInterval(20_ms);
}
@ -757,11 +745,14 @@ void PX4IO::updateTimerRateGroups()
void PX4IO::update_params()
{
if (!_mixing_output.armed().armed) {
updateFailsafe();
updateDisarmed();
}
if (!_mixing_output.armed().armed && _mixing_output.useDynamicMixing()) {
// sync params to IO
updateTimerRateGroups();
updateFailsafe();
updateDisarmed();
return;
}
@ -770,17 +761,11 @@ void PX4IO::update_params()
return;
}
int32_t pwm_min_default = PWM_DEFAULT_MIN;
int32_t pwm_max_default = PWM_DEFAULT_MAX;
int32_t pwm_disarmed_default = 0;
int32_t pwm_rate_default = 50;
int32_t pwm_default_channels = 0;
const char *prefix = "PWM_MAIN";
param_get(param_find("PWM_MAIN_MIN"), &pwm_min_default);
param_get(param_find("PWM_MAIN_MAX"), &pwm_max_default);
param_get(param_find("PWM_MAIN_DISARM"), &pwm_disarmed_default);
param_get(param_find("PWM_MAIN_RATE"), &pwm_rate_default);
param_get(param_find("PWM_MAIN_OUT"), &pwm_default_channels);
@ -794,125 +779,6 @@ void PX4IO::update_params()
char str[17];
// PWM_MAIN_MINx
if (!_pwm_min_configured) {
for (unsigned i = 0; i < _max_actuators; i++) {
sprintf(str, "%s_MIN%u", prefix, i + 1);
int32_t pwm_min = -1;
if (param_get(param_find(str), &pwm_min) == PX4_OK) {
if (pwm_min >= 0 && pwm_min != 1000) {
_mixing_output.minValue(i) = math::constrain(pwm_min, static_cast<int32_t>(PWM_LOWEST_MIN),
static_cast<int32_t>(PWM_HIGHEST_MIN));
if (pwm_min != _mixing_output.minValue(i)) {
int32_t pwm_min_new = _mixing_output.minValue(i);
param_set(param_find(str), &pwm_min_new);
}
} else if (pwm_default_channel_mask & 1 << i) {
_mixing_output.minValue(i) = pwm_min_default;
}
}
}
_pwm_min_configured = true;
}
// PWM_MAIN_MAXx
if (!_pwm_max_configured) {
for (unsigned i = 0; i < _max_actuators; i++) {
sprintf(str, "%s_MAX%u", prefix, i + 1);
int32_t pwm_max = -1;
if (param_get(param_find(str), &pwm_max) == PX4_OK) {
if (pwm_max >= 0 && pwm_max != 2000) {
_mixing_output.maxValue(i) = math::constrain(pwm_max, static_cast<int32_t>(PWM_LOWEST_MAX),
static_cast<int32_t>(PWM_HIGHEST_MAX));
if (pwm_max != _mixing_output.maxValue(i)) {
int32_t pwm_max_new = _mixing_output.maxValue(i);
param_set(param_find(str), &pwm_max_new);
}
} else if (pwm_default_channel_mask & 1 << i) {
_mixing_output.maxValue(i) = pwm_max_default;
}
}
}
_pwm_max_configured = true;
}
// PWM_MAIN_FAILx
if (!_pwm_fail_configured) {
for (unsigned i = 0; i < _max_actuators; i++) {
sprintf(str, "%s_FAIL%u", prefix, i + 1);
int32_t pwm_fail = -1;
if (param_get(param_find(str), &pwm_fail) == PX4_OK) {
if (pwm_fail >= 0) {
_mixing_output.failsafeValue(i) = math::constrain(pwm_fail, static_cast<int32_t>(0),
static_cast<int32_t>(PWM_HIGHEST_MAX));
if (pwm_fail != _mixing_output.failsafeValue(i)) {
int32_t pwm_fail_new = _mixing_output.failsafeValue(i);
param_set(param_find(str), &pwm_fail_new);
}
}
}
}
_pwm_fail_configured = true;
updateFailsafe();
}
// PWM_MAIN_DISx
if (!_pwm_dis_configured) {
for (unsigned i = 0; i < _max_actuators; i++) {
sprintf(str, "%s_DIS%u", prefix, i + 1);
int32_t pwm_dis = -1;
if (param_get(param_find(str), &pwm_dis) == PX4_OK) {
if (pwm_dis >= 0 && pwm_dis != 900) {
_mixing_output.disarmedValue(i) = math::constrain(pwm_dis, static_cast<int32_t>(0),
static_cast<int32_t>(PWM_HIGHEST_MAX));
if (pwm_dis != _mixing_output.disarmedValue(i)) {
int32_t pwm_dis_new = _mixing_output.disarmedValue(i);
param_set(param_find(str), &pwm_dis_new);
}
} else if (pwm_default_channel_mask & 1 << i) {
_mixing_output.disarmedValue(i) = pwm_disarmed_default;
}
}
}
_pwm_dis_configured = true;
updateDisarmed();
}
// PWM_MAIN_REVx
if (!_pwm_rev_configured) {
uint16_t &reverse_pwm_mask = _mixing_output.reverseOutputMask();
reverse_pwm_mask = 0;
for (unsigned i = 0; i < _max_actuators; i++) {
sprintf(str, "%s_REV%u", prefix, i + 1);
int32_t pwm_rev = -1;
if (param_get(param_find(str), &pwm_rev) == PX4_OK) {
if (pwm_rev >= 1) {
reverse_pwm_mask |= (1 << i);
}
}
}
_pwm_rev_configured = true;
}
// PWM_MAIN_TRIMx
if (_mixing_output.mixers()) {
int16_t values[8] {};
@ -1648,27 +1514,6 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
*(unsigned *)arg = io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_RATES);
break;
case PWM_SERVO_SET_FAILSAFE_PWM: {
PX4_DEBUG("PWM_SERVO_SET_FAILSAFE_PWM");
struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
if (pwm->channel_count > _max_actuators)
/* fail with error */
{
return -E2BIG;
}
for (unsigned i = 0; i < pwm->channel_count; i++) {
if (pwm->values[i] != 0 && !_mixing_output.useDynamicMixing()) {
_mixing_output.failsafeValue(i) = math::constrain(pwm->values[i], (uint16_t)PWM_LOWEST_MIN, (uint16_t)PWM_HIGHEST_MAX);
}
}
updateFailsafe();
break;
}
case PWM_SERVO_GET_FAILSAFE_PWM: {
PX4_DEBUG("PWM_SERVO_GET_FAILSAFE_PWM");
struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
@ -1683,26 +1528,6 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
break;
}
case PWM_SERVO_SET_DISARMED_PWM: {
PX4_DEBUG("PWM_SERVO_SET_DISARMED_PWM");
struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
if (pwm->channel_count > _max_actuators) {
/* fail with error */
return -E2BIG;
}
for (unsigned i = 0; i < pwm->channel_count; i++) {
if (pwm->values[i] != 0 && !_mixing_output.useDynamicMixing()) {
_mixing_output.disarmedValue(i) = math::constrain(pwm->values[i], (uint16_t)PWM_LOWEST_MIN, (uint16_t)PWM_HIGHEST_MAX);
}
}
updateDisarmed();
break;
}
case PWM_SERVO_GET_DISARMED_PWM: {
PX4_DEBUG("PWM_SERVO_GET_DISARMED_PWM");
struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
@ -1794,16 +1619,6 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
*(unsigned *)arg = _max_actuators;
break;
case PWM_SERVO_SET_DISABLE_LOCKDOWN:
PX4_DEBUG("PWM_SERVO_SET_DISABLE_LOCKDOWN");
_lockdown_override = arg;
break;
case PWM_SERVO_GET_DISABLE_LOCKDOWN:
PX4_DEBUG("PWM_SERVO_GET_DISABLE_LOCKDOWN");
*(unsigned *)arg = _lockdown_override;
break;
case PWM_SERVO_SET_FORCE_SAFETY_OFF:
PX4_DEBUG("PWM_SERVO_SET_FORCE_SAFETY_OFF");
/* force safety swith off */
@ -1816,36 +1631,6 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
ret = io_reg_set(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FORCE_SAFETY_ON, PX4IO_FORCE_SAFETY_MAGIC);
break;
case PWM_SERVO_SET_FORCE_FAILSAFE:
PX4_DEBUG("PWM_SERVO_SET_FORCE_FAILSAFE");
/* force failsafe mode instantly */
if (arg == 0) {
/* clear force failsafe flag */
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, PX4IO_P_SETUP_ARMING_FORCE_FAILSAFE, 0);
} else {
/* set force failsafe flag */
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, 0, PX4IO_P_SETUP_ARMING_FORCE_FAILSAFE);
}
break;
case PWM_SERVO_SET_TERMINATION_FAILSAFE:
PX4_DEBUG("PWM_SERVO_SET_TERMINATION_FAILSAFE");
/* if failsafe occurs, do not allow the system to recover */
if (arg == 0) {
/* clear termination failsafe flag */
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, PX4IO_P_SETUP_ARMING_TERMINATION_FAILSAFE, 0);
} else {
/* set termination failsafe flag */
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, 0, PX4IO_P_SETUP_ARMING_TERMINATION_FAILSAFE);
}
break;
case DSM_BIND_START:
/* bind a DSM receiver */
ret = dsm_bind_ioctl(arg);
@ -2211,60 +1996,6 @@ int PX4IO::monitor()
return 0;
}
int PX4IO::lockdown(int argc, char *argv[])
{
if (argc > 1 && !strcmp(argv[1], "disable")) {
PX4_WARN("WARNING: ACTUATORS WILL BE LIVE IN HIL! PROCEED?");
PX4_WARN("Press 'y' to enable, any other key to abort.");
/* check if user wants to abort */
char c;
struct pollfd fds;
int ret;
hrt_abstime start = hrt_absolute_time();
const unsigned long timeout = 5000000;
while (hrt_elapsed_time(&start) < timeout) {
fds.fd = 0; /* stdin */
fds.events = POLLIN;
ret = ::poll(&fds, 1, 0);
if (ret > 0) {
if (::read(0, &c, 1) > 0) {
if (c != 'y') {
return 0;
} else if (c == 'y') {
break;
}
}
}
px4_usleep(10000);
}
if (hrt_elapsed_time(&start) > timeout) {
PX4_ERR("TIMEOUT! ABORTED WITHOUT CHANGES.");
return 1;
}
get_instance()->ioctl(0, PWM_SERVO_SET_DISABLE_LOCKDOWN, 1);
PX4_WARN("ACTUATORS ARE NOW LIVE IN HIL!");
} else {
get_instance()->ioctl(0, PWM_SERVO_SET_DISABLE_LOCKDOWN, 0);
PX4_WARN("ACTUATORS ARE NOW SAFE IN HIL.");
}
return 0;
}
int PX4IO::task_spawn(int argc, char *argv[])
{
device::Device *interface = get_interface();
@ -2468,10 +2199,6 @@ int PX4IO::custom_command(int argc, char *argv[])
return bind(argc - 1, argv + 1);
}
if (!strcmp(verb, "lockdown")) {
return lockdown(argc, argv);
}
if (!strcmp(verb, "sbus1_out")) {
int ret = get_instance()->ioctl(nullptr, SBUS_SET_PROTO_VERSION, 1);
@ -2534,8 +2261,6 @@ Output driver communicating with the IO co-processor.
PRINT_MODULE_USAGE_COMMAND_DESCR("monitor", "continuously monitor status");
PRINT_MODULE_USAGE_COMMAND_DESCR("bind", "DSM bind");
PRINT_MODULE_USAGE_ARG("dsm2|dsmx|dsmx8", "protocol", false);
PRINT_MODULE_USAGE_COMMAND_DESCR("lockdown", "enable (or disable) lockdown");
PRINT_MODULE_USAGE_ARG("disable", "disable lockdown", true);
PRINT_MODULE_USAGE_COMMAND_DESCR("sbus1_out", "enable sbus1 out");
PRINT_MODULE_USAGE_COMMAND_DESCR("sbus2_out", "enable sbus2 out");
PRINT_MODULE_USAGE_COMMAND_DESCR("test_fmu_fail", "test: turn off IO updates");

View File

@ -676,17 +676,6 @@ UavcanNode::init(uavcan::NodeID node_id, UAVCAN_DRIVER::BusEvent &bus_events)
return -EINVAL;
}
_mixing_interface_esc.mixingOutput().setAllDisarmedValues(UavcanEscController::DISARMED_OUTPUT_VALUE);
if (!_mixing_interface_esc.mixingOutput().useDynamicMixing()) {
// these are configurable with dynamic mixing
_mixing_interface_esc.mixingOutput().setAllMinValues(0); // Can be changed to 1 later, according to UAVCAN_ESC_IDLT
_mixing_interface_esc.mixingOutput().setAllMaxValues(UavcanEscController::max_output_value());
param_get(param_find("UAVCAN_ESC_IDLT"), &_idle_throttle_when_armed_param);
enable_idle_throttle_when_armed(true);
}
/* Start the Node */
return _node.start();
}
@ -791,10 +780,6 @@ UavcanNode::Run()
node_spin_once(); // expected to be non-blocking
// Check arming state
const actuator_armed_s &armed = _mixing_interface_esc.mixingOutput().armed();
enable_idle_throttle_when_armed(!armed.soft_stop);
// check for parameter updates
if (_parameter_update_sub.updated()) {
// clear update
@ -838,19 +823,6 @@ UavcanNode::Run()
}
}
void
UavcanNode::enable_idle_throttle_when_armed(bool value)
{
value &= _idle_throttle_when_armed_param > 0;
if (!_mixing_interface_esc.mixingOutput().useDynamicMixing()) {
if (value != _idle_throttle_when_armed) {
_mixing_interface_esc.mixingOutput().setAllMinValues(value ? 1 : 0);
_idle_throttle_when_armed = value;
}
}
}
int
UavcanNode::teardown()
{

View File

@ -216,8 +216,6 @@ private:
void set_setget_response(uavcan::protocol::param::GetSet::Response *resp) { _setget_response = resp; }
void free_setget_response(void) { _setget_response = nullptr; }
void enable_idle_throttle_when_armed(bool value);
px4::atomic_bool _task_should_exit{false}; ///< flag to indicate to tear down the CAN driver
px4::atomic<int> _fw_server_action{None};
int _fw_server_status{-1};

View File

@ -77,15 +77,6 @@ PARAM_DEFINE_INT32(UAVCAN_NODE_ID, 1);
*/
PARAM_DEFINE_INT32(UAVCAN_BITRATE, 1000000);
/**
* UAVCAN ESC will spin at idle throttle when armed, even if the mixer outputs zero setpoints.
*
* @boolean
* @reboot_required true
* @group UAVCAN
*/
PARAM_DEFINE_INT32(UAVCAN_ESC_IDLT, 1);
/**
* UAVCAN rangefinder minimum range
*

View File

@ -104,15 +104,13 @@ _param_prefix(param_prefix)
_use_dynamic_mixing = _param_sys_ctrl_alloc.get();
if (_use_dynamic_mixing) {
initParamHandles();
initParamHandles();
for (unsigned i = 0; i < MAX_ACTUATORS; i++) {
_failsafe_value[i] = UINT16_MAX;
}
updateParams();
for (unsigned i = 0; i < MAX_ACTUATORS; i++) {
_failsafe_value[i] = UINT16_MAX;
}
updateParams();
}
MixingOutput::~MixingOutput()
@ -129,8 +127,6 @@ void MixingOutput::initParamHandles()
char param_name[17];
for (unsigned i = 0; i < _max_num_outputs; ++i) {
snprintf(param_name, sizeof(param_name), "%s_%s%d", _param_prefix, "FUNC", i + 1);
_param_handles[i].function = param_find(param_name);
snprintf(param_name, sizeof(param_name), "%s_%s%d", _param_prefix, "DIS", i + 1);
_param_handles[i].disarmed = param_find(param_name);
snprintf(param_name, sizeof(param_name), "%s_%s%d", _param_prefix, "MIN", i + 1);
@ -140,6 +136,13 @@ void MixingOutput::initParamHandles()
snprintf(param_name, sizeof(param_name), "%s_%s%d", _param_prefix, "FAIL", i + 1);
_param_handles[i].failsafe = param_find(param_name);
}
if (_use_dynamic_mixing) {
for (unsigned i = 0; i < _max_num_outputs; ++i) {
snprintf(param_name, sizeof(param_name), "%s_%s%d", _param_prefix, "FUNC", i + 1);
_param_handles[i].function = param_find(param_name);
}
}
}
void MixingOutput::printStatus() const
@ -190,13 +193,40 @@ void MixingOutput::updateParams()
_mixers->set_airmode((Mixer::Airmode)_param_mc_airmode.get());
}
_reverse_output_mask = 0;
for (unsigned i = 0; i < _max_num_outputs; i++) {
int32_t val;
if (_param_handles[i].disarmed != PARAM_INVALID && param_get(_param_handles[i].disarmed, &val) == 0) {
_disarmed_value[i] = val;
}
if (_param_handles[i].min != PARAM_INVALID && param_get(_param_handles[i].min, &val) == 0) {
_min_value[i] = val;
}
if (_param_handles[i].max != PARAM_INVALID && param_get(_param_handles[i].max, &val) == 0) {
_max_value[i] = val;
}
if (_min_value[i] > _max_value[i]) {
_reverse_output_mask |= 1 << i;
uint16_t tmp = _min_value[i];
_min_value[i] = _max_value[i];
_max_value[i] = tmp;
}
if (_param_handles[i].failsafe != PARAM_INVALID && param_get(_param_handles[i].failsafe, &val) == 0) {
_failsafe_value[i] = val;
}
}
if (_use_dynamic_mixing) {
_param_mot_ordering.set(0); // not used with dynamic mixing
bool function_changed = false;
_reverse_output_mask = 0;
for (unsigned i = 0; i < _max_num_outputs; i++) {
int32_t val;
@ -207,29 +237,6 @@ void MixingOutput::updateParams()
// we set _function_assignment[i] later to ensure _functions[i] is updated at the same time
}
if (_param_handles[i].disarmed != PARAM_INVALID && param_get(_param_handles[i].disarmed, &val) == 0) {
_disarmed_value[i] = val;
}
if (_param_handles[i].min != PARAM_INVALID && param_get(_param_handles[i].min, &val) == 0) {
_min_value[i] = val;
}
if (_param_handles[i].max != PARAM_INVALID && param_get(_param_handles[i].max, &val) == 0) {
_max_value[i] = val;
}
if (_min_value[i] > _max_value[i]) {
_reverse_output_mask |= 1 << i;
uint16_t tmp = _min_value[i];
_min_value[i] = _max_value[i];
_max_value[i] = tmp;
}
if (_param_handles[i].failsafe != PARAM_INVALID && param_get(_param_handles[i].failsafe, &val) == 0) {
_failsafe_value[i] = val;
}
}
if (function_changed) {

View File

@ -155,29 +155,6 @@ bool param_modify_on_import(bson_node_t node)
}
}
// 2021-01-31 (v1.12 alpha): translate PWM_MIN/PWM_MAX/PWM_DISARMED to PWM_MAIN
{
if (strcmp("PWM_MIN", node->name) == 0) {
strcpy(node->name, "PWM_MAIN_MIN");
PX4_INFO("copying %s -> %s", "PWM_MIN", "PWM_MAIN_MIN");
}
if (strcmp("PWM_MAX", node->name) == 0) {
strcpy(node->name, "PWM_MAIN_MAX");
PX4_INFO("copying %s -> %s", "PWM_MAX", "PWM_MAIN_MAX");
}
if (strcmp("PWM_RATE", node->name) == 0) {
strcpy(node->name, "PWM_MAIN_RATE");
PX4_INFO("copying %s -> %s", "PWM_RATE", "PWM_MAIN_RATE");
}
if (strcmp("PWM_DISARMED", node->name) == 0) {
strcpy(node->name, "PWM_MAIN_DISARM");
PX4_INFO("copying %s -> %s", "PWM_DISARMED", "PWM_MAIN_DISARM");
}
}
// 2021-04-30: translate ASPD_STALL to FW_AIRSPD_STALL
{
if (strcmp("ASPD_STALL", node->name) == 0) {

View File

@ -29,40 +29,6 @@ parameters:
max: 2000
default: 50
PWM_AUX_MIN:
description:
short: PWM aux minimum value
long: |
Set to 1000 for industry default or 900 to increase servo travel.
type: int32
unit: us
min: 800
max: 1400
default: 1000
PWM_AUX_MAX:
description:
short: PWM aux maximum value
long: |
Set to 2000 for industry default or 2100 to increase servo travel.
type: int32
unit: us
min: 1600
max: 2200
default: 2000
PWM_AUX_DISARM:
description:
short: PWM aux disarmed value
long: |
This is the PWM pulse the autopilot is outputting if not armed.
The main use of this parameter is to silence ESCs when they are disarmed.
type: int32
unit: us
min: 0
max: 2200
default: 1500
PWM_AUX_TRIM${i}:
description:
short: PWM aux ${i} trim value
@ -75,27 +41,3 @@ parameters:
num_instances: *max_num_config_instances
instance_start: 1
default: 0
PWM_AUX_REV${i}:
description:
short: PWM aux ${i} reverse value
long: |
Enable to invert the channel.
Warning: Use this parameter when connected to a servo only.
For a brushless motor, invert manually two phases to reverse the direction.
type: boolean
num_instances: *max_num_config_instances
instance_start: 1
default: 0
PWM_AUX_RATE${i}:
description:
short: PWM aux ${i} rate
long: |
Set the default PWM output frequency for the aux outputs
type: int32
unit: Hz
min: 0
max: 400
instance_start: 1
default: 50

View File

@ -121,27 +121,3 @@ parameters:
num_instances: *max_num_config_instances
instance_start: 1
default: 0
PWM_EXTRA_REV${i}:
description:
short: PWM extra ${i} reverse value
long: |
Enable to invert the channel.
Warning: Use this parameter when connected to a servo only.
For a brushless motor, invert manually two phases to reverse the direction.
type: boolean
num_instances: *max_num_config_instances
instance_start: 1
default: 0
PWM_EXTRA_RATE${i}:
description:
short: PWM extra ${i} rate
long: |
Set the default PWM output frequency for the main outputs
type: int32
unit: Hz
min: 0
max: 400
instance_start: 1
default: 50

View File

@ -29,40 +29,6 @@ parameters:
max: 2000
default: 400
PWM_MAIN_MIN:
description:
short: PWM main minimum value
long: |
Set to 1000 for industry default or 900 to increase servo travel.
type: int32
unit: us
min: 800
max: 1400
default: 1000
PWM_MAIN_MAX:
description:
short: PWM main maximum value
long: |
Set to 2000 for industry default or 2100 to increase servo travel.
type: int32
unit: us
min: 1600
max: 2200
default: 2000
PWM_MAIN_DISARM:
description:
short: PWM main disarmed value
long: |
This is the PWM pulse the autopilot is outputting if not armed.
The main use of this parameter is to silence ESCs when they are disarmed.
type: int32
unit: us
min: 0
max: 2200
default: 900
PWM_MAIN_TRIM${i}:
description:
short: PWM main ${i} trim value
@ -75,27 +41,3 @@ parameters:
num_instances: *max_num_config_instances
instance_start: 1
default: 0
PWM_MAIN_REV${i}:
description:
short: PWM main ${i} reverse value
long: |
Enable to invert the channel.
Warning: Use this parameter when connected to a servo only.
For a brushless motor, invert manually two phases to reverse the direction.
type: boolean
num_instances: *max_num_config_instances
instance_start: 1
default: 0
PWM_MAIN_RATE${i}:
description:
short: PWM main ${i} rate
long: |
Set the default PWM output frequency for the main outputs
type: int32
unit: Hz
min: 0
max: 400
instance_start: 1
default: 50

View File

@ -2036,13 +2036,6 @@ Commander::run()
_status_flags.vtol_transition_failure = _vtol_status.vtol_transition_failsafe;
_status_changed = true;
}
const bool should_soft_stop = (_status.vehicle_type != vehicle_status_s::VEHICLE_TYPE_ROTARY_WING);
if (_armed.soft_stop != should_soft_stop) {
_armed.soft_stop = should_soft_stop;
_status_changed = true;
}
}
}

View File

@ -192,7 +192,7 @@ registers_set(uint8_t page, uint8_t offset, const uint16_t *values, unsigned num
while ((offset < PX4IO_CONTROL_CHANNELS) && (num_values > 0)) {
/* XXX range-check value? */
if (*values != PWM_IGNORE_THIS_CHANNEL) {
if (*values != UINT16_MAX) {
r_page_direct_pwm[offset] = *values;
}

View File

@ -115,21 +115,10 @@ $ pwm test -c 13 -p 1200
PRINT_MODULE_USAGE_COMMAND_DESCR("disarm", "Disarm output");
PRINT_MODULE_USAGE_COMMAND_DESCR("status", "Print current configuration of all channels");
PRINT_MODULE_USAGE_COMMAND_DESCR("forcefail", "Force Failsafe mode. "
"PWM outputs are set to failsafe values.");
PRINT_MODULE_USAGE_ARG("on|off", "Turn on or off", false);
PRINT_MODULE_USAGE_COMMAND_DESCR("terminatefail", "Enable Termination Failsafe mode. "
"While this is true, "
"any failsafe that occurs will be unrecoverable (even if recovery conditions are met).");
PRINT_MODULE_USAGE_ARG("on|off", "Turn on or off", false);
PRINT_MODULE_USAGE_COMMAND_DESCR("rate", "Configure PWM rates");
PRINT_MODULE_USAGE_PARAM_INT('r', -1, 50, 400, "PWM Rate in Hz (0 = Oneshot, otherwise 50 to 400Hz)", false);
PRINT_MODULE_USAGE_COMMAND_DESCR("oneshot", "Configure Oneshot125 (rate is set to 0)");
PRINT_MODULE_USAGE_COMMAND_DESCR("failsafe", "Set Failsafe PWM value");
PRINT_MODULE_USAGE_COMMAND_DESCR("disarmed", "Set Disarmed PWM value");
PRINT_MODULE_USAGE_COMMAND_DESCR("min", "Set Minimum PWM value");
PRINT_MODULE_USAGE_COMMAND_DESCR("max", "Set Maximum PWM value");
PRINT_MODULE_USAGE_COMMAND_DESCR("test", "Set Output to a specific value until 'q' or 'c' or 'ctrl-c' pressed");
@ -506,113 +495,6 @@ pwm_main(int argc, char *argv[])
return 0;
} else if (!strcmp(command, "disarmed")) {
if (set_mask == 0) {
usage("no channels set");
return 1;
}
if (pwm_value < 0) {
return 0;
}
if (pwm_value == 0) {
PX4_WARN("reading disarmed value of zero, disabling disarmed PWM");
}
struct pwm_output_values pwm_values {};
pwm_values.channel_count = servo_count;
/* first get current state before modifying it */
ret = px4_ioctl(fd, PWM_SERVO_GET_DISARMED_PWM, (long unsigned int)&pwm_values);
if (ret != OK) {
PX4_ERR("failed get disarmed values");
return ret;
}
for (unsigned i = 0; i < servo_count; i++) {
if (set_mask & 1 << i) {
pwm_values.values[i] = pwm_value;
if (print_verbose) {
PX4_INFO("chan %d: disarmed PWM: %d", i + 1, pwm_value);
}
}
}
if (pwm_values.channel_count == 0) {
usage("disarmed: no PWM channels");
return 1;
} else {
ret = px4_ioctl(fd, PWM_SERVO_SET_DISARMED_PWM, (long unsigned int)&pwm_values);
if (ret != OK) {
PX4_ERR("failed setting disarmed values (%d)", ret);
return error_on_warn;
}
}
return 0;
} else if (!strcmp(command, "failsafe")) {
if (set_mask == 0) {
usage("no channels set");
return 1;
}
if (pwm_value < 0) {
return 0;
}
if (pwm_value == 0) {
usage("failsafe: no PWM provided");
return 1;
}
struct pwm_output_values pwm_values {};
pwm_values.channel_count = servo_count;
/* first get current state before modifying it */
ret = px4_ioctl(fd, PWM_SERVO_GET_FAILSAFE_PWM, (long unsigned int)&pwm_values);
if (ret != OK) {
PX4_ERR("failed get failsafe values");
return 1;
}
for (unsigned i = 0; i < servo_count; i++) {
if (set_mask & 1 << i) {
pwm_values.values[i] = pwm_value;
if (print_verbose) {
PX4_INFO("Channel %d: failsafe PWM: %d", i + 1, pwm_value);
}
}
}
if (pwm_values.channel_count == 0) {
usage("failsafe: no PWM channels");
return 1;
} else {
ret = px4_ioctl(fd, PWM_SERVO_SET_FAILSAFE_PWM, (long unsigned int)&pwm_values);
if (ret != OK) {
PX4_ERR("BAD input VAL");
return 1;
}
}
return 0;
} else if (!strcmp(command, "test")) {
if (set_mask == 0) {
@ -968,54 +850,6 @@ err_out_no_test:
}
}
return 0;
} else if (!strcmp(command, "forcefail")) {
if (argc < 3) {
PX4_ERR("arg missing [on|off]");
return 1;
} else {
if (!strcmp(argv[2], "on")) {
/* force failsafe */
ret = px4_ioctl(fd, PWM_SERVO_SET_FORCE_FAILSAFE, 1);
} else {
/* disable failsafe */
ret = px4_ioctl(fd, PWM_SERVO_SET_FORCE_FAILSAFE, 0);
}
if (ret != OK) {
PX4_ERR("FAILED setting forcefail %s", argv[2]);
}
}
return 0;
} else if (!strcmp(command, "terminatefail")) {
if (argc < 3) {
PX4_ERR("arg missing [on|off]");
return 1;
} else {
if (!strcmp(argv[2], "on")) {
/* force failsafe */
ret = px4_ioctl(fd, PWM_SERVO_SET_TERMINATION_FAILSAFE, 1);
} else {
/* disable failsafe */
ret = px4_ioctl(fd, PWM_SERVO_SET_TERMINATION_FAILSAFE, 0);
}
if (ret != OK) {
PX4_ERR("FAILED setting termination failsafe %s", argv[2]);
}
}
return 0;
}

View File

@ -128,7 +128,7 @@ int test_ppm_loopback(int argc, char *argv[])
pwm_out.channel_count++;
}
result = ioctl(servo_fd, PWM_SERVO_SET_DISARMED_PWM, (long unsigned int)&pwm_out);
//result = ioctl(servo_fd, PWM_SERVO_SET_DISARMED_PWM, (long unsigned int)&pwm_out);
/* give driver 10 ms to propagate */