精选优质文档-----倾情为你奉上 温度的PID控制一.温度检测部分首先要OK.二、PID调节作用PID控制时域的公式分解开来:(1) 比例调节器 y(t) = Kp * e(t) e(k) 为当前的温差(设定值与检测值的插值) y(k) 为当前输出的控制信号(需要转化为PWM形式) # 输出与输入偏差成正比只要偏差出现,就能及时地产生与之成比例的调节作用,使被控量朝着减小偏差的方向变化,具有调节及时的特点但是, Kp过大会导致动态品质变坏,甚至使系统不稳定比例调节器的特性曲线.(2) 积分调节器 y(t) = Ki * ∫(e(t))dt Ki = Kp/Ti Ti为积分时间#TI是积分时间常数,它表示积分速度的大小,Ti越大,积分速度越慢,积分作用越弱只要偏差不为零就会产生对应的控制量并依此影响被控量增大Ti会减小积分作用,即减慢消除静差的过程,减小超调,提高稳定性3) 微分调节器 y(t) = Kd*d(e(t))/dt Kd = Kp*Td Td为微分时间#微分分量对偏差的任何变化都会产生控制作用,以调整系统输出,阻止偏差变化。
偏差变化越快,则产生的阻止作用越大从分析看出,微分作用的特点是:加入微分调节将有助于减小超调量,克服震荡,使系统趋于稳定他加快了系统的动作速度,减小调整的时间,从而改善了系统的动态性能3. 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/Ti T为采样周期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)T IT D0.75Pδ S PI1.2 δ S0.5T S PID0.8 δ S0.3T S0.1T S0.9Pδ S PI1.2 δ S2T r PID0.8 δ S1.2T r0.4T r 大致计算出Kp,Ti,Td后代入公式,然后完善算法让系统运作多测试几次直到满意为止以下是网上找的一个示例程序#include #include #define N0 40536#define nop() _nop_()#define uchar unsigned char#define uint unsigned int/*程序中变量 数组定义*/uchar idata table[]={"Real-time Temp:"};//第一行显示"Real-time Temp:"uchar idata table1[5];uchar data1,kp,ki,kd; uint t,hightime,count; //占空比调节参数uint rltemp,settemp=350;int e1,e2,e3,duk,uk;/*引脚定义*/sbit EOC=P2^6;sbit OE=P2^5;sbit START=P2^7;sbit lcden=P3^2;sbit lcdrw=P3^1;sbit lcdrs=P3^0;sbit pwm=P3^3;/****************************** 延时子程序*******************************/void delay(uint z){ uint x,y; for(x=z;x>0;x--) for(y=29;y>0;y--);}/****************************** LCD忙检测*******************************/bit lcd_busy(){ bit result; lcdrw = 1; lcdrs = 0; lcden = 1; nop();nop();nop();nop(); result = (bit)(P0&0x80); lcden = 0; return(result);}/****************************** LCD写命令子程序*******************************/void write_com(uchar com){ while(lcd_busy());//忙等待 lcdrs = 0; lcdrw = 0; P1 = com; delay(5); lcden = 1; delay(5); lcden = 0;}/****************************** LCD写数据子程序*******************************/void write_data(uchar date){ while(lcd_busy()); //忙等待 lcdrs = 1; lcdrw = 0; P1=date; delay(5); lcden = 1; delay(5); lcden = 0;}/****************************** LCD初始化*******************************/void lcd_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);} /****************************** 定时器初始化*******************************/void time_init() { EA = 1; ET0 = 1; ET1 = 1; TR0 = 1; TR1 = 1; TMOD = 0x11; TH0 = N0/256; TL0 = N0%256; TH1 = 0X3C; TL1 = 0XB0; }/****************************** PID算法系数装载*******************************/void Pid_init(){ hightime= 0; //输出的占空比 e1 = 0; //本次的温度差 e2 = 0; //前一次的温度差 e3 = 0; //两次前的温度差 kp = 10; //需要根据试验确定参数 ki = 5; //需要根据试验确定参数 kd = 5; //需要根据试验确定参数}/****************************** 温度比较 PID算法*******************************/void pid_ys(){ if(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的输出结果需要除以10 uk = 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(uk>100) uk = 100; //设置饱和控制, else if(uk<-100) uk = -100; if(uk<0) { hightime=-uk; } else { hightime=uk; } e3 = e2; e2 = e1; } }if(rltemp>=settemp) // 如果实际温度大于设定值 { if(rltemp-settemp >0) //只要实际温度与设定值不相等 { hightime=0; //停止加热 } else / { e1 = rltemp-settemp; duk=(kp*(e1-e2)+ki*e1+kd*(e1-e2*2+e3)); uk = uk+duk; if(u。