PID算法的定義:
P:比例控制項(xiàng)。 I:積分控制項(xiàng)。 D:微分控制項(xiàng)。
設(shè)當(dāng)前輸出量為U,我們的期望值或是設(shè)定值為U0,則可得當(dāng)前時(shí)刻誤差:E=U-U0;
PID算法即是對(duì)誤差量E及E的歷史進(jìn)行某種線性組合得到控制量的算法。
一般形式:
Up=P*E;
Ui=i*(E+E_1+E_2+.。。) E_n為之前的第n次誤差.
Ud=i*(E-E_1)
U=Up+Ui+Ud; U為PID控制輸出量.
上式中Ui的計(jì)算不太方便,長(zhǎng)時(shí)間單方向的累加將可能出現(xiàn)溢出,于是將上式改為如下所示的增量形式:
Up=p*(E-E_1) 比例項(xiàng)增量
Ui=i*(E-2*E_1+E_2) 微分項(xiàng)增量
Ud=i*E 積分項(xiàng)增量
U=Uout_1+Up+Ui+Ud U為PID控制輸出量,Uout_1為前次PID輸出值
Uout=U 保存本次值
對(duì)于上面的公式或理論,便可得到相應(yīng)的C語(yǔ)言程序:
//======================定義PID結(jié)構(gòu)=========================
static float MinValue; //最大值限制
static float MaxValue; //最小值限制
static float CurrentValue; //當(dāng)前采樣值
static struct PID{
float Ki; //定義積分常數(shù)
float Kp; //定義比例常數(shù)
float Kd; //定義微分常數(shù)
float E_2; //存儲(chǔ)前前次誤差
float E_1; //存諸前次誤差
float E; //存儲(chǔ)本次誤差
float OutPut; //本次輸出量
float ValueSet; //設(shè)定值或期望值
}Control;
//===========================PID計(jì)算函數(shù)=====================
void PidWork() {
float Up,Ud,Ui;
Control.E=CurrentValue-Control.ValueSet; //得到本次誤差
Up =Control.Kp*(Control.E-Control.E_1); //得到比例項(xiàng)
Ud=Control.Kd*(Control.E-2*Control.E_1+Control.E_2); //得到微分項(xiàng)
Ui=Control.Ki*Control.E; //得到積分項(xiàng)
Control.E_2=Control.E_1; //歷史存儲(chǔ)
Control.E_1=Control.E;
Control.OutPut+=Up+Ud+Ui; //計(jì)算增量和
if(Control.OutPut
else if(Control.OutPut》MaxValue)Control.OutPut=MaxValue;
}
//==========================初始化速度=========================
void PidInit() {
MinValue=0;
MaxValue=1000;
CurrentValue=0;
Control.Kp=-6;
Control.Ki=-1.5;
Control.Kd=-0.5;
Control.E=0;
Control.E_2=0;
Control.E_1=0;
Control.ValueSet=100;
Control.OutPut=0;
}
以上三個(gè)函數(shù)為PID的主體函數(shù),也是萬用PID函數(shù).代碼量已經(jīng)相當(dāng)精簡(jiǎn)了。注意上面的PID初始化函數(shù)中有Kp,Ki,Kd的符號(hào)一定要正確,否則輸出量方向相反,后果不堪設(shè)想!!!
附上一段完整代碼:
#include
struct _pid {
int pv; /*integer that contains the process value*/
int sp; /*integer that contains the set point*/
float integral;
float pgain;
float igain;
float dgain;
int deadband;
int last_error;
};
struct _pid warm,*pid;
int process_point, set_point,dead_band;
float p_gain, i_gain, d_gain, integral_val,new_integ;;
/*------------------------------------------------------------------------
pid_init
DESCRIPTION This function initializes the pointers in the _pid structure
to the process variable and the setpoint. *pv and *sp are
integer pointers.
------------------------------------------------------------------------*/
void pid_init(struct _pid *warm, int process_point, int set_point)
{
struct _pid *pid;
pid = warm;
pid-》pv = process_point;
pid-》sp = set_point;
}
/*------------------------------------------------------------------------
pid_tune
DESCRIPTION Sets the proportional gain (p_gain), integral gain (i_gain),
derivitive gain (d_gain), and the dead band (dead_band) of
a pid control structure _pid.
------------------------------------------------------------------------*/
void pid_tune(struct _pid *pid, float p_gain, float i_gain, float d_gain, int dead_band)
{
pid-》pgain = p_gain;
pid-》igain = i_gain;
pid-》dgain = d_gain;
pid-》deadband = dead_band;
pid-》integral= integral_val;
pid-》last_error=0;
}
/*------------------------------------------------------------------------
pid_setinteg
DESCRIPTION Set a new value for the integral term of the pid equation.
This is useful for setting the initial output of the
pid controller at start up.
------------------------------------------------------------------------*/
void pid_setinteg(struct _pid *pid,float new_integ)
{
pid-》integral = new_integ;
pid-》last_error = 0;
}
/*------------------------------------------------------------------------
pid_bumpless
DESCRIPTION Bumpless transfer algorithim. When suddenly changing
setpoints, or when restarting the PID equation after an
extended pause, the derivative of the equation can cause
a bump in the controller output. This function will help
smooth out that bump. The process value in *pv should
be the updated just before this function is used.
------------------------------------------------------------------------*/
void pid_bumpless(struct _pid *pid)
{
pid-》last_error = (pid-》sp)-(pid-》pv);
}
/*------------------------------------------------------------------------
pid_calc
DESCRIPTION Performs PID calculations for the _pid structure *a. This function uses the positional form of the pid equation, and incorporates an integral windup prevention algorithim. Rectangular integration is used, so this function must be repeated on a consistent time basis for accurate control.
RETURN VALUE The new output value for the pid loop.
USAGE #include ‘control.h’*/
float pid_calc(struct _pid *pid)
{
int err;
float pterm, dterm, result, ferror;
err = (pid-》sp) - (pid-》pv);
if (abs(err) 》 pid-》deadband)
{
ferror = (float) err; /*do integer to float conversion only once*/
pterm = pid-》pgain * ferror;
if (pterm 》 100 || pterm 《》
{
pid-》integral = 0.0;
}
else
{
pid-》integral += pid-》igain * ferror;
if (pid-》integral 》 100.0)
{
pid-》integral = 100.0;
}
else if (pid-》integral 《 0.0)=“” pid-=“”》integral = 0.0;
}
dterm = ((float)(err - pid-》last_error)) * pid-》dgain;
result = pterm + pid-》integral + dterm;
}
else result = pid-》integral;
pid-》last_error = err;
return (result);
}
void main(void)
{
float display_value;
int count=0;
pid = &warm;
// printf(‘Enter the values of Process point, Set point, P gain, I gain, D gain \n’);
// scanf(‘%d%d%f%f%f’, &process_point, &set_point, &p_gain, &i_gain, &d_gain);
process_point = 30;
set_point = 40;
p_gain = (float)(5.2);
i_gain = (float)(0.77);
d_gain = (float)(0.18);
dead_band = 2;
integral_val =(float)(0.01);
printf(‘The values of Process point, Set point, P gain, I gain, D gain \n’);
printf(‘ %6d %6d %4f %4f %4f\n’, process_point, set_point, p_gain, i_gain, d_gain);
printf(‘Enter the values of Process point\n’);
while(count《》
{
scanf(‘%d’,&process_point);
pid_init(&warm, process_point, set_point);
pid_tune(&warm, p_gain,i_gain,d_gain,dead_band);
pid_setinteg(&warm,0.0); //pid_setinteg(&warm,30.0);
//Get input value for process point
pid_bumpless(&warm);
// how to display output
display_value = pid_calc(&warm);
printf(‘%f\n’, display_value);
//printf(‘\n%f%f%f%f’,warm.pv,warm.sp,warm.igain,warm.dgain);
count++;
}
}
評(píng)論
查看更多