2.4.3 C算法
#include
#include
struct _pid
{
float SetSpeed ; //設(shè)置速度
float ActualSpeed ; //實際速度
float err ; //誤差
float err_last ; //最終誤差
float Kp , Kd , Ki ; //比例系數(shù)
float voltage ; //輸出電壓
float integral ; //積分值
float umax ; //積分上限
float umin ; //積分下限
}pid;
void PID_Init()
{
pid.SetSpeed = 0 ;
pid.ActualSpeed = 0.0 ;
pid.err = 0.0 ;
pid.err_last = 0.0 ;
pid.voltage = 0.0 ;
pid.integral = 0.0 ;
pid.Kp = 0.2 ;
pid.Kd = 0.2 ;
pid.Ki = 0.1 ;
pid.umax = 400 ;
pid.umin = -200 ;
}
float PID_Realize( float Speed )
{
char index ;
pid.SetSpeed = Speed ;
pid.err = pid.SetSpeed-pid.ActualSpeed ;
if( abs(pid.err)<= pid.umax )
{
index = 1 ;
pid.integral += pid.err ;
}
else
index = 0 ;
pid.voltage = pid.Kp*pid.err+index*pid.Ki*pid.integral+pid.Kd*( pid.err-pid.err_last ) ;
pid.err_last = pid.err ;
pid.ActualSpeed = pid.voltage*1.0 ;
return pid.ActualSpeed ;
}
void main()
{
int count ;
count = 0 ;
PID_Init() ;
while( count<1000 )
{
float Speed = PID_Realize( 200.0 ) ;
count ++ ;
printf( "%.2f\\n" , Speed ) ;
}
}
2.5 抗積分飽和型PID算法
2.5.1 實現(xiàn)原理
所謂積分飽和現(xiàn)象是指如果系統(tǒng)存在一個方向的偏差,PID控制器的輸出會因為存在積分環(huán)節(jié)而不斷累積增大,從而導致執(zhí)行機構(gòu)達到極限位置,若控制器輸出響應(yīng)繼續(xù)增大,執(zhí)行器開度不可能再增大,此時計算機輸出控制量超出了正常運行范圍而進入飽和區(qū),一旦系統(tǒng)出現(xiàn)反向偏差,輸出響應(yīng)逐漸從飽和區(qū)退出,進入飽和區(qū)時間越長則退出飽和區(qū)的時間也就隨之增加,這段時間里,執(zhí)行機構(gòu)仍然停留在極限位置而不能隨著偏差方向立即作出相應(yīng)的改變,造成控制性能惡化,這種現(xiàn)象稱為積分飽和現(xiàn)象或積分失控現(xiàn)象。實現(xiàn)抗積分飽和算法的基本思路是計算系統(tǒng)的響應(yīng)時,首先判斷上一時刻的控制量是否超出了極限范圍,如果超過上限,則只累計反向偏差,若低于下限,則只累計正向偏差,從而避免控制量長時間停留在飽和區(qū)。
2.5.2 MATLAB算法
clc
clear
%PID初始化
len = 180 ; %運算次數(shù)
y = zeros(1,len); %期望值
y_d = zeros(1,len); %過程值
err = zeros(1,len); %誤差值
err_0 = 0 ; %k時刻誤差
err_1 = 0 ; %k-1時刻誤差
y_d_last = 0 ; %k-1時刻輸出
integral = 0; %積分值
Kp = 0.2; %比例系數(shù)
Kd = 0.2; %微分值
Ki = 0.1 ; %積分值
max = 400 ; %積分上限
min = -200 ; %積分下限
index = 0 ; %積分有效性
%運算過程
for k=1:1:len
y(k) = 200 ; %期望輸出
err_0 = y(k)-y_d_last; %計算偏差
if y_d_last>max
if abs(err_0) <= y(k)
index = 1 ;
if err_0 < 0
integral = integral+err_0; %誤差累計
end
else
index = 0 ;
end
elseif y_d_last<min
if abs(err_0) <= y(k)
index = 1 ;
if err_0 > 0
integral = integral+err_0; %誤差累計
end
else
index = 0 ;
end
else
if abs(err_0) <= y(k)
index = 1 ;
integral = integral+err_0; %誤差累計
else
index = 0 ;
end
end
y_d_last = Kp*err_0 + Ki*index*integral + Kd*(err_1-err_0); %位置型PID運算公式
err_1 = err_0 ;
%更新參數(shù)
y_d(k) = y_d_last ;
err(k) = err_1 ;
end
%輸出圖像繪制
t = 1:1:len;
subplot( 2, 1, 1 ) ;
plot( t, y, 'r', t, y_d, 'b' );
axis([0 len, 0 1.5*y(1)])
title('輸出曲線');
xlabel('t')
ylabel('y(t)')
%誤差圖像繪制
subplot( 2, 1, 2 ) ;
plot( t, err );
axis([0 len, 0 1.5*y(1)])
title('誤差曲線');
xlabel('t')
ylabel('e(t)')
MATLAB運行結(jié)果如下圖所示。
2.5.3 C算法
#include
#include
struct _pid
{
float SetSpeed ; //設(shè)置速度
float ActualSpeed ; //實際速度
float err ; //誤差
float err_last ; //最終誤差
float Kp , Kd , Ki ; //比例系數(shù)
float voltage ; //輸出電壓
float integral ; //積分值
float umax ; //積分上限
float umin ; //積分下限
}pid;
void PID_Init()
{
pid.SetSpeed = 0 ;
pid.ActualSpeed = 0.0 ;
pid.err = 0.0 ;
pid.err_last = 0.0 ;
pid.voltage = 0.0 ;
pid.integral = 0.0 ;
pid.Kp = 0.2 ;
pid.Kd = 0.2 ;
pid.Ki = 0.1 ;
pid.umax = 400 ;
pid.umin = -200 ;
}
float PID_Realize( float Speed )
{
char index ;
pid.SetSpeed = Speed ;
pid.err = pid.SetSpeed-pid.ActualSpeed ;
if( pid.ActualSpeed>pid.umax )
{
if( abs(pid.err)<=200 )
{
index = 1 ;
if( pid.err<0 )
pid.integral += pid.err ;
}
else
index = 0 ;
}
else if( pid.ActualSpeed
2.6 梯形積分PID算法
2.6.1 實現(xiàn)原理
根據(jù)梯形算法的積分環(huán)節(jié)公式
作為PID控制的積分項,其作用是消除余差,為了盡量減小余差,應(yīng)提高積分項運算精度,為此可以將矩形積分改為梯形積分,具體實現(xiàn)的語句為pid.voltage = pid.Kppid.err+indexpid.Ki pid.integral/2+pid.Kd ( pid.err-pid.err_last ) ;
2.6.2 MATLAB算法
clc
clear
%PID初始化
len = 358 ; %運算次數(shù)
y = zeros(1,len); %期望值
y_d = zeros(1,len); %過程值
err = zeros(1,len); %誤差值
err_0 = 0 ; %k時刻誤差
err_1 = 0 ; %k-1時刻誤差
y_d_last = 0 ; %k-1時刻輸出
integral = 0; %積分值
Kp = 0.2; %比例系數(shù)
Kd = 0.2; %微分值
Ki = 0.1 ; %積分值
max = 400 ; %積分上限
min = -200 ; %積分下限
index = 0 ; %積分有效性
%運算過程
for k=1:1:len
y(k) = 200 ; %期望輸出
err_0 = y(k)-y_d_last; %計算偏差
if y_d_last>max
if abs(err_0) <= y(k)
index = 1 ;
if err_0 < 0
integral = integral+err_0; %誤差累計
end
else
index = 0 ;
end
elseif y_d_last<min
if abs(err_0) <= y(k)
index = 1 ;
if err_0 > 0
integral = integral+err_0; %誤差累計
end
else
index = 0 ;
end
else
if abs(err_0) <= y(k)
index = 1 ;
integral = integral+err_0; %誤差累計
else
index = 0 ;
end
end
y_d_last = Kp*err_0 + Ki*index*integral/2 + Kd*(err_1-err_0); %PID運算公式
err_1 = err_0 ;
%更新參數(shù)
y_d(k) = y_d_last ;
err(k) = err_1 ;
end
%輸出圖像繪制
t = 1:1:len;
subplot( 2, 1, 1 ) ;
plot( t, y, 'r', t, y_d, 'b' );
axis([0 len, 0 1.5*y(1)])
title('輸出曲線');
xlabel('t')
ylabel('y(t)')
%誤差圖像繪制
subplot( 2, 1, 2 ) ;
plot( t, err );
axis([0 len, 0 1.5*y(1)])
title('誤差曲線');
xlabel('t')
ylabel('e(t)')
2.6.3 C算法
#include
#include
struct _pid
{
float SetSpeed ; //設(shè)置速度
float ActualSpeed ; //實際速度
float err ; //誤差
float err_last ; //最終誤差
float Kp , Kd , Ki ; //比例系數(shù)
float voltage ; //輸出電壓
float integral ; //積分值
float umax ; //積分上限
float umin ; //積分下限
}pid;
void PID_Init()
{
pid.SetSpeed = 0 ;
pid.ActualSpeed = 0.0 ;
pid.err = 0.0 ;
pid.err_last = 0.0 ;
pid.voltage = 0.0 ;
pid.integral = 0.0 ;
pid.Kp = 0.2 ;
pid.Kd = 0.2 ;
pid.Ki = 0.1 ;
pid.umax = 400 ;
pid.umin = -200 ;
}
float PID_Realize( float Speed )
{
char index ;
pid.SetSpeed = Speed ;
pid.err = pid.SetSpeed-pid.ActualSpeed ;
if( pid.ActualSpeed>pid.umax )
{
if( abs(pid.err)<=200 )
{
index = 1 ;
if( pid.err<0 )
pid.integral += pid.err ;
}
else
index = 0 ;
}
else if( pid.ActualSpeed
-
matlab
+關(guān)注
關(guān)注
182文章
2963瀏覽量
230195 -
直流電機
+關(guān)注
關(guān)注
36文章
1708瀏覽量
70088 -
PID
+關(guān)注
關(guān)注
35文章
1471瀏覽量
85307
發(fā)布評論請先 登錄
相關(guān)推薦
評論