PID controllers with large and unpredictable anomalies

Short question
Is there a general way to handle very large anomalies (in order of magnitude) within a homogeneous control area?

Background
I am working on a control algorithm that drives the engine in a usually uniform control area. With minimal load, the PID controller works fine (fast response, little happens). The problem I am facing will be, as a rule, at least one place with a high load. The position is determined by the user during installation, so there is no reasonable way to know when / where to expect it.

When I configure the PID to handle a high-load location, it causes large shoots in unloaded areas (which I fully expected). While everything is in order to overshoot the average stroke, there are no mechanical hard stops on the case. The absence of hard stops means that any significant excess can cause the control lever to be disconnected from the engine (which will give a dead unit).

Things I prototype

  • Nested PIDs (very aggressive when they are far from the target, conservative when near)
  • Fixed gain when it is far, PID when closing
  • Conservative PID (works without load) + an external control that looks for PID to stop and apply additional energy until a goal is reached or a rate of change is detected (i.e., exit from a heavy load area)

Hardware limitations

  • Full movement detected
  • Hardstops cannot be added (currently)

Update
My answer does not indicate that this is the best solution. This is just my current solution, which I thought I would share.

+4
source share
1 answer

Original solution

stalled_pwm_output = PWM / | ΔE |

PWM = maximum PWM value
ΔE = last_error - new_error

The initial relationship successfully increases the PWM output based on the absence of changes in the engine. See graph for sample output.

This approach does, because for a situation where a non-aggressive PID has stopped. However, it has a sad (and obvious) problem: when a non-aggressive PID is able to reach a given value and tries to slow down, stalled_pwm_output grows. This increase leads to a large overshoot when moving to an unloaded position.

1 / ΔE vs ΔE

Current solution

Theory

stalled_pwm_output = (kE * PID_PWM) / | ΔE |

kE = scaling constant
PID_PWM = current PWM request from non-aggressive PID
ΔE = last_error - new_error

My current relationship still uses the 1 / ΔE concept, but uses the non-aggressive PWM PID pin to determine stall_pwm_output. This allows the PID to throttle back to stall_pwm_output when it begins to approach the target, but allows 100% PWM output when stopped. The scaling constant kE is necessary to ensure that the PWM reaches its saturation point (above 10,000 in the graphs below).

Pseudo code

Note that the result from cal_stall_pwm is added to the PID PWM pin in my current control logic.

int calc_stall_pwm(int pid_pwm, int new_error) { int ret = 0; int dE = 0; static int last_error = 0; const int kE = 1; // Allow the stall_control until the setpoint is achived if( FALSE == motor_has_reached_target()) { // Determine the error delta dE = abs(last_error - new_error); last_error = new_error; // Protect from divide by zeros dE = (dE == 0) ? 1 : dE; // Determine the stall_pwm_output ret = (kE * pid_pwm) / dE; } return ret; } 

Output

Slow PWM Output Stalled PWM Output

Please note that when the PWM output schedule is disabled, the sudden drop in PWM by ~ 3400 is a built-in safety function activated because the engine could not reach the position within the set time.

No load output PWM No-Load PWM Output

0
source

All Articles