PID 温度控制的实现
PID 简介
PID(Proportional Integral Derivative)控制是控制工程中技术成熟、应用广泛的一种控制策略,经过长期的工程实践,已形成了一套完整的控制方法和典型的结构。它不仅适用于数学模型已知的控制系统中,而且对于大多数数学模型难以确定的工业过程也可应用,在众多工业过程控制中取得了满意的应用效果。
PID 工作基理:由于来自外界的各种扰动不断产生,要想达到现场控制对象值保持恒定的目的,控制作用就必须不断的进行。若扰动出现使得现场控制对象值(以下简称被控参数)发生变化,现场检测元件就会将这种变化采集后经变送器送至PID 控制器的输入端,并与其给定值(以下简称SP 值)进行比较得到偏差值(以下简称e 值),调节器按此偏差并以我们预先设定的整定参数控制规律发出控制信号,去改变调节器的开度,使调节器的开度增加或减少,从而使现场控制对象值发生改变,并趋向于给定值(SP 值),以达到控制目的 ,如图 1 所示,其实PID 的实质就是对偏差(e 值)进行比例、积分、微分运算,根据运算结果控制执行部件的过程。
图1 模拟PID 控制系统原理图
PID 控制器的控制规律可以描述为:
(1)
比例(P)控制能迅速反应误差,从而减小稳态误差。但是,比例控制不能消除稳态误差。比例放大系数的加大,会引起系统的不稳定。积分(I)控制的作用是:只要系统有误差存在,积分控制器就不断地积累,输出控制量,以消除误差。因而,只要有足够的时间,积分控制将能完全消除误差,使系统误差为零,从而消除稳态误差。积分作用太强会使系统超调加大,甚至使系统出现振荡。微分(D)控制可以减小超调量,克服振荡,使系统的稳定性提高,同时加快系统的动态响应速度,减小调整时间,从而改善系统的动态性能。根据不同的被控对象的控制特性,又可以分为P、PI、PD、PID 等不同的控制模型。
数字PID 的实现
在连续-时间控制系统(模拟PID 控制系统)中,PID 控制器应用得非常广泛。其设计技术成熟,长期以来形成了典型的结构,参数整定方便,结构更改灵活,能满足一般的控制要求。随着计算机的快速发展,人们将计算机引入到PID 控制领域,也就出现了数字式PID 控制。
由于计算机基于采样控制理论,计算方法也不能沿袭传统的模拟PID 控制算法(如公式1 所示),所以必须将控制模型离散化,离散化的方法:以T 为采样周期,k 为采样序号,用求和的形式代替积分,用增量的形式(求差)代替微分,这样可以将连续的PID 计算公式离散:
(2)
式1 就可以离散为:
(3)
或者:
(4)
这样就可以让计算机或者单片机通过采样的方式实现PID 控制,具体的PID 控制又分为位置式PID 控制和增量式PID 控制,公式4 给出了控制量的全部大小,所以称之为全量式或者位置式控制;如果计算机只对相邻的两次作计算,只考虑在前一次基础上,计算机输出量的大小变化,而不是全部输出信息的计算,这种控制叫做增量式PID 控制算法,其实质就是求Δμ的大小,而 Δμk =μk -μk-1;所以将式4 做自减变换有:
(5)
其中
温度控制PID 算法设计
本设计利用了上面所介绍的位置式PID 算法,将温度传感器采样输入作为当前输入,然后与设定值进行相减得偏差ek,然后再对之进行PID 运算产生输出结果fOut,然后让fOut 控制定时器的时间进而控制加热器。为了方便PID 运算,首先建立一个PID 的结构体数据类型,该数据类型用于保存PID 运算所需要的P、I、D 系数,以及设定值,历史误差的累加和等信息:
typedef struct PID
{
float SetPoint; // 设定目标 Desired Value
float Proportion; // 比例系数 Proportional Const
float Integral; // 积分系数 Integral Const
float Derivative; // 微分系数 Derivative Const
int LastError; // 上次偏差
int SumError; // 历史误差累计值
} PID;
PID stPID; // 定义一个stPID 变量
下面是PID 运算的算法程序,通过PID 运算返回fOut,fOut 的值决定是否加热,加热时间是多少。
PID 运算的C 实现代码:
float PIDCalc( PID *pp, int NextPoint )
{
int dError,Error;
Error = pp->SetPoint*10 - NextPoint; // 偏差,设定值减去当前采样值
pp->SumError += Error; // 积分,历史偏差累加
dError = Error-pp->LastError; // 当前微分,偏差相减
pp->PrevError = pp->LastError; // 保存
pp->LastError = Error;
+ pp->Integral * pp->SumError // 积分项
- pp->Derivative * dError // 微分项
);
}
在实际运算时,由于水具有很大的热惯性,而且PID 运算中的I(积分项)具有非常明显的延迟效应所以不能保留,我们必须把积分项去掉,相反D(微分项)则有很强的预见性,能够加快反应速度,抑制超调量,所以积分作用应该适当加强才能达到较佳的控制效果,系统最终选择PD 控制方案,下面C 代码所示为PD 控制的实现过程:
float PIDCalc( PID *pp, int NextPoint )
{
int dError,Error;
Error = pp->SetPoint*10 - NextPoint; // 偏差,设定值减去当前采样值
dError = Error-pp->LastError; // 当前微分,偏差相减
pp->PrevError = pp->LastError; // 保存
pp->LastError = Error;
return (pp->Proportion * Error // 比例项
- pp->Derivative * dError // 微分项
);
}
温度控制实现
通过温度的PID 运算,产生结果fOut,该参数决定是否加热,加热时间是多长。该程序如下:
stPID.Proportion = 2; //设置PID 比例值
stPID.Integral = 0; //设置PID 积分值
stPID.Derivative = 5; //设置PID 微分值
fOut = PIDCalc ( &stPID,(int)(fT*10) ); //PID 计算
if(fOut<=0)
*P_IOA_Buffer &= 0xff7f; //温度高于设定值,关闭加热器
else
*P_IOA_Buffer |= 0x0080; //温度低于设定值,打开加热器
加热时间由主函数计算,由TimerB 中断控制。主程序中通过PIDCalc 函数得到fOut 参数,如果该参数大于“0”,则开启加热器。IRQ2_TMB 中断一直处于允许状态,每进入一次IRQ2_TMB 中断,fOut 参数减1,直到fOut = 0,停止加热。如果PIDCalc 计算结果比较大说明离目标温度相差较大,则加热时间比较长,如果计算结果比较小,说明离目标温度相差较小,加热时间相对较短。