Pular para o conteúdo principal

PID com Anti-Windup: Teoria, Ajuste e Validação Experimental

· Leitura de 3 minutos
Oséias D. Farias
Trainee Dev IA · Engenheiro ML · Pesquisador Mestrando @ UFABC & UFPA

O windup integral é um dos modos de falha mais comuns em controladores PID em produção. Este post cobre o problema a partir dos primeiros princípios, deriva o esquema de anti-windup por back-calculation, mostra como o Synapsys o implementa e valida o projeto contra uma planta simulada de segunda ordem.

O problema do windup

Um controlador PID com saturação na saída tem uma interação problemática: quando o atuador está saturado, o integrador continua acumulando erro mesmo que a saída esteja limitada. Quando o sinal do erro se inverte, o integrador leva muito tempo para "desacumular" antes que a saída saia da saturação — causando sobressinal e oscilação.


Anti-windup por back-calculation

O esquema de back-calculation realimenta o erro de saturação para o integrador com ganho 1/Tt1/T_t:

I˙(t)=Kie(t)+1Tt[usat(t)uuns(t)]\dot{I}(t) = K_i \cdot e(t) + \frac{1}{T_t}\bigl[u_{sat}(t) - u_{uns}(t)\bigr]

Quando a saída não está saturada, usat=uunsu_{sat} = u_{uns} e o termo de correção é zero — o integrador se comporta normalmente.

Implementação no Synapsys

from synapsys.algorithms import PID

pid = PID(
Kp = 5.0,
Ki = 2.0,
Kd = 0.1,
dt = 0.01,
u_min = -1.0,
u_max = 1.0,
# anti_windup=True é o padrão
)

u = pid.compute(setpoint=5.0, measurement=y)

Simulação comparativa

import numpy as np
from synapsys.algorithms import PID
from synapsys.api import ss, c2d

planta = c2d(ss([[-0.5]], [[1]], [[1]], [[0]]), dt=0.01)

def rodar_sim(anti_windup: bool, n_passos: int = 800):
pid = PID(Kp=5.0, Ki=2.0, Kd=0.05, dt=0.01,
u_min=-1.0, u_max=1.0, anti_windup=anti_windup)
x = np.zeros(1)
ys = []
for i in range(n_passos):
setpoint = 3.0 if i < 400 else -3.0
y = float(x[0])
u = np.array([pid.compute(setpoint, y)])
x, _ = planta.evolve(x, u)
ys.append(y)
return np.array(ys)

y_sem = rodar_sim(anti_windup=False)
y_com = rodar_sim(anti_windup=True)

Diretrizes de ajuste para pesquisa

ParâmetroEfeitoPonto de partida
KpK_pVelocidade de respostaFOPDT: Kp=0,6/(Kplantaτ)K_p = 0,6 / (K_{planta} \cdot \tau)
Ki=Kp/TiK_i = K_p / T_iEliminação de erro em regime permanenteTi=2τT_i = 2\tau
Kd=KpTdK_d = K_p \cdot T_dAmortecimento, amplificação de ruídoTd=τ/4T_d = \tau / 4
umin,umaxu_{min}, u_{max}Limites do atuadorEspecificação física do atuador

Conexão com a literatura

O esquema de back-calculation usado no Synapsys segue Åström & Hägglund (2006) Advanced PID Control, Capítulo 6.

@book{astrom2006advanced,
author = {Åström, Karl Johan and Hägglund, Tore},
title = {Advanced PID Control},
publisher = {ISA — The Instrumentation, Systems, and Automation Society},
year = {2006},
isbn = {978-1556175169},
}

A referência completa da API está em synapsys.algorithms →.