温度的PID控制一.温度检测部分首先要OK.二、PID调节作用PID控制时域的公式))()(1)(()(dttdeTdteTiteKpty分解开来:(1)比例调节器y(t)=Kp*e(t)e(k)为当前的温差(设定值与检测值的插值)y(k)为当前输出的控制信号(需要转化为PWM形式)#输出与输入偏差成正比。只要偏差出现,就能及时地产生与之成比例的调节作用,使被控量朝着减小偏差的方向变化,具有调节及时的特点。但是,Kp过大会导致动态品质变坏,甚至使系统不稳定。比例调节器的特性曲线.(2)积分调节器y(t)=Ki*∫(e(t))dtKi=Kp/TiTi为积分时间#TI是积分时间常数,它表示积分速度的大小,Ti越大,积分速度越慢,积分作用越弱。只要偏差不为零就会产生对应的控制量并依此影响被控量。增大Ti会减小积分作用,即减慢消除静差的过程,减小超调,提高稳定性。(3)微分调节器y(t)=Kd*d(e(t))/dtKd=Kp*TdTd为微分时间#微分分量对偏差的任何变化都会产生控制作用,以调整系统输出,阻止偏差变化。偏差变化越快,则产生的阻止作用越大。从分析看出,微分作用的特点是:加入微分调节将有助于减小超调量,克服震荡,使系统趋于稳定。他加快了系统的动作速度,减小调整的时间,从而改善了系统的动态性能。三.PID算法:由时域的公式离散化后可得如下公式:y(k)=y(k-1)+(Kp+Ki+Kd)*e(k)-(Kp+2*Kd)*e(k-1)+Kd*e(k-2)y(k)为当前输出的控制信号(需要转化为PWM形式)y(k-1)为前一次输出的控制信号e(k)为当前的温差(设定值与检测值的插值)e(k-1)为一次前的温差e(k-2)为二次前的温差Kp为比例系数Ki=Kp*T/TiT为采样周期Kd=Kp*Td/T四.PID参数整定(确定Kp,Ts,Ti,Td):温度控制适合衰减曲线法,需要根据多次采样的数据画出响应曲线。所以需要通过串口将采样时间t,输出y(t)记录下来,方便分析。1)、不加入算法,系统全速加热,从常温加热到较高的温度的时间为Tk,则采样时间一般设为T=Tk/10。2)、置调节器积分时间TI=∞,微分时间TD=0,即只加比例算法:y(k)=y(k-1)+Kp*e(k)比例带δ置于较大的值。将系统投入运行。(δ=1/Kp)3)、待系统工作稳定后,对设定值作阶跃扰动,然后观察系统的响应。若响应振荡衰减太快,就减小比例带;反之,则增大比例带。如此反复,直到出现如图所示的衰减比为4:1的振荡过程时,记录此时的δ值(设为δS),以及TS的值(如图中所示)。当采用衰减比为10:1振荡过程时,应用上升时间Tr替代振荡周期TS计算。系统衰减振荡曲线图中,TS为衰减振荡周期,Tr为响应上升时间。据表中所给的经验公式计算δ、TI及TD的参数。表衰减曲线法整定计算公式衰减率ψ整定参数调节规律δ(1/Kp)TITD0.75PδSPI1.2δS0.5TSPID0.8δS0.3TS0.1TS0.9PδSPI1.2δS2TrPID0.8δS1.2Tr0.4Tr大致计算出Kp,Ti,Td后代入公式,然后完善算法。让系统运作多测试几次。直到满意为止。以下是网上找的一个示例程序#includereg51.h#includeintrins.h#defineN040536#definenop()_nop_()#defineucharunsignedchar#defineuintunsignedint/*程序中变量数组定义*/ucharidatatable[]={Real-timeTemp:};//第一行显示Real-timeTemp:ucharidatatable1[5];uchardata1,kp,ki,kd;uintt,hightime,count;//占空比调节参数uintrltemp,settemp=350;inte1,e2,e3,duk,uk;/*引脚定义*/sbitEOC=P2^6;sbitOE=P2^5;sbitSTART=P2^7;sbitlcden=P3^2;sbitlcdrw=P3^1;sbitlcdrs=P3^0;sbitpwm=P3^3;/******************************延时子程序*******************************/voiddelay(uintz){uintx,y;for(x=z;x0;x--)for(y=29;y0;y--);}/******************************LCD忙检测*******************************/bitlcd_busy(){bitresult;lcdrw=1;lcdrs=0;lcden=1;nop();nop();nop();nop();result=(bit)(P0&0x80);lcden=0;return(result);}/******************************LCD写命令子程序*******************************/voidwrite_com(ucharcom){while(lcd_busy());//忙等待lcdrs=0;lcdrw=0;P1=com;delay(5);lcden=1;delay(5);lcden=0;}/******************************LCD写数据子程序*******************************/voidwrite_data(uchardate){while(lcd_busy());//忙等待lcdrs=1;lcdrw=0;P1=date;delay(5);lcden=1;delay(5);lcden=0;}/******************************LCD初始化*******************************/voidlcd_init(){lcden=0;write_com(0x38);delay(5);write_com(0x0f);delay(5);write_com(0x06);delay(5);write_com(0x01);delay(5);write_com(0x80);delay(5);write_com(0x01);}/******************************定时器初始化*******************************/voidtime_init(){EA=1;ET0=1;ET1=1;TR0=1;TR1=1;TMOD=0x11;TH0=N0/256;TL0=N0%256;TH1=0X3C;TL1=0XB0;}/******************************PID算法系数装载*******************************/voidPid_init(){hightime=0;//输出的占空比e1=0;//本次的温度差e2=0;//前一次的温度差e3=0;//两次前的温度差kp=10;//需要根据试验确定参数ki=5;//需要根据试验确定参数kd=5;//需要根据试验确定参数}/******************************温度比较PID算法*******************************/voidpid_ys(){if(rltempsettemp)//如果实际温度小于设定温度值{if(settemp-rltemp20)//如果相差20度(根据实际情况确定是多少){hightime=100;//全速加热}else//否则运行PID算法进行平滑加热{e1=settemp-rltemp;duk=(kp*(e1-e2)+ki*e1+kd*(e1-e2*2+e3))/10;//式(1)因为Kp是10,输入放大了10倍,所以duk的输出结果需要除以10uk=uk+duk;/*****************************式(1)与上面提到的公式类似y(k)=y(k-1)+(Kp+Ki+Kd)*e(k)-(Kp+2*Kd)*e(k-1)+Kd*e(k-2)可以写成y(k)-y(k-1)=(kp*(e(k)-e(k))+ki*e(k)+kd*(e(k)-e(k-1)*2+e(k-2))式(1)中duk相当于y(k)-(k-1)*****************************/if(uk100)uk=100;//设置饱和控制,elseif(uk-100)uk=-100;if(uk0){hightime=-uk;}else{hightime=uk;}e3=e2;e2=e1;}}if(rltemp=settemp)//如果实际温度大于设定值{if(rltemp-settemp0)//只要实际温度与设定值不相等{hightime=0;//停止加热}else/{e1=rltemp-settemp;duk=(kp*(e1-e2)+ki*e1+kd*(e1-e2*2+e3));uk=uk+duk;if(uk100)uk=100;elseif(uk-100)uk=-100;e3=e2;e2=e1;}}}/******************************主函数*******************************/voidmain(){uinti;time_init();//定时器初始化Pid_init();//PID初始化lcd_init();//LCD初始化table1[5]=0x43;table1[4]=0xdf;table1[2]=0x2e;//小数点摄氏度符号ASCII码for(i=0;i15;i++)//带循环第一行显示Real-timeTemp:{write_data(table[i]);delay(20);}while(1){t=data1*196/100;table1[3]=(t%100)%10+0x30;table1[1]=(t%100)/10+0x30;table1[0]=t/100+0x30;//以上温度数据转化rltemp=t;//给PID算法装载实际值write_com(0x80+0x45);//写LCD第二行的初地址for(i=0;i5;i++)//该循环显示温度值{write_data(table1[i]);delay(20);}pid_ys();//运行温度比较PID算法}}/******************************温度采集转换的定时中断0.5s刷新一次数据*******************************/voidtimer0()interrupt1{uintj;j++;if(j==20){OE=0;START=0;_nop_();START=1;_nop_();START=0;while(EOC==0);OE=1;_nop_();data1=P0;_nop_();OE=0;j=0;}TH0=N0/256;TL0=N0%256;}/******************************PWM波输出的定时中断*******************************/voidtimer1()interrupt3{if(++count=(hightime))pwm=0;elseif(count=100){pwm=1;}elsecount=0;TH1=0x3c;TL1=0xb0;}