|
常规PID控温在升温过程中不可避免会产生一定量的超调,抛砖引玉贴一个防止温控升温过程超调的C代码,该段代码是应项目需要快速加热一8KG铁块(如图被加热件)加热至100~200℃
单纯的传统的PID会产生40℃左右的超调
浙江余姚一国产温控表从21℃加热至150℃过冲6摄氏度用时4分30秒。
之前网友说宇电温控表技术接近了日本岛电,于是花了450多元购买了一台,加热过程不是一般的慢,起始温度61℃加热至150℃用时9分46秒,超调1℃,如果起始温度接近设定温度开始加热,到达设定温度会更慢,从145℃加热到150℃也需要8分钟,加热器本来功率很大,都让温控表吃掉了,为了防止超调以很小的功率升温很容易做到不超调,这算什么技术,宇电的升温太慢了。
要想达到即快速加热又没有超调或者超调量小,真的不是那么容易,加热铁块这种变态的东西(不像水空气)很容易超调,要想加热快肯定会产生一定的超调量,想没有超调只能缓慢加热,这就是一组矛盾如何这这两个要求之间选个折中点,贴个C代码程序。试验从53℃升温至150℃,加热时间5分30秒,超调不过1℃,为了省事本控制器测温使用的是MAX6675,测量分辨率只有0.25℃,所以控制精度能做到
整个温控函数分7个阶段,快速升温过程共6个阶段,第一个阶段是判断,第二个阶段强制加热,第三个阶段快速升温,第四个阶段间歇加热,第五个阶段是缓慢加热,第六个是缓冲阶段,第七个是PID,具体每个阶段的实现各位看官看代码,代码比较容易理解,没有使用高深的公式,只是仿照人类的思维进行调节。各位有什么更好的想法可以讨论一下。至于第七个阶段PID控温,当然要有好的PID三个参数,研究了市场上几款国产的温控仪大部分都是采用继电器负反馈进行参数自整定,自整定部分代码有需要的可有偿提供。
void pid_calc(float set_temp ,float now_temp )
{
uchar xdata back_i=4;
Error = set_temp - now_temp;// 偏差
dError = Error - LastError; // 当前微分
LastError= Error;
if(first_flag==1)
SumError += Error;
switch (pross_number)
{
case 1: //过程1,误差大于10度 强制提温,小于10度进入过程4间歇加热
if(Error>10)
{
first_count=30;//如果温差大于10度,进入过程2,连续加热10S钟
pid_result=100;
pross_number=2;
}
else
{
first_count=0;//如果温度小于10度,进入过程3,
pid_result=0;
pross_number=4;
}
break;
case 2://连续加热
if(first_count>0)
first_count--;//
else
{
pid_result=0;
pross_number=3; //进入间歇加热过程
}
break;
case 3: //快速加热阶段
if(Error >max_value_error)
pid_result=100;
else
{
pross_number=4; //进入间歇调温
pid_result=0;
}
break;
case 4://间歇加热温度上升不加热,温度不变或加热进行加热
if(max_tempter<=now_temp)//更新最大温度。
{
max_tempter=now_temp;
}
if(Error<=0)//超过设定温度进入停顿状态
{
pid_result = 0;
pross_number=6;//缓慢加热阶段
time_number=0;
}
else
{
if(Error>=10)//
{
if(pre_temper<now_temp)// 温度升高不需要加热
pid_result = 0;
else
pid_result =50;
}
else
{
pross_number=5;//缓慢加热阶段
time_number=0;
last_tempter=now_temp;
}
}
break;
case 5://缓慢加热阶段
if(max_tempter<=now_temp)//更新最大温度。
{
max_tempter=now_temp;
}
if(Error<=0)//超过设定温度进入停顿状态
{
pid_result = 0;
pross_number=6;//缓慢加热阶段
time_number=0;
}
else
{
if(time_number<5)
{
time_number++;
if((pid_result==100)&&((Error<5.0)&&(time_number>1)))
pid_result=0;
}
else//时间到后输出
{
if(last_tempter<now_temp)//时间到后判断如果温度有增加则不升温
pid_result=0;
else
pid_result=100;
last_tempter=now_temp;//更新温度
time_number=0;
}
if((last_tempter-now_temp)>1.0)//如果温度降低1度结束本次计时,计时重新开始
{
last_tempter=now_temp;//更新温度
pid_result=100;
time_number=0;
}
}
break;
case 6://间歇加热完毕后需要等待温度停止升高
if(max_tempter<now_temp)//最大温度更新
{
max_tempter=now_temp;
time_number=0;
}
else//确定温度不再爬升。
time_number++;
if(time_number>=4)//
{
pross_number=7;
first_flag=1;
pid_result=0;
time_number=0;
max_tempter=0;
}
break;
case 7://
if((Error<=5.0)&&(Error>=-5.0))
first_flag=1;
else
first_flag=0;
if((Error<=1.0)&&(Error>=-1.0))//误差在2.0至-1.5摄氏度时PID控温
{
p_temp=Proportion * Error;
i_temp=Integral * SumError;
d_temp=(dError*Derivative);
pid_result = (int)(p_temp+i_temp+d_temp);
}
if((Error<=2.0)&&(Error>1.0))//当误差大于1时,
{
pid_result =20;
}
if((Error<=5.0)&&(Error>2.0))//当误差大于1时,
{
pid_result =30;
}
if((Error<=10.0)&&(Error>5.0))//当误差大于1时,
{
pid_result =40;
}
if(Error>10.0)//当误差小于-1时,停止输出。
{
pid_result =100;
pross_number=1;
}
if(Error<-1.0)//当误差小于-1时,停止输出。
{
pid_result =0;
}
break;
default: break;
}//switch
if( pid_result < 0 )
{
pid_result = 0;
}
else if( pid_result > 100 )
{
pid_result = 100;
}
pre_temper=now_temp;
}
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
|