¿Debo poner un protector de cuerda en cada término del PID, o solo el I, o tal vez toda la salida?
¿Debo poner un protector de cuerda en cada término del PID, o solo el I, o tal vez toda la salida?
El anti-windup del integrador es una medida que debe tomar debido a la saturación de salida u otros límites en el sistema, y dichos límites son un comportamiento no lineal. Cuando empiezas a hacer un control no lineal, muchas de las cosas agradables, claras y de procedimiento que nos enseñan en las clases de teoría de control de pregrado no se aplican por completo.
En general , debe aplicar anti-windup de integrador solo al término de integrador, aunque es posible que también deba aplicar un límite al término de salida antes de que se aplique a un DAC (asumiendo que está haciendo el trabajo en software). Hay muchas maneras de hacer esto. Mi preferencia es limitar el estado del integrador a ciertos límites por sí mismo:
// (Calculate integrator_state)
if (integrator_state > integrator_max) {integrator_state = integrator_max;}
if (integrator_state < integrator_min) {integrator_state = integrator_min;}
O para calcular una salida candidata, luego recorte el estado del integrador:
output_candidate = integrator_state + error * prop_gain;
if (output_candidate > output_max) {
integrator_state = output_max - error * prop_gain;
} else if (output_candidate < output_min) {
integrator_state = output_min - error * prop_gain;
}
// Re-calculate the actual output, possibly with a D term
El método que menciona @Chu funcionaría, si recuerdas que solo debes aplicarlo cuando el integrador está siendo excedido, no retirado (pero mi primer método es equivalente). Otro método que se usa a menudo es mantener el término del integrador en cero cuando el error es grande, luego permitir la acción del integrador cuando el error está por debajo de algún umbral, o si está haciendo un controlador de movimiento que sabe cuándo comienza un "movimiento" establezca el integrador en cero al comienzo de un movimiento y manténgalo allí durante un tiempo determinado. No soy un gran fanático de ninguno de esos métodos, pero otros sí lo son.
Debido a que se está aventurando en el control no lineal, incluso si está tan lejos en el extremo poco profundo de la piscina, puede acostarse sin ahogarse, hay opciones sobre opciones y no hay una forma correcta de hacerlo. . Además, no puedes encontrar una respuesta mediante el análisis: tienes que implementar el sistema real y darle un giro, o hacer una simulación y probar tu algoritmo con eso.
Por lo general, se hace referencia a la protección contra el viento como el protector del término integral para que no se acumule continuamente. El controlador puede sobrepasar significativamente y continuará sobrepasando con el crecimiento continuo de la integral.
Por lo tanto, la protección contra el viento es solo el término integral. Como este término puede "enrollarse" y seguir creciendo. Pero, la salida de un PID también puede / debería estar limitada en la salida.
Por ejemplo, el siguiente código calcula el término integral y luego lo limita según un valor establecido. También limita la salida del controlador, pero de acuerdo con un término limitador diferente.
void PID_Compute(PID *pid)
{
//Find all error variables
pid->lastError = pid->error;
pid->error = pid->setpoint - pid->input;
pid->derivative = pid->error - pid->lastError;
pid->integral += pid->Ki * pid->error;
//Anti-integral Windup
if(pid->integral > pid->IntegralLimit){
pid->integral = pid->IntegralLimit;
}
else if(pid->integral < -pid->IntegralLimit){
pid->integral = -pid->IntegralLimit;
}
//Calculate PID
pid->output = (pid->Kp*pid->error) + (pid->integral) + (pid->Kd * pid->derivative);
//Set limits
if(pid->output > pid->Outmax){
pid->output = pid->Outmax;
}
else if(pid->output < pid->Outmin){
pid->output = pid->Outmin;
}
}
Para cualquier cosa relacionada con la escritura o la comprensión de un controlador PID, consulte el artículo de Tim Wescott.
Como ya han dicho otros, la conclusión es solo un problema para el término I
.
Donde difiero de casi todo lo que he visto, es que no me gusta limitar arbitrariamente mi I
. Quiero que sea capaz de saturar la salida sin importar lo que se requiera para hacer eso, pero no tiene sentido ir más allá de eso. Así que mis límites son flotantes, según la salida final.
Por lo tanto, utilizo un tipo de datos más grande para mantener la salida de lo que realmente necesito, para poder detectar fuera de rango y ajustarlo. Luego, como parte de esa abrazadera, también desenrollo el I
. Para un proyecto, en realidad calculé lo que debería haber sido saturar exactamente, pero para otro, simplemente conecté una caída exponencial:
I_acc += Error;
//other code here
if (OUTPUT_OUT_OF_RANGE())
{
CLAMP_OUTPUT();
//anti_windup
I_acc -= (I_acc >> 2);
}
Lea otras preguntas en las etiquetas pid-controller