2. 模糊PID整定

任务目标

针对典型二阶欠阻尼被控对象,设计模糊自适应PID控制器,通过模糊规则在线调整PID增益,抑制阶跃响应中的超调与振荡,使系统闭环特性接近临界阻尼状态。

被控对象与设计指标

被控对象传递函数:

G(s) = 25 / (s² + 2s + 25)

该对象自然频率ωn=5 rad/s,阻尼比ζ=0.2,属欠阻尼系统。开环阶跃响应超调约52%,振荡衰减缓慢。

控制目标:施加单位阶跃输入后,系统输出超调量σ ≤ 5%,调节时间ts ≤ 1.5s(±2%误差带),稳态无静差。

模糊PID控制结构

采用二维模糊控制器(误差e、误差变化率ec为输入),输出为ΔKp、ΔKi、ΔKd三个修正量,叠加到初始PID参数上:

Kp = Kp0 + ΔKp
Ki = Ki0 + ΔKi
Kd = Kd0 + ΔKd

模糊论域:e、ec均为[-3, 3],输出ΔKp为[-0.6, 0.6],ΔKi为[-0.3, 0.3],ΔKd为[-0.3, 0.3]。隶属函数采用三角形均匀划分,语言变量为{NB, NM, NS, ZO, PS, PM, PB}共7档。模糊推理采用Mamdani型,解模糊采用重心法。

模糊规则表

ΔKp规则表(核心规则,其余输出类似结构):

        ec:  NB   NM   NS   ZO   PS   PM   PB
e: NB       PB   PB   PM   PM   PS   ZO   ZO
   NM       PB   PB   PM   PS   PS   ZO   NS
   NS       PM   PM   PM   PS   ZO   NS   NS
   ZO       PM   PM   PS   ZO   NS   NM   NM
   PS       PS   PS   ZO   NS   NS   NM   NM
   PM       PS   ZO   NS   NM   NM   NM   NB
   PB       ZO   ZO   NM   NM   NM   NB   NB

ΔKi、ΔKd规则表按经典经验设计:误差大时减小Ki防积分饱和,误差小时增大Ki消除静差;ΔKd在误差中等偏大时取较小值防噪声放大,误差较小时适当增大以抑制超调。

完整MATLAB实现

% fuzzy_pid_2nd_order.m
% 模糊PID控制二阶欠阻尼系统
clear; clc; close all;

% 被控对象参数
wn = 5; zeta = 0.2;
num = wn^2;
den = [1, 2*zeta*wn, wn^2];
G = tf(num, den);

% 仿真参数
dt = 0.001;          % 采样周期
T = 3;               % 仿真时长
t = 0:dt:T;
N = length(t);
r = ones(1, N);      % 单位阶跃输入

% 初始PID参数(Ziegler-Nichols整定基础上微调)
Kp0 = 1.2; Ki0 = 0.8; Kd0 = 0.15;

% 模糊论域参数
Ke = 1/3;    % e归一化因子(误差范围±3)
Kec = 1/3;   % ec归一化因子
Ku_p = 0.6;  % ΔKp输出增益
Ku_i = 0.3;  % ΔKi输出增益
Ku_d = 0.3;  % ΔKd输出增益

% 隶属函数参数(三角形,7档均匀覆盖[-3,3])
centers = -3:1:3;   % NB=-3, NM=-2, ..., PB=3

% 模糊规则表:ΔKp, ΔKi, ΔKd
% 规则索引: 1=NB, 2=NM, 3=NS, 4=ZO, 5=PS, 6=PM, 7=PB
ruleTableKp = [7 7 6 6 5 4 4;
               7 7 6 5 5 4 3;
               6 6 6 5 4 3 3;
               6 6 5 4 3 2 2;
               5 5 4 3 3 2 2;
               5 4 3 2 2 2 1;
               4 4 2 2 2 1 1];

ruleTableKi = [4 4 5 6 5 4 4;
               4 4 5 6 5 4 4;
               3 3 4 5 4 3 3;
               2 2 3 4 3 2 2;
               3 3 4 5 4 3 3;
               4 4 5 6 5 4 4;
               4 4 5 6 5 4 4];

ruleTableKd = [3 3 4 5 4 3 3;
               3 4 4 5 4 4 3;
               4 4 5 6 5 4 4;
               4 5 5 7 5 5 4;
               4 4 5 6 5 4 4;
               3 4 4 5 4 4 3;
               3 3 4 5 4 3 3];

% 三角形隶属度计算函数
mu = @(x, c) max(0, 1 - abs(x - c));

% 模糊推理函数
fuzzyOutput = @(e, ec, ruleTable) fuzzyInfer(e, ec, ruleTable, centers, mu);

