diff --git a/docs/assets/config/actuators/trim_GS.png b/docs/assets/config/actuators/trim_GS.png new file mode 100644 index 0000000000..1d1dcdc5b5 Binary files /dev/null and b/docs/assets/config/actuators/trim_GS.png differ diff --git a/docs/en/config/actuators.md b/docs/en/config/actuators.md index 448783cc33..222860bc7e 100644 --- a/docs/en/config/actuators.md +++ b/docs/en/config/actuators.md @@ -535,7 +535,27 @@ If you're using PWM servos, PWM50 is far more common. If a high rate servo is _really_ needed, DShot offers better value. ::: -#### Control surfaces that move both directions about a neutral point +##### PWM: Control surfaces that move both directions about a neutral point + +To facilitate setting the neutral point of the servos, a bilinear curve function can be defined using the following parameters `PWM_MAIM_TRIMx` / `PWM_AUX_TRIMx` for each servo. This allows for unequal deflections in the positive and negative direction: +![Asymetric Servo Deflections](../../assets/config/actuators/servo_pwm_trim.png) + +To set this up: + +1. Set all surface `Trim` to `0.00` for all surfaces: + + ![PWM Trimming](../../assets/config/actuators/trim_GS.png) + +1. Set the `PWM_MAIN_TRIMx` / `PWM_AUX_TRIMx` value so that the surface will stay at the neutral position. +This is usually around `1500` for PWM servos (near the center of the servo range). + +![Control Surface Trimming](../../assets/config/actuators/control_surface_trim.png) + +2. Gradualy increase the `Maximum` for each servo, while checking the deflection with the sliders or manual input with [`COM_PREARM_MODE`](../advanced_config/parameter_reference.md#COM_PREARM_MODE) parameter to `Always` until the desired deflection is reached. +3. Gradualy decrease the `Minimum` for each servo, until the desired deflection is reached. +4. Set `Disarmed` value to the desired value. It is usually desirable to have it the same as the `Trim` value. + +#### Non-PWM: Control surfaces that move both directions about a neutral point Control surfaces that move either direction around a neutral point include: ailerons, elevons, V-tails, A-tails, and rudders. @@ -575,27 +595,7 @@ Another way to test without using the sliders would be to set the [`COM_PREARM_M ::: -##### Split Servo Deflections -::: info -This method is experimental, but much faster. - -::: -To facilitate setting the neutral point of the servos, a bilinear curve function can be defined using the following parameters `PWM_MAIM_TRIMx` / `PWM_AUX_TRIMx` for each servo. This allows for unequal deflections in the positive and negative direction: -![Split Servo Deflections](../../assets/config/actuators/servo_pwm_trim.png) - -To set this up: - -1. Set all surface `Trim` to `0.00` for all surfaces: - - ![Control Surface Trimming](../../assets/config/actuators/control_surface_trim.png) - -1. Set `Minimum`, `Maximum`, `Trim` and `Disarm` value so that the surface will stay at neutral position approximately. -This is usually around `1500` for PWM servos (near the centre of the servo range). - -2. Gradualy increase the `Maximum` for each servo, while checking the deflection with the sliders or manual input with [`COM_PREARM_MODE`](../advanced_config/parameter_reference.md#COM_PREARM_MODE) parameter to `Always` until the desired deflection is reached. -3. Gradualy decrease the `Minimum` for each servo, until the desired deflection is reached. -4. Set `PWM_MAIN_TRIMx` / `PWM_AUX_TRIMx` to the neutral point of each servo. #### Control surfaces that move from neutral to full deflection @@ -616,6 +616,7 @@ One approach for setting these up is: - If the value was increased towards `Max`, then set `Max` to match `Disarmed`. 4. The value that you did _not_ set to match `Disarmed` controls the maximum amount that the control surface can extend. Set the slider to the top of the control, then change the value (`Max` or `Min`) so that the control surface is fully extended when the slider is at top. +5. (Only PWM servos) Set the `Trim` value to the middle between `Min` and `Max`. ::: info Special note for flaps In some vehicle builds, flaps may be configured such that both flaps are controlled from a single output. diff --git a/src/lib/mixer_module/mixer_module.cpp b/src/lib/mixer_module/mixer_module.cpp index a375704b18..b7784f7377 100644 --- a/src/lib/mixer_module/mixer_module.cpp +++ b/src/lib/mixer_module/mixer_module.cpp @@ -548,7 +548,8 @@ uint16_t MixingOutput::output_limit_calc_single(int i, float value) const float output = _disarmed_value[i]; if (_function_assignment[i] >= OutputFunction::Servo1 - && _function_assignment[i] <= OutputFunction::ServoMax) { + && _function_assignment[i] <= OutputFunction::ServoMax + && _param_handles[i].trim != PARAM_INVALID) { /* bi-linear interpolation */ if (value < 0.0f) { diff --git a/src/modules/control_allocator/VehicleActuatorEffectiveness/ActuatorEffectivenessControlSurfaces.cpp b/src/modules/control_allocator/VehicleActuatorEffectiveness/ActuatorEffectivenessControlSurfaces.cpp index 46fea5f33e..8a8359667b 100644 --- a/src/modules/control_allocator/VehicleActuatorEffectiveness/ActuatorEffectivenessControlSurfaces.cpp +++ b/src/modules/control_allocator/VehicleActuatorEffectiveness/ActuatorEffectivenessControlSurfaces.cpp @@ -74,6 +74,27 @@ void ActuatorEffectivenessControlSurfaces::updateParams() return; } + // Helper to check if a PWM trim parameter is set to non-default value (1500 µs) + auto check_pwm_trim = [](const char *prefix, int channel) -> bool { + char param_name[20]; + snprintf(param_name, sizeof(param_name), "%s_TRIM%d", prefix, channel); + param_t param = param_find(param_name); + + if (param != PARAM_INVALID) { + int32_t value; + return (param_get(param, &value) == PX4_OK && value != 1500); + } + + return false; + }; + + // Check if any PWM_MAIN or PWM_AUX trim is configured + bool pwm_trim_set = false; + + for (int i = 1; i <= 8 && !pwm_trim_set; i++) { + pwm_trim_set = check_pwm_trim("PWM_MAIN", i) || check_pwm_trim("PWM_AUX", i); + } + for (int i = 0; i < _count; i++) { param_get(_param_handles[i].type, (int32_t *)&_params[i].type); @@ -84,6 +105,16 @@ void ActuatorEffectivenessControlSurfaces::updateParams() } param_get(_param_handles[i].trim, &_params[i].trim); + + // If PWM trim is set and CA_SV_CS trim is non-zero, warn and reset to 0 + if (pwm_trim_set && fabsf(_params[i].trim) > 0.001f) { + PX4_WARN("CA_SV_CS%d_TRIM (%.3f) should be 0 when PWM TRIM is used. Resetting to 0.", + i, (double)_params[i].trim); + _params[i].trim = 0.0f; + // Update the parameter storage + param_set(_param_handles[i].trim, &_params[i].trim); + } + param_get(_param_handles[i].scale_flap, &_params[i].scale_flap); param_get(_param_handles[i].scale_spoiler, &_params[i].scale_spoiler); diff --git a/src/modules/control_allocator/module.yaml b/src/modules/control_allocator/module.yaml index 99d0d5ed85..4dffb7649f 100644 --- a/src/modules/control_allocator/module.yaml +++ b/src/modules/control_allocator/module.yaml @@ -312,7 +312,11 @@ parameters: CA_SV_CS${i}_TRIM: description: short: Control Surface ${i} trim - long: Can be used to add an offset to the servo control. + long: | + Can be used to add an offset to the servo control. + + NOTE: Do not use for PWM servos. Use the PWM TRIM parameters instead (e.g., PWM_MAIN_TRIM, PWM_AUX_TRIM) instead. + This parameter can only be set if all PWM Trim parameters are set to default. type: float decimal: 2 min: -1.0