|
发表于 2011-5-17 12:24:21
|
显示全部楼层
我按照楼主的说法做实验,折腾了一夜也没个结果,苦恼中。
我的加热设备是一个500w的电热块,被加热的设备是一个约3斤重的铝块;
也用MAX6675采集温度,用可控硅控制加热,通过串口将数据输出到电脑查看工作曲线;
也是5秒钟计算一次PID,定时器10ms中断一次,5秒钟中断500次;
通过计算得出5秒钟要导通的次数来控制加热量;
以上跟楼主做实验的设备原理基本上是一样的;
源程序如下:
struct pid
{
float sp;
float pv;
float errk;
float errk_1;
float errk_2;
float sum;
float kp;
float ki;
float kd;
float Last_Out;
};
struct pid ppid;
//PID计算
void PID_Cal(void)
{
float pterm,iterm,dterm;
//把当前的温度和设定的目标温度定义好
ppid.pv = f_temp; //当前温度
ppid.sp = 110; //设定的温度
ppid.kp = 200; //先求临界震荡
ppid.ki = 0;
ppid.kd = 0;
//PID数学模型
//u(t) = kp * e(t) + ki * [e(1) + e(2) + ....+ e(t)] + kd * [e(t) - e(t-1)]
ppid.errk = (float)(ppid.sp - ppid.pv); //偏差 = 设定温度 - 当前温度
pterm = ppid.kp * ppid.errk; //比例系数 * 偏差 kp * e(t)
ppid.sum += ppid.errk; // e(1) + e(2) + ....+ e(t)
iterm = ppid.ki * ppid.sum; //ki * [e(1) + e(2) + ....+ e(t)]
pid_sum = ppid.sum;
dterm = ppid.kd * (ppid.errk_1 - ppid.errk_2); //kd * [e(t) - e(t-1)] 这里与楼主源程序有点区别,源程序是(ppid.errk - ppid.errk_1)
ppid.Last_Out = pterm + iterm + dterm; //u(t) = kp * e(t) + ki * [e(1) + e(2) + ....+ e(t)] + kd * [e(t) - e(t-1)]
ppid.errk_2 = ppid.errk_1;
ppid.errk_1 = ppid.errk;
if(ppid.Last_Out > SampleT)
ppid.Last_Out = SampleT;
else if(ppid.Last_Out < 0)
ppid.Last_Out = 0;
sprintf(tx_buf,"%5.2f\n",f_temp); //输出测量的数据
v_sent_uart1_str(tx_buf,0);
}
开始试验,
我要控制达到的温度是110,而我实验比例调节时(Pi,Pd=0),只有KC = 200时,才会震荡,而KC低于70时,温度根本达不到设定的110,楼主的9.3是怎么来的?当kp=9.3时,当温度接近设
定温度时,如相差2度,则pterm = ppid.kp * ppid.errk=9.3*2=18.6,也就是每五秒钟只导通18.6/500*5=0.186秒?可能我理解的不对,可不知道错在哪里。
我试验的数据如图,我的图形远没有楼主的那么平滑。
根据数据我计算的PID参数:
振荡周期为:Pc=51*5=255
T=5s
Td=0.12Pc=30.6
Ti=0.5Pc=127.5
Kp=0.65KC=130
Kd=Kp*Td/T=795
Ki=Kp*T/Ti=5.1
把这些数据带到程序中,结果一运行,温度到180度都没停下,吓得我赶紧断了电。
另,关于pi的算法,根据公式ki * [e(1) + e(2) + ....+ e(t)],我从最低温加热到设定的温度,[e(1) + e(2) + ....+ e(t)]这个值会很大,我的达到了几千,再小的Ki与他相乘也会变得
很大,是这样计算的吗?
求高人指点一下我,可怜我昨晚一直做实验到天亮。

(原文件名:临界震荡.JPG) |
|