理论部分参考:https://blog.csdn.net/foxclever/article/details/80633275
这里附上写的matlab程序:
clear all;
close all;
%获取控制对象离散化模型
ts = 20; %采样时间
sys = tf([1],[60,1],'inputdelay',80);
dsys = c2d(sys,ts,'zoh');
[num,den]=tfdata(dsys,'v');
%获取滤波器离散化模型(这里的滤波器模型是微分模型*积分模型的模型)
sys1=tf([14/0.36,1],[14/0.36*0.5,1]); %滤波器模型
dsys1 = c2d(sys1,ts,'tucsin');%模型离散化
[num1,den1]=tfdata(dsys1,'v');
d_filter_out_1=0;
d_filter_input_1=0;%滤波器上一时刻输入
%设置pid参数
k_p=0.36;
k_i=0.0021;
k_d=14;
gama=0.5;
td=k_d/k_p;
c1=gama*td/(gama*td+ts);
c2=(td+ts)/(gama*td+ts);
c3=td/(gama*td+ts);
%设置输入信号形式
%y_d = ones(1,100); %输入信号为阶跃信号
%y_d = [ones(1,250) zeros(1,250)]; 输入信号为阶跃信号
for k=1:1:400%输入信号为正弦信号
y_d(k) = 1.0*sign(sin(0.00025*2*pi*k*ts))+0.05*sin(0.03*pi*k*ts);
end
y = zeros(1,400);%初始化输出信号
y_feed=zeros(1,400);%反馈回来的信号,y_feed=y
d_filter_out=zeros(1,400);%经过滤波器后的输出
erro = zeros(1,400);%信号差值
erro_1 = 0;
erro_total = 0;%信号差值累计值
y_1=0;%上一时刻的输出
y_2=0;%上一上一时刻的输出
y_3=0;%上一上一上一时刻的输出
pi_out=0; %pid控制器的输出,注意不是系统输出
pi_out_1=0;%上一时刻pid控制器的输出,注意不是系统输出
pi_out_2=0;%上一上一时刻pid控制器的输出,注意不是系统输出
pi_out_3=0;%上一上一上一时刻pid控制器的输出,注意不是系统输出
pi_out_4=0;%上一上一上一时刻pid控制器的输出,注意不是系统输出
pi_out_5=0;%上一上一上一时刻pid控制器的输出,注意不是系统输出
% m用来选择是否用不完全篇pid
% m=1:用微分先行pid
% m=2:普通pid
M=input('input the m:');
if M==1
for k=1:1:400
time(k)=k*ts; %存储时间,用于后面画图
y(k) = -den(2)*y_1+num(2)*pi_out_5 ;%控制对象
y_feed(k)=y(k);
erro(k) =y_d(k) - y_feed(k) ;
erro_total = erro_total +erro(k) ;
d_filter_input= y_feed(k);
d_filter_out=c2* d_filter_input-c3*d_filter_input_1;
pi_out = k_p*erro(k) +k_i*erro_total*ts+d_filter_out;
if pi_out>=110
pi_out=110;
end
if pi_out<=-110
pi_out=-110;
end
%更新系统输出状态
y_1=y(k);
%更新pid输出状态
pi_out_5=pi_out_4;
pi_out_4=pi_out_3;
pi_out_3=pi_out_2;
pi_out_2=pi_out_1;
pi_out_1=pi_out;
%更新滤波器的状态
%d_filter_out_1=d_filter_out;
d_filter_input_1= d_filter_input;
end
%画图
plot(time,y_d,'r',time,y_feed,'k:','linewidth',2);
xlabel('time');
ylabel('y and y_d');
legend('yd','y');
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if M==2
for k=1:1:400
time(k)=k*ts; %存储时间,用于后面画图
y(k) = -den(2)*y_1+num(2)*pi_out_5 ;%控制对象
y_feed(k)=y(k);
erro(k) =y_d(k) - y_feed(k) ;
erro_total = erro_total +erro(k) ;
pi_out = k_p*erro(k) +k_i*erro_total*ts+k_d*(erro(k)-erro_1)/ts;
if pi_out>=110
pi_out=110;
end
if pi_out<=-110
pi_out=-110;
end
%更新系统输出状态
y_1=y(k);
erro_1= erro(k);
%更新pid输出状态
pi_out_5=pi_out_4;
pi_out_4=pi_out_3;
pi_out_3=pi_out_2;
pi_out_2=pi_out_1;
pi_out_1=pi_out;
end
%画图
plot(time,y_d,'r',time,y_feed,'k:','linewidth',2);
xlabel('time');
ylabel('y and y_d');
legend('yd','y');
end
结果:
但是目前仍存在疑问:
根据推导的微分的模型:d_filter_out=c1*d_filter_out_1+c2* d_filter_input-c3*d_filter_input_1;%
应该要在后面对d_filter_out_1进行迭代替换,但是如果替换了会出现明显得震荡,但如果将它永远设为0就不会出现。在查阅很多别人的代码时也发现别人也没有对他进行迭代替换??