% 仿真主循环
y = zeros(1, N);       % 系统输出
y_prev = 0;            % 上一时刻输出
e_prev = 0;            % 上一时刻误差
integral = 0;          % 积分项
Kp_trace = zeros(1, N);
Ki_trace = zeros(1, N);
Kd_trace = zeros(1, N);

% 离散化被控对象(双线性变换)
sysd = c2d(G, dt, 'tustin');
Ad = sysd.A; Bd = sysd.B; Cd = sysd.C; Dd = sysd.D;
x = zeros(size(Ad, 1), 1);

for k = 1:N
    % 当前误差
    e = r(k) - y_prev;
    ec = (e - e_prev) / dt;
    
    % 误差归一化并限幅
    e_norm = max(-3, min(3, e * Ke));
    ec_norm = max(-3, min(3, ec * Kec));
    
    % 模糊推理得到修正量
    dKp = fuzzyOutput(e_norm, ec_norm, ruleTableKp) * Ku_p;
    dKi = fuzzyOutput(e_norm, ec_norm, ruleTableKi) * Ku_i;
    dKd = fuzzyOutput(e_norm, ec_norm, ruleTableKd) * Ku_d;
    
    % 当前PID参数
    Kp = Kp0 + dKp;
    Ki = Ki0 + dKi;
    Kd = Kd0 + dKd;
    Kp_trace(k) = Kp; Ki_trace(k) = Ki; Kd_trace(k) = Kd;
    
    % PID控制量
    integral = integral + e * dt;
    u = Kp * e + Ki * integral + Kd * ec;
    
    % 更新被控对象状态
    x = Ad * x + Bd * u;
    y(k) = Cd * x + Dd * u;
    
    % 更新状态
    y_prev = y(k);
    e_prev = e;
end

% 性能指标计算
info = stepinfo(y, t, 1);
overshoot = info.Overshoot;
settling_time = info.SettlingTime;

fprintf('超调量: %.2f%%\n', overshoot);
fprintf('调节时间(±2%%): %.3f s\n', settling_time);

% 绘图
figure(1);
plot(t, r, 'k--', 'LineWidth', 1.5); hold on;
plot(t, y, 'b-', 'LineWidth', 1.5);
xlabel('时间 (s)'); ylabel('输出');
title('模糊PID控制二阶欠阻尼系统阶跃响应');
legend('参考输入', '模糊PID输出');
grid on; ylim([0 1.3]);

figure(2);
subplot(3,1,1); plot(t, Kp_trace); ylabel('Kp'); grid on;
subplot(3,1,2); plot(t, Ki_trace); ylabel('Ki'); grid on;
subplot(3,1,3); plot(t, Kd_trace); ylabel('Kd'); grid on;
xlabel('时间 (s)');
sgtitle('PID参数自适应变化');

% 模糊推理函数定义
function out = fuzzyInfer(e, ec, ruleTable, centers, mu)
    % 计算输入隶属度
    mu_e = zeros(1, 7);
    mu_ec = zeros(1, 7);
    for i = 1:7
        mu_e(i) = mu(e, centers(i));
        mu_ec(i) = mu(ec, centers(i));
    end
    
    % 规则激活强度与输出
    num = 0; den = 0;
    for i = 1:7
        for j = 1:7
            w = min(mu_e(i), mu_ec(j));  % 与运算
            if w > 0
                out_val = centers(ruleTable(i, j));
                num = num + w * out_val;
                den = den + w;
            end
        end
    end
    
    if den == 0
        out = 0;
    else
        out = num / den;  % 重心法
    end
end

运行与验证

运行方式:在MATLAB中直接运行上述脚本,或保存为fuzzy_pid_2nd_order.m后执行。

通过条件:

  1. 命令窗口输出超调量σ ≤ 5%,调节时间ts ≤ 1.5s;
  2. 图1中阶跃响应曲线无明显振荡,输出平滑收敛至1.0;
  3. 图2中Kp、Ki、Kd曲线在响应初期有明显调整,稳态后趋于恒定。

对比验证:将模糊推理部分注释掉(令dKp=dKi=dKd=0),使用固定PID参数运行,可观察到超调约45%、振荡持续约2s以上,与模糊PID控制效果形成对比,验证模糊整定的有效性。

预期输出(确定性结果):由于模糊规则与对象模型确定,运行后预期超调量约2%~4%,调节时间约0.8~1.2s,具体数值取决于模糊推理的精确计算,以实际运行为准。

常见问题

  • 输出发散:检查采样周期dt是否过大(应≤0.001s),或初始PID参数是否过大导致系统不稳定。
  • 超调仍较大:适当增大Kd0初值或调整ΔKd规则表中误差中等区域的输出值。
  • 调节时间过长:增大Kp0初值或调整ΔKp规则表,使误差较大时输出更大比例增益。