描述
温度控制PID介绍自整定原理
整定PID控制器
为了获得特定的过度,整定温度控制器涉及设定比例、积分和微分值 程的最佳控制。如果控制器不包括自动整定算法或自动整定算法 如果动态整定算法没有提供足够的适合特定应用的控制,则必须使用试错法 整定装置。
以下是温度控制器的标准整定步骤。还可采用其他整定步骤, 但都使用类似的试错方法。请注意,如果控制器使用机械继电器 (非固态继电器)开始时应使用较长的循环时间(20秒)。
以下定义可能需要使用 :
循环时间 – 又称工作周期,是控制器完成的通断循环 使用的总时间长度。 对于20秒的循环时间,10秒的连接时间 切断时间和10秒代表50%的功率输出。在比例带内,控制 循环连接和切断制器。
比例带 – 控制器的比例以满量程的%或度表示 这种作用发生在这个范围内。比例带越宽,比例作用发生在其中 围绕设定值的区域越大。有时用增益来表示增益是比例带 的倒数。
积分,又称复位,是根据设定值调整带宽以补偿偏差 设定值偏移(固定偏差)的函数,也就是说,它在 系统稳定后,将控制温度调整到设定值。
微分,又称速率,感应系统温度上升或下降的速率 动态调节比例带,以最大限度地减少下冲或过冲。
PID(三模式)控制器如果正确整定和使用的话,能具有优异的 控制稳定性。通过仔细遵守这些指示,操作人员可以尽快实现 响应时间和最小过冲。三模控制器的信息可能会有所不同 对于其他控制器的整定步骤。对于主输出,自整定功能可以节省 需要使用此手动整定步骤,但需要时可以进入自整定值 行调整。
A.加热控制控制的输出
启用输出并启动过程。
过程应在设定值处运行,将用所需热量输入让温度稳定。
当速率和复位断开时,温度将稳定,并在设定值和实际值中 温度之间存在稳态偏差或固定偏差。观察显示屏上的测量 密切注意这个温度是否有规则的循环或振荡。(振荡可以 长达30分钟。
4.如果温度没有规则振荡,会PB除以2(见图1) 稳定,然后检查是否有温度振荡。如果仍然没有振荡, 再将PB除以2。重复此操作,直到循环或振荡。 第5步。
5.如果立即观察到振荡,将是PB乘以2。观察到的温度几分钟 钟。如果振荡继续,系数2将继续乘以PB,直到振荡停止。
此时,PB非常接近其临界设置。小心增加或减少PB设 直到温度记录刚刚出现循环或振荡。
即使在1%的最小PB设置过程中温度仍不振荡, 请跳过以下第6步到第11步,转到第B条。
临界的临界BP读取设定值和实际温度 稳态偏差,或固定偏差。(因为温度有一点循环, 请使用平均温度。
测量相邻峰谷之间的振荡时间,分为单位 (见图2)。这种测量最容易使用图表记录仪,但每次都可以 为了掌握时间,每隔一分钟读取一次测量值。
此时,增大PB设置,直到温度偏差(或固定偏差)增加 65%。
用于临界BP初始温度偏差乘以1.65或者 使用方便的线列图I(见图4)计算所需的最终温度偏差 差。用试错法尝试几次。PB控制设置,直到最终得到所需的 温度偏差。
此时您已经完成了得到控制器最佳性能所需的所有测量。 只需再做两次调整 – 速度与复位。
复位值按以下方法计算, 以每分钟重复次数为单位。
输入此值RESET 1。
使用第7步中测得的振荡时间,按以下方法计算速率 值,分为单位。
输入此值RATE 1。
如有过冲,可通过减少复位时间来消除。对复位值 更改时,还应相应更改速率调整,使速率值 等于:
也就是说,如果复位 = 2 R/M,则速率= 0.08分钟
如果你想在系统干扰的响应时间和设置时间之间扰 正确的平衡可能需要多次更改设定值和随后的复发 调整位置和速度控制时间。快速响应往往伴随着较大的过冲, 稳定过程所需的时间也很短。相反,如果响应比较好 慢,过程往往慢慢滑到最终值,过冲很小或没有过冲 冲。根据系统的要求,决定采取哪种行动。
为了节省接触器的增加循环时间,以节省接触器的寿命 (适用于只有时间比输出的装置(TPRI))。不引起测量 当值因负载循环而振荡时,应尽量增加循环时间。
转到C节。
B. 未观察振荡时的整个步骤
在最小PB在设定下,测量设定值与实际温度之间的稳态偏差 或固定偏差。
增大PB设置,直到温度偏差(固定偏差)增加65%。 图I(见图4)为计算最终温度偏差提供了简单的方法。
将RESET 1设置为较高值(10 R/M)。将RATE 1设 对应值(0.02分)。此时,由于复位,测量 在设定温度下,量值应稳定。
由于我们不能确定临界振荡时间,我们必须用试错法来确定复位 调整位置和速度的最佳设置。温度稳定在设定值后 设定温度增加10度。观察实际温度上升过程中伴 随的过冲。然后将设定温度的设置返回到其初始值,然后观察 检查实际温度升高过程中伴随的过冲。 过冲过大表明复位和/或速率值设置过高。过阻尼响应 (无过冲)表明复位和/或速率值设置过低。请参看图 7。当需要改进性能时,一次改变整个参数并观察设置 参数在定值变化时对性能的影响。让参数增加变化,直 优化性能。
满意的固定时,应增加循环时间,以节省接触器的寿命 生命(适用于只有时间比输出的装置(TPRI))。在不造成 当测量值因负载循环而振荡时,尽量增加循环时间。
图7:设置复位和/或速率
C. 整个冷却控制的主输出
使用与加热相同的步骤。工艺应在设定值处运行,要求 在温度稳定前进行冷却控制。
D. PID简化控制器的固定步骤
以下步骤是分析步进输入响应曲线的图形方法。 用长图记录仪读取过程中的变量(PV)会更简单。
从冷启动(PV从室温开始,控制器不在环路中 在这种情况下(即开环时)给过程供电最大功率。记录此开口 始时间。
延迟后(让热量到达传感器),PV将开始上 升。再经过一段延迟后,PV最大变化率将达到 (斜率)。记录最大斜率出现的时间和此时的时间 PV。记录最大斜率,以度/分为单位。关闭系统电源。
从最大斜率点到环境温度轴,画一条线 系统延时Td(见图8)。以下公式也可以延迟: Td = 达到最大斜率的时间-(最大斜率PV – 环境温度/ 最大斜率s
应用以下公式获取PID参数:
比例范围 = Td x 最大斜率x 100/量程 = 量程的%
复位 = 0.4 / Td =次/分
速率 = 0.4 x Td = 分
当控制器处于环路中时,重启系统并将过程带到设置中 定值,观察响应。如果响应过大或振荡,可以 改变以下方向PID参数(稍微改变,一次改变一个参数 加宽比例带,降低复位值,增加速率值。
示例: 图8中的图表记录是在最大功率供电加热炉时获得的 是的。图表比例尺是10?F/cm和5分/cm。控制器范围为 100 ~ 600?F,或者说500?F的量程。
示例: 图8中的图表记录是在最大功率供电加热炉时获得的 是的。图表比例尺为10°F/cm和5分/cm。控制器范围为 100 ~ 600°F,或者说500°F的量程。
最大斜率 = 18°F/5分
= 3.6°F/分
延时 = Td = 大约7分
比例带 = 7分x3.6°F/分 x 100/500°F = 5%。
复位 = 0.4 /7分 = 0.06次/分
速率 = 0.4 x 7分 = 2.8分
图8:系统延迟
pid算法温度控制c语言程序
基于PID温度控制系统的算法 89C51单片机通过键盘输入预设值DS18B比较20测得的实际值,然后驱动制冷或加热电路。keil C语言来实现PID的控制。
#include《reg51.h》
#include《intrins.h》
#include《math.h》
#include《string.h》
struct PID {
unsigned int SetPoint; // 设定目标 Desired Value
unsigned int Proportion; // 比例常数 Proportional Const
unsigned int Integral; // 积分常数 Integral Const
unsigned int Derivative; // 微分常数 Derivative Const
unsigned int LastError; // Error[-1]
unsigned int PrevError; // Error[-2]
unsigned int SumError; // Sums of Errors
};
struct PID spid; // PID Control Structureunsigned int rout; // PID Response (Output)
unsigned int rin; // PID Feedback (Input)
sbit data1=P1^0;
sbit clk=P1^1;
sbit plus=P2^0;
sbit subs=P2^1;
sbit stop=P2^2;
sbit output=P3^4;
sbit DQ=P3^3;
unsigned char flag,flag_1=0;
unsigned char high_time,low_time,count=0;//占空比调节参数
unsigned char set_temper=35;
unsigned char temper;
unsigned char i;
unsigned char j=0;
unsigned int s;
/***********************************************************
延时子程序,延时时间以12M晶振为准,延时时间为30us×time
***********************************************************/
void delay(unsigned char time)
{
unsigned char m,n;
for(n=0;n《time;n++)
for(m=0;m《2;m++){}
}
/***********************************************************
写一位数据子程序
***********************************************************/
void write_bit(unsigned char bitval)
{
EA=0;
DQ=0; /*拉低DQ以开始一个写时序*/
if(bitval==1)
{
_nop_();
DQ=1; /*如要写1,则将总线置高*/
}
delay(5); /*延时90us供DA18B20采样*/
DQ=1; /*释放DQ总线*/
_nop_();
_nop_();
EA=1;
}
/***********************************************************
写一字节数据子程序
***********************************************************/
void write_byte(unsigned char val)
{
unsigned char i;
unsigned char temp;
EA=0; /*关中断*/
TR0=0;
for(i=0;i《8;i++) /*写一字节数据,一次写一位*/
{
temp=val》》i; /*移位操作,将本次要写的位移到最低位*/
temp=temp&1;
write_bit(temp); /*向总线写该位*/
}
delay(7); /*延时120us后*/
// TR0=1;
EA=1; /*开中断*/
}
/***********************************************************
读一位数据子程序
***********************************************************/
unsigned char read_bit()
{
unsigned char i,value_bit;
EA=0;
DQ=0; /*拉低DQ,开始读时序*/
_nop_();
_nop_();
DQ=1; /*释放总线*/
for(i=0;i《2;i++){}
value_bit=DQ;
EA=1;
return(value_bit);
}
/***********************************************************
读一字节数据子程序
***********************************************************/
unsigned char read_byte()
{
unsigned char i,value=0;
EA=0;
for(i=0;i《8;i++)
{
if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/
value|=0x01《《i;
delay(4); /*延时80us以完成此次都时序,之后再读下一数据*/
}
EA=1;
return(value);
}
/***********************************************************
复位子程序
***********************************************************/
unsigned char reset()
{
unsigned char presence;
EA=0;
DQ=0; /*拉低DQ总线开始复位*/
delay(30); /*保持低电平480us*/
DQ=1; /*释放总线*/
delay(3);
presence=DQ; /*获取应答信号*/
delay(28); /*延时以完成整个时序*/
EA=1;
return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/
}
/***********************************************************
获取温度子程序
***********************************************************/
void get_temper()
{
unsigned char i,j;
do
{
i=reset(); /*复位*/
}while(i!=0); /*1为无反馈信号*/
i=0xcc; /*发送设备定位命令*/
write_byte(i);
i=0x44; /*发送开始转换命令*/
write_byte(i);
delay(180); /*延时*/
do
{
i=reset(); /*复位*/
}while(i!=0);
i=0xcc; /*设备定位*/
write_byte(i);
i=0xbe; /*读出缓冲区内容*/
write_byte(i);
j=read_byte();
i=read_byte();
i=(i《《4)&0x7f;
s=(unsigned int)(j&0x0f);
s=(s*100)/16;
j=j》》4;
temper=i|j; /*获取的温度放在temper中*/
}
/*====================================================================================================
Initialize PID Structure
=====================================================================================================*/
void PIDInit (struct PID *pp)
{
memset ( pp,0,sizeof(struct PID));
}
/*====================================================================================================
PID计算部分
=====================================================================================================*/
unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint )
{
unsigned int dError,Error;
Error = pp-》SetPoint - NextPoint; // 偏差
pp-》SumError += Error; // 积分
dError = pp-》LastError - pp-》PrevError; // 当前微分
pp-》PrevError = pp-》LastError;
pp-》LastError = Error;
return (pp-》Proportion * Error//比例
+ pp-》Integral * pp-》SumError //积分项
+ pp-》Derivative * dError); // 微分项
}
/***********************************************************
温度比较处理子程序
***********************************************************/
compare_temper()
{
unsigned char i;
if(set_temper》temper)
{
if(set_temper-temper》1)
{
high_time=100;
low_time=0;
}
else
{
for(i=0;i《10;i++)
{ get_temper();
rin = s; // Read Input
rout = PIDCalc ( &spid,rin ); // Perform PID Interation
}
if (high_time《=100)
high_time=(unsigned char)(rout/800);
else
high_time=100;
low_time= (100-high_time);
}
}
else if(set_temper《=temper)
{
if(temper-set_temper》0)
{
high_time=0;
low_time=100;
}
else
{
for(i=0;i《10;i++)
{ get_temper();
rin = s; // Read Input
rout = PIDCalc ( &spid,rin ); // Perform PID Interation
}
if (high_time《100)
high_time=(unsigned char)(rout/10000);
else
high_time=0;
low_time= (100-high_time);
}
}
// else
// {}
}
/*****************************************************
T0中断服务子程序,用于控制电平的翻转 ,40us*100=4ms周期
******************************************************/
void serve_T0() interrupt 1 using 1
{
if(++count《=(high_time))
output=1;
else if(count《=100)
{
output=0;
}
else
count=0;
TH0=0x2f;
TL0=0xe0;
}
/*****************************************************
串行口中断服务程序,用于上位机通讯
******************************************************/
void serve_sio() interrupt 4 using 2
{
/* EA=0;
RI=0;
i=SBUF;
if(i==2)
{
while(RI==0){}
RI=0;
set_temper=SBUF;
SBUF=0x02;
while(TI==0){}
TI=0;
}
else if(i==3)
{
TI=0;
SBUF=temper;
while(TI==0){}
TI=0;
}
EA=1; */
}
void disp_1(unsigned char disp_num1[6])
{
unsigned char n,a,m;
for(n=0;n《6;n++)
{
// k=disp_num1[n];
for(a=0;a《8;a++)
{
clk=0;
m=(disp_num1[n]&1);
disp_num1[n]=disp_num1[n]》》1;
if(m==1)
data1=1;
else
data1=0;
_nop_();
clk=1;
_nop_();
}
}
}
/*****************************************************
显示子程序
功能:将占空比温度转化为单个字符,显示占空比和测得到的温度
******************************************************/
void display()
{
unsigned char code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};
unsigned char disp_num[6];
unsigned int k,k1;
k=high_time;
k=k%1000;
k1=k/100;
if(k1==0)
disp_num[0]=0;
else
disp_num[0]=0x60;
k=k%100;
disp_num[1]=number[k/10];
disp_num[2]=number[k%10];
k=temper;
k=k%100;
disp_num[3]=number[k/10];
disp_num[4]=number[k%10]+1;
disp_num[5]=number[s/10];
disp_1(disp_num);
}
/***********************************************************
主程序
***********************************************************/
main()
{
unsigned char z;
unsigned char a,b,flag_2=1,count1=0;
unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2};
TMOD=0x21;
TH0=0x2f;
TL0=0x40;
SCON=0x50;
PCON=0x00;
TH1=0xfd;
TL1=0xfd;
PS=1;
EA=1;
EX1=0;
ET0=1;
ES=1;
TR0=1;
TR1=1;
high_time=50;
low_time=50;
PIDInit ( &spid ); // Initialize Structure
spid.Proportion = 10; // Set PID Coefficients
spid.Integral = 8;
spid.Derivative =6;
spid.SetPoint = 100; // Set PID Setpoint
while(1)
{
if(plus==0)
{
EA=0;
for(a=0;a《5;a++)
for(b=0;b《102;b++){}
if(plus==0)
{
set_temper++;
flag=0;
}
}
else if(subs==0)
{
for(a=0;a《5;a++)
for(b=0;a《102;b++){}
if(subs==0)
{
set_temper--;
flag=0;
}
}
else if(stop==0)
{
for(a=0;a《5;a++)
for(b=0;b《102;b++){}
if(stop==0)
{
flag=0;
break;
}
EA=1;
}
get_temper();
b=temper;
if(flag_2==1)
a=b;
if((abs(a-b))》5)
temper=a;
else
temper=b;
a=temper;
flag_2=0;
if(++count1》30)
{
display();
count1=0;
}
compare_temper();
}
TR0=0;
z=1;
while(1)
{
EA=0;
if(stop==0)
{
for(a=0;a《5;a++)
for(b=0;b《102;b++){}
if(stop==0)
disp_1(phil);
// break;
}
EA=1;
}
}
//DS18b20 子程序
#include 《REG52.H》
sbit DQ=P2^1; //定义端口
typedef unsigned char byte;
typedef unsigned int word;
//延时
void delay(word useconds)
{
for(;useconds》0;useconds--);
}
//复位
byte ow_reset(void)
{
byte presence;
DQ=0; //DQ低电平
delay(29); //480us
DQ=1; //DQ高电平
delay(3); //等待
presence=DQ; //presence信号
delay(25);
return(presence);
} //0允许,1禁止
//从1-wire 总线上读取一个字节
byte read_byte(viod)
{
byte i;
byte value=0;
for (i=8;i》0;i--)
{
value》》=1;
DQ=0;
DQ=1;
delay(1);
if(DQ)value|=0x80;
delay(6);
}
return(value);
}
//向1-wire总线上写一个字节
void write_byte(char val)
{
byte i;
for (i=8;i》0;i--) //一次写一个字节
{
DQ=0;
DQ=val&0x01;
delay(5);
DQ=1;
val=val/2;
}
delay(5);
}
//读取温度
char Read_Temperature(void)
{
union{
byte c[2];
int x;
}temp;
ow_reset();
write_byte(0xcc);
write_byte(0xBE);
temp.c[1]=read_byte();
temp.c[0]=read_byte();
ow_reset();
write_byte(0xCC);
write_byte(0x44);
return temp.x/2;
}
打开APP阅读更多精彩内容
点击阅读全文