3. 一阶惯性环节的PID控制整定
任务目标
本案例针对一阶惯性环节对象(含纯滞后),采用Ziegler-Nichols开环阶跃响应整定法获取P、PI、PID三组参数,并在同一仿真中比较三种控制器的阶跃响应性能。
被控对象与整定原理
被控对象传递函数为:
G(s) = K * e^(-L·s) / (T·s + 1)
其中K为静态增益,T为惯性时间常数,L为纯滞后时间。Ziegler-Nichols开环整定法通过施加阶跃输入,从响应曲线提取特征参数:
- 滞后时间L:从阶跃施加到响应开始明显变化的时间
- 等效时间常数T:响应变化至稳态值的63.2%所对应的时间减去L
根据提取的K、T、L查表计算控制器参数:
| 控制器 | Kp | Ti | Td |
|---|---|---|---|
| P | T/(K·L) | — | — |
| PI | 0.9·T/(K·L) | 3·L | — |
| PID | 1.2·T/(K·L) | 2·L | 0.5·L |
仿真实现
采用Python实现,使用numpy进行数值积分(一阶欧拉法),matplotlib绘制对比曲线。仿真过程:
- 对开环对象施加单位阶跃,提取K、T、L特征参数
- 按ZN公式计算P、PI、PID参数
- 分别构建闭环系统(PID控制器+对象),施加单位阶跃设定值,观察响应
import numpy as np
import matplotlib.pyplot as plt
# 被控对象参数
K_obj = 2.0 # 静态增益
T_obj = 5.0 # 惯性时间常数
L_obj = 1.0 # 纯滞后时间
# 仿真参数
dt = 0.01
t_end = 40.0
t = np.arange(0, t_end, dt)
n = len(t)
# 纯滞后用输入延迟实现
delay_steps = int(L_obj / dt)
def plant_step(u, y_prev, u_history):
"""一阶惯性+纯滞后对象,欧拉法递推"""
u_delayed = u_history[-delay_steps] if len(u_history) >= delay_steps else 0.0
dy = (K_obj * u_delayed - y_prev) / T_obj
return y_prev + dy * dt
# 开环阶跃响应提取特征
u_open = np.ones(n)
y_open = np.zeros(n)
u_hist = []
for i in range(1, n):
u_hist.append(u_open[i-1])
y_open[i] = plant_step(u_open[i], y_open[i-1], u_hist)
# 提取特征参数
steady_val = y_open[-1]
K_est = steady_val # 单位阶跃下K=稳态值
# 找响应到达稳态值63.2%的时间点
target = 0.632 * steady_val
t63_idx = np.argmax(y_open >= target)
t63 = t[t63_idx]
# 滞后时间L:从响应开始明显变化(超过2%稳态值)算起
t_start_idx = np.argmax(y_open >= 0.02 * steady_val)
L_est = t[t_start_idx]
# 等效时间常数T:63.2%时间减去滞后时间
T_est = t63 - L_est
print(f"特征提取: K={K_est:.3f}, L={L_est:.3f}s, T={T_est:.3f}s")
# Ziegler-Nichols参数计算
Kp_p = T_est / (K_est * L_est)
Kp_pi = 0.9 * T_est / (K_est * L_est)
Ti_pi = 3 * L_est
Kp_pid = 1.2 * T_est / (K_est * L_est)
Ti_pid = 2 * L_est
Td_pid = 0.5 * L_est
print(f"P: Kp={Kp_p:.3f}")
print(f"PI: Kp={Kp_pi:.3f}, Ti={Ti_pi:.3f}")
print(f"PID: Kp={Kp_pid:.3f}, Ti={Ti_pid:.3f}, Td={Td_pid:.3f}")
# 闭环仿真
def closed_loop(controller_type):
y = np.zeros(n)
e_sum = 0.0
e_prev = 0.0
u = 0.0
u_hist = []
setpoint = 1.0
for i in range(1, n):
# 误差
e = setpoint - y[i-1]
e_sum += e * dt
de = (e - e_prev) / dt
# 控制器输出
if controller_type == 'P':
u = Kp_p * e
elif controller_type == 'PI':
u = Kp_pi * e + (Kp_pi / Ti_pi) * e_sum
elif controller_type == 'PID':
u = Kp_pid * e + (Kp_pid / Ti_pid) * e_sum + Kp_pid * Td_pid * de
# 限幅
u = np.clip(u, -5, 5)
# 对象递推
u_hist.append(u)
y[i] = plant_step(u, y[i-1], u_hist)
e_prev = e
return y
# 运行三种控制器
y_p = closed_loop('P')
y_pi = closed_loop('PI')
y_pid = closed_loop('PID')
# 绘制对比
plt.figure(figsize=(10, 6))
plt.plot(t, y_p, label='P Controller', linewidth=1.5)
plt.plot(t, y_pi, label='PI Controller', linewidth=1.5)
plt.plot(t, y_pid, label='PID Controller', linewidth=1.5)
plt.axhline(y=1.0, color='gray', linestyle='--', alpha=0.5)
plt.xlabel('Time (s)')
plt.ylabel('Output')
plt.title('Step Response Comparison: P vs PI vs PID')
plt.legend()
plt.grid(True, alpha=0.3)
plt.xlim(0, 30)
plt.ylim(0, 1.6)
plt.show()
运行与验证
运行方式:直接执行上述Python脚本(需安装numpy和matplotlib)。
预期输出:
- 控制台打印特征提取结果:K≈2.0,L≈1.0s,T≈5.0s(因采样离散化略有偏差)
- 打印三组控制器参数
- 弹出对比曲线图
通过判定标准:
- 特征提取的K、L、T与设定值误差在5%以内
- P控制器存在稳态误差(输出低于设定值1.0)
- PI控制器稳态误差消除,但超调量大于PID
- PID控制器响应最快,超调量最小(通常约10%~20%),调节时间最短
结果分析要点
- P控制器因无积分作用,对含滞后对象必然存在稳态误差,误差大小与Kp成反比
- PI控制器通过积分消除稳态误差,但积分作用导致超调量增大
- PID控制器引入微分预测,有效抑制超调,综合性能最优
- 若增大L/T比值(滞后占比增加),三种控制器的超调量均会增大,PID优势更明显