平时很少上论坛,偶尔查查资料的时候才会上来看看,废话不多说了直入主题吧。
手上有一个项目需要有加热功能(目标65℃左右),刚开始也没怎么在意,最开始只是想着一个普通的加热功能无非就是接近目标温度的时候开始间段加温(类似发光二极管闪烁的状态),等到了实际加热的时候发现用这种方法可以控温,但是控温上下幅值过高,虽说项目对精度要求不高,个人有点强迫症,想着要做就做好,然后在网上查询了一下控温方式的几种算法,基本上90%的都是用PID,好那就开始着手研究PID了,查阅了大量的相关文献,对PID的原理也懂了(能查到的都是通篇大道理,可是能实际应用的少之又少),关于PID的算法网上也是一大堆,说实话我也看不懂,也没心思取研究他的算法,干脆直接在网上找源代码好了,源代码倒是很多,大部分都不是很完善,没办法只要算法是正确的就行了,有了算法,具体怎么用就只能靠自己写了。
下面开始直入核心阶段 1:什么是PID,PID的发展史,,这些问题自行百度,我只简单的描述一下,比如设定65℃,当温度上升到60℃的时候开始启用PID加热方式,然后由PID进行温度控制,因为有PID的存在,实际温度会在65℃上下浮动,浮动的精度由多种因素决定。精度控制在+-0.5℃还是很好控制的。 2 :PID公式,PID公式网上也是一搜一大把,我也看不懂,在网上找到了PID公式的源代码那就不需要研究他是怎么计算的,没什么意义,就跟1+1为什么等于2一样,我们要用的是公式计算出来的值,至于为什么得到了这样的一个值不是我们所关心的,这个值具体怎么用在网上能找到的相关问题很少,至少我是没找到的,后来经过我反复印证,PID公式计算出来的这个值是一个任意值,所谓的任意值指的是我想要一个什么样的结果就让PID计算出什么样的结果,比如,我要让PID输出的结果在0-100也可以,0-1000-10000-50000都可以,包括输出负数也是可以的,PID核心的东西是我们要用到的这个值,既然这个值是由我们来控制的,那么我就把这个值控制在0-100,这个值我们已经决定好了,这个值怎么应用到实际工程当中呢? 我的目标温度是65℃,实际温度<=60的时候由单片机持续输出低电平信号(持续加热), 当温度>=60.1℃的时候开始用PID加热方式,所谓的PID加热方式就是,把PID计算出来的值用作加热的时间,这个时间怎么对应呢,刚刚我们提到过PID的值由我们决定让他的结果在0-100之内,然后我们利用定时器设置一个定时时间在10毫秒钟的加热周期(这里按照自己实际项目来调整,只能先进行测试之后得到一个大概值,在结合实际情况来调整),当PID算出来的结果是100,那么就是加热10ms*100(也就是持续加热1秒中),当PID的值是25的时候就是加热10*25=250ms(还有750ms是处于不加温的时间段),这个时候PID的值和加热的时间已经对应上了,这个不难理解,到了这里PID这个公式本身也算是讲完了,但是在实际应用的时候还有非常多的问题,这次一并把个人所得得经验也分享出来,刚刚讲到到了60.1℃就开启PID算法(开启就是让PID公式计算一次,得到一个值,既然是要让PID自行控温,那么就需要不停得让PID进行计算,一旦PID得值发生了变化,控制加热得时间也就变化了,那么PID多长时间计算一次呢,这个问题没有人能回答,只能说按照实际工程来调整,我测试加热得时候是每2秒中计算一次,如果用在电机上进行调速2秒中计算一次肯定不行,调速的话肯定是毫秒级别了), 3:PID参数的调整,第2部分所以的功能已经完善了,但是要想达到很高的精度还得进行PID的三个参数调整,P值,I值,D值,这个三个参数调整也是最费时间的,也是最难调整的,我也是查阅了大量相关资料才慢慢调出来,前前后后调了3天,第4天才算是稳定下来了。 说一下我的调整经验吧,首先调P值,I和D全部设定为0,P值可以从1开始调,慢慢加,调到什么样才算正常呢?还是拿我的经验来说吧,目标温度65℃,当PID控制温度在65℃上下徘徊的时候就是最佳状态(我的实际情况是P值设定为15的时候,最高温度是在66.3,最低温度在63.9),简单的说就是P值调到在目标值在设定值上下徘徊的时候就对了(徘徊幅度越小越好)。 好了这个时候就开始调整I值,I值得设定也是和P值一样,慢慢调试,我刚开始是从1开始往上加,结果发现整个PID都失去控制了,因为是第一次用PID也是没经验,查了资料才知道I值一般都是很小,然后开始从0.1开始调整,反正就是一直调整呢,最后把I值调整在0.05的时候温度已经很平稳了,这个时候实际温度稳定在64.5-65.4之间了,和没有I值得时候相对稳定一些了,关键得问题是时间越长越稳定,个人觉得I值调整是在P值得基础上让实际温度和无限接近设定温度(上下浮动越小越好),I值确定了,开始调D值,D值调整的目的是为了弥补PID因为环境温度变化或者是加热器件的功率变化导致控温误差变大而来的,所以我在调整D值得时候拿一个扇子给加热器件进行加速散热,后来把D值确定在0.03的时候发现用扇子额外散热和不用扇子的已经没有什么区别了。调完I值得时候可以发现D值调不调整感觉意义也不大了,之前查到得资料D值得作用就是能预测未来(预测未来是个人得一个理解,这也是PID得精华所在),这个所谓得预测未来的值,是当外界加热环境或者加热功率发生了变化依然不影响之前所调整得精度,比如你夏天调好得精度,不会因为到了冬天而让精度发生了变化,当然了这个也不是绝对得,比如你之前用的是100W得加热方式在调整,你突然把加热器换成2000W的加热器,那肯定是不行的,也没有哪个PID算法能做到这么大的范围让它自动调整(串级PID估计可以达到这个条件)。 //----------------------------------- 4:下面开始分享PID源代码是怎么使用的, float pid_p;//P值 float pid_i;//I值 float pid_d;//D值 unsigned intZLG_pid_val_mid;//PID计算的值存放变量, /************************ZLG_PID控制算法*************/ void ZLG_PID() {
int dError=0,Error=0,B; //--------------------- Error=ZLG_SpeedSet-ZLG_CurrentSpeed;//当前误差 //PID算法第一步 设定转速减去当前转速 赋值给 Error ZLG_sumError=Error+ZLG_sumError;//误差和 dError=Error-ZLG_lastError;//误差偏差 ZLG_lastError=Error; B=pid_p*Error+pid_i*ZLG_sumError+pid_d*dError; //---------------------- if(B>100) ZLG_pid_val_mid=100;//pid_val_midPWM占空比宽带/ //-------------------- if(B<0) ZLG_pid_val_mid=0;// PWM占空比宽带 //---------------------- if(B>=0&&B<=100) ZLG_pid_val_mid=B;//PID计算出来的值存放在这里,
} 这个函数就是PID的核心,每调用一次就进行一次PID的计算(每计算一次也就会得到一个PID计算出来的值,这个值就是我上面提到的加热时间)
PID本身的计算方法这里就已经完成了,但是这个值具体怎么使用呢,PID本身又该怎么调用呢? 我这里用到了2个定时器,定时器1每隔2秒中进行一次PID运算(2秒中的时间也是我调试出来的,具体项目具体调整),代码如下: if(TIM4->SR&0X0001)//溢出中断 { P0_xin_hao_Time++;//P0信号灯闪烁 //---------------------------- //ZLG PID运算 if(biao_zhi_wei.ZLG_PID_kai_guan==1)//ZLGPID启动了,温度到了60.1℃开始进行PID计算 { ZLG_PID_Time++;//PID计算周期变量 if(ZLG_PID_Time>=2)//定时器1秒进入一次中断 2次就是2秒,所以每隔2秒做一次PID运算。 { ZLG_PID_Time=0;//清0 ZLG_PID();//每2秒中计算一次ZLG_PID的值 } } } 这是STM32的代码。 我这里只贴出了运算,具体定时器启动的设置就不贴出来了,大概原理就是当温度到了60.1℃定时器1开始启动,每隔2秒中产生一次中断,在中断里面进行一次PID运算,这个非常简单。 定时器2做为加热时间的判断(类似于PWM),通样只贴出部判断部分代码,代码如下: if(biao_zhi_wei.ZLG_PID_kai_guan==1)//ZLGPID启动了,温度到了60.1℃之后进行加热时间的判断 {
ZLG_c++; //每次定时器溢出加1 //ccc=ZLG_c; if(ZLG_pid_val_mid>=ZLG_c) { ZLG_LED=0; //BEEP=0; } if(ZLG_pid_val_mid<ZLG_c) { ZLG_LED=1; // BEEP=1;
} if(ZLG_c>=100) { ZLG_c=0; //ccc=ZLG_c; } } } 这段代码的原理就是,每产生一次中断(中断时间10ms)计数器+1(自己定义的一个变量),当PID的值>=PID计算出来的值那就输出低电平(开启加热),反过来就是输出高电平了,如果PID计算出来得值超过了100,那就持续加热就完了. 到了这里,PID得所有东西都讲完了,PID本身也不是很难,只要知道怎么用剩下得就是慢慢调整了,而且用在加热上面算是最简单了。 简单的叙述一下PID的加热原理 1:当目标温度接近设定温度(我设计的是相差5)开启PID运算 2:定时器1每隔2秒中产生一次PID运算(这个时间实际情况调整) 3:定时器2每隔10ms产生一次中断并做记录(也是实际情况调整),PID计算出来的值和记录值想比较,时间到了就切换加热或者不加热 前3条整个PID的动作都完成了,剩下的就是调整PID的 P I D三个参数 调整方法 先调P值,效果达到实际温度在目标温度上下徘徊,徘徊浮动越小越好,此时P值调完, 再调I值,I值非常,我调整的是0.05,这个时候在调整I值得时候会发现实际温度和目标温度非常接近,上下浮动也是非常小,直至达到要求。 最后调D值,P和I调完后我发现D调不调精度都是很好,后来查到D值得作用就是能预测未来(这是我自己得理解,也许有误),D值得作用上面也提到了,这里就不再提了。
以上都是个人经验所得,个人能力有限,也许很多地方理解错误了,请多包涵。。。
|