Set default minimum and maximum PWM for motors

This allows to consistently define:
Motor stopped - disarmed PWM
Motor idling - minimum PWM
Motor at full thrust - maximum PWM

Any allocation can then distinctly decide if
a motor should be running or not depending
on the context and also explicitly command that.
This commit is contained in:
Matthias Grob 2023-04-25 20:21:55 +02:00
parent 21fb22d581
commit 9b092d6d35
7 changed files with 74 additions and 47 deletions

View File

@ -4,7 +4,7 @@ actuator_output:
- param_prefix: PWM_MAIN
channel_label: 'Channel'
standard_params:
disarmed: { min: 800, max: 2200, default: 900 }
disarmed: { min: 800, max: 2200, default: 1000 }
min: { min: 800, max: 1400, default: 1000 }
max: { min: 1600, max: 2200, default: 2000 }
failsafe: { min: 800, max: 2200 }

View File

@ -4,7 +4,7 @@ actuator_output:
- param_prefix: PCA9685
channel_label: 'Channel'
standard_params:
disarmed: { min: 800, max: 2200, default: 900 }
disarmed: { min: 800, max: 2200, default: 1000 }
min: { min: 800, max: 1400, default: 1000 }
max: { min: 1600, max: 2200, default: 2000 }
failsafe: { min: 800, max: 2200 }

View File

@ -218,42 +218,55 @@ void PWMOut::update_params()
updateParams();
// Automatically set the PWM rate and disarmed value when a channel is first set to a servo
// Automatically set PWM configuration when a channel is first assigned
if (!_first_update_cycle) {
for (size_t i = 0; i < _num_outputs; i++) {
if ((previously_set_functions & (1u << i)) == 0 && _mixing_output.functionParamHandle(i) != PARAM_INVALID) {
int32_t output_function;
if (param_get(_mixing_output.functionParamHandle(i), &output_function) == 0
&& output_function >= (int)OutputFunction::Servo1
&& output_function <= (int)OutputFunction::ServoMax) { // Function got set to a servo
int32_t val = 1500;
PX4_INFO("Setting disarmed to %i for channel %i", (int) val, i);
param_set(_mixing_output.disarmedParamHandle(i), &val);
if (param_get(_mixing_output.functionParamHandle(i), &output_function) == 0) {
// Servos need PWM rate 50Hz and disramed value 1500us
if (output_function >= (int)OutputFunction::Servo1
&& output_function <= (int)OutputFunction::ServoMax) { // Function got set to a servo
int32_t val = 1500;
PX4_INFO("Setting channel %i disarmed to %i", (int) val, i);
param_set(_mixing_output.disarmedParamHandle(i), &val);
// If the whole timer group was not set previously, then set the pwm rate to 50 Hz
for (int timer = 0; timer < MAX_IO_TIMERS; ++timer) {
// If the whole timer group was not set previously, then set the pwm rate to 50 Hz
for (int timer = 0; timer < MAX_IO_TIMERS; ++timer) {
uint32_t channels = io_timer_get_group(timer);
uint32_t channels = io_timer_get_group(timer);
if ((channels & (1u << i)) == 0) {
continue;
}
if ((channels & (1u << i)) == 0) {
continue;
}
if ((channels & previously_set_functions) == 0) { // None of the channels was set
char param_name[17];
snprintf(param_name, sizeof(param_name), "%s_TIM%u", _mixing_output.paramPrefix(), timer);
if ((channels & previously_set_functions) == 0) { // None of the channels was set
char param_name[17];
snprintf(param_name, sizeof(param_name), "%s_TIM%u", _mixing_output.paramPrefix(), timer);
int32_t tim_config = 0;
param_t handle = param_find(param_name);
int32_t tim_config = 0;
param_t handle = param_find(param_name);
if (param_get(handle, &tim_config) == 0 && tim_config == 400) {
tim_config = 50;
PX4_INFO("setting timer %i to %i Hz", timer, (int) tim_config);
param_set(handle, &tim_config);
if (param_get(handle, &tim_config) == 0 && tim_config == 400) {
tim_config = 50;
PX4_INFO("setting timer %i to %i Hz", timer, (int) tim_config);
param_set(handle, &tim_config);
}
}
}
}
// Motors need a minimum value that idles the motor and have a deadzone at the top of the range
if (output_function >= (int)OutputFunction::Motor1
&& output_function <= (int)OutputFunction::MotorMax) { // Function got set to a motor
int32_t val = 1100;
PX4_INFO("Setting channel %i minimum to %i", (int) val, i);
param_set(_mixing_output.minParamHandle(i), &val);
val = 1900;
PX4_INFO("Setting channel %i maximum to %i", (int) val, i);
param_set(_mixing_output.maxParamHandle(i), &val);
}
}
}
}

View File

@ -5,7 +5,7 @@ actuator_output:
param_prefix: '${PWM_MAIN_OR_AUX}'
channel_labels: ['${PWM_MAIN_OR_AUX}', '${PWM_MAIN_OR_AUX_CAP}']
standard_params:
disarmed: { min: 800, max: 2200, default: 900 }
disarmed: { min: 800, max: 2200, default: 1000 }
min: { min: 800, max: 1400, default: 1000 }
max: { min: 1600, max: 2200, default: 2000 }
failsafe: { min: 800, max: 2200 }

View File

@ -7,7 +7,7 @@ actuator_output:
channel_label_module_name_prefix: false
timer_config_file: "boards/px4/io-v2/src/timer_config.cpp"
standard_params:
disarmed: { min: 800, max: 2200, default: 900 }
disarmed: { min: 800, max: 2200, default: 1000 }
min: { min: 800, max: 1400, default: 1000 }
max: { min: 1600, max: 2200, default: 2000 }
failsafe: { min: 800, max: 2200 }

View File

@ -702,36 +702,48 @@ void PX4IO::update_params()
if ((previously_set_functions & (1u << i)) == 0 && _mixing_output.functionParamHandle(i) != PARAM_INVALID) {
int32_t output_function;
if (param_get(_mixing_output.functionParamHandle(i), &output_function) == 0
&& output_function >= (int)OutputFunction::Servo1
&& output_function <= (int)OutputFunction::ServoMax) { // Function got set to a servo
int32_t val = 1500;
PX4_INFO("Setting disarmed to %i for channel %i", (int) val, i);
param_set(_mixing_output.disarmedParamHandle(i), &val);
if (param_get(_mixing_output.functionParamHandle(i), &output_function) == 0) {
if (output_function >= (int)OutputFunction::Servo1
&& output_function <= (int)OutputFunction::ServoMax) { // Function got set to a servo
int32_t val = 1500;
PX4_INFO("Setting channel %i disarmed to %i", (int) val, i);
param_set(_mixing_output.disarmedParamHandle(i), &val);
// If the whole timer group was not set previously, then set the pwm rate to 50 Hz
for (int timer = 0; timer < (int)(sizeof(_group_channels) / sizeof(_group_channels[0])); ++timer) {
// If the whole timer group was not set previously, then set the pwm rate to 50 Hz
for (int timer = 0; timer < (int)(sizeof(_group_channels) / sizeof(_group_channels[0])); ++timer) {
uint32_t channels = _group_channels[timer];
uint32_t channels = _group_channels[timer];
if ((channels & (1u << i)) == 0) {
continue;
}
if ((channels & (1u << i)) == 0) {
continue;
}
if ((channels & previously_set_functions) == 0) { // None of the channels was set
char param_name[17];
snprintf(param_name, sizeof(param_name), "%s_TIM%u", _mixing_output.paramPrefix(), timer);
if ((channels & previously_set_functions) == 0) { // None of the channels was set
char param_name[17];
snprintf(param_name, sizeof(param_name), "%s_TIM%u", _mixing_output.paramPrefix(), timer);
int32_t tim_config = 0;
param_t handle = param_find(param_name);
int32_t tim_config = 0;
param_t handle = param_find(param_name);
if (param_get(handle, &tim_config) == 0 && tim_config == 400) {
tim_config = 50;
PX4_INFO("setting timer %i to %i Hz", timer, (int) tim_config);
param_set(handle, &tim_config);
if (param_get(handle, &tim_config) == 0 && tim_config == 400) {
tim_config = 50;
PX4_INFO("setting timer %i to %i Hz", timer, (int) tim_config);
param_set(handle, &tim_config);
}
}
}
}
// Motors need a minimum value that idles the motor
if (output_function >= (int)OutputFunction::Motor1
&& output_function <= (int)OutputFunction::MotorMax) { // Function got set to a motor
int32_t val = 1100;
PX4_INFO("Setting channel %i minimum to %i", (int) val, i);
param_set(_mixing_output.minParamHandle(i), &val);
val = 1900;
PX4_INFO("Setting channel %i maximum to %i", (int) val, i);
param_set(_mixing_output.maxParamHandle(i), &val);
}
}
}
}

View File

@ -179,6 +179,8 @@ public:
param_t functionParamHandle(int index) const { return _param_handles[index].function; }
param_t disarmedParamHandle(int index) const { return _param_handles[index].disarmed; }
param_t minParamHandle(int index) const { return _param_handles[index].min; }
param_t maxParamHandle(int index) const { return _param_handles[index].max; }
/**
* Returns the actual failsafe value taking into account the assigned function