tangcangeng 发表于 2014-6-3 10:28:06

万般无奈只好求助:请分析一下我的PID温控问题出现在哪?

本帖最后由 tangcangeng 于 2014-6-3 11:02 编辑

我照着一个老帖子http://www.amobbs.com/thread-936512-1-1.html做了温度PID恒温控制实验,温度传感器采用的是跟这个老帖子一样的MAX6675,用300W加热片加热一个1斤重的铁块,按照Ziegler-Nichols法来调参数,可是当我逐渐加大Kp这个系数的时候,出现的振荡很奇怪,最后以这个奇怪的振荡显现的振荡周期对另外两个参数KI和Kd进行计算后进行PID恒温控制,效果很不好 振荡的很厉害,我目标温度设置为70度,但是实际效果总是在75度到69度之间振荡 调了一个多月了也熬了好几个晚上的夜总是调不好 现在万般无奈只好求助坛里各位搞技术的同志了,帮我看看问题出现在哪里 是程序的问题还是控制思想出了问题~~在这里先向大家说一下万分的谢谢先了

PID输出u(K)对被控对象是这样子控制的:PID采样周期为2S,温度实时检测, 采用过零检测触发单片机的外部中断对可控硅进行导通控制,每个交流半波的周期是10mS,因此2S中有200个交流半波,PID计算结果u(K)等于多少就让这一个PID周期2S中的200个半波导通多少个,比如u(K)=10则在2S中的200个半波中导通10个半波,其他190个半波不导通。下面实验图片如下:那个炉子只是做一个支撑作用,真正加热的是那个中间银色的300W加热器,上头放了一块1斤重的铁块,中间打了个孔将热电偶锁在上面,然后由MAX6675转换温度数据后读进单片机




下面是我的PID程序:采用位置式子,带积分抗饱和的
void PIDfunc_calc(volatile PID *p)
{       
   p->Ek = (p->Give)-(p->Feedback);//计算出当前的误差E(k)
   p->sum += p->Ek;//计算出累计误差ΣE(k)


//使用条件编译指令进行切换
#if PID_DEBUG//在校正PID参数时,使用宏定义将PID_DEBUG设为1
                //从而执行以下程序
   float a0,a1,a2;

   
   //这里每次都要计算 a0、a1、a2的值
   a0 = p->Kp;
   a1 =(p->Kp)*(p->T)/(p->Ti);
   a2 =(p->Kp)*(p->Td)/(p->T);
   
   
   //计算PID调节器的输出
   p->Output = a0*(p->Ek) + a1*(p->sum) + a2*((p->Ek)-(p->Ek_1));
   
   
#else//当参数校正完成后,那么得到固定的a0、a1、a2的值,
      //使用宏定义将PID_DEBUG设为0,从而执行以下过程
      //当参数校正完成后,初始化时直接为p->a0、p->a1、p->a2赋值,省去计算过程
   p->Output = (p->a0)*(p->Ek) + (p->a1)*(p->sum) + (p->a2)*((p->Ek)-(p->Ek_1));
#endif

   if(PID_WINDUP_PROTECTION)//积分抗饱和处理
       {
          if((p->Output > p->OutMax)||(p->Output < p->OutMin))
          {
       p->sum -= p->Ek;//不增加sum
          }
       }
//输出限幅
   if(p->Output > p->OutMax) p->Output = p->OutMax;
   if(p->Output < p->OutMin) p->Output = p->OutMin;

//保存上一周期的值
   p->LastOutput = p->Output;
   p->Ek_1 = p->Ek;
}

下面这段是过零检测出发外部中断程序程序:
SIGNAL(SIG_INTERRUPT0)//INT0的中断服务程序写法
{
k++;
if(((pid.Output==0)||(pid.Output-k==0))&&(k!=200))
PORTB&=~(1<<2);//PB2输出0
else if((pid.Output-k)>0)
PORTB|=(1<<2);//PB2输出1
if(k==200)
{
k=0;//经过了200个10mS=2S以后,重新将K恢复成第0次触发
pid.Feedback=temperature;//将当前每隔2S的实时温度读到pid结构体参数变量中。
PIDfunc_calc(&pid);//进行一次PID计算
if(pid.Output==0)
PORTB&=~(1<<2);//PB2输出0
else if((pid.Output-k)>0)
PORTB|=(1<<2);//PB2输出1
send_temp_ok=1;//经过200次外部中断触发后,即2S后,可以将温度发送到PC机子显示
}
}

下面是主程序:将实时采集的温度也发送到串口调试助手中
int main(void)
{
while(1)
        {
   temperature=Read_Max6675(0x00);
       if(send_temp_ok)//2S时间到,即可进行重新PID计算和发送温度值
       {
      disp_temp=temperature*25;//将小数点包括进去,因此要放大100倍
          shiwan=disp_temp/(long)100000;
          wan=disp_temp%(long)100000/10000;
          qian=disp_temp%(long)100000%10000/1000;
          bai=disp_temp%(long)100000%10000%1000/100;
          shi=disp_temp%(long)100000%10000%1000%100/10;
          ge=disp_temp%(long)100000%10000%1000%100%10;
      while ( !( UCSRA & (1<<UDRE)) )//在载入新的要发送的数据前,通过检测UDRE 标志等待发送缓冲器为空。该位在发送缓冲器空时被置"1” ;当发送缓冲器包含需要发送的数据时清零。
      ;
      UDR = shiwan+0x30;/* 确认UDR空时,将数据放入缓冲器,然后将接收到的数据freq的高8位发送回PC机子 */
          while ( !( UCSRA & (1<<UDRE)) )//在载入新的要发送的数据前,通过检测UDRE 标志等待发送缓冲器为空。该位在发送缓冲器空时被置"1” ;当发送缓冲器包含需要发送的数据时清零。
      ;
      UDR = wan+0x30;/* 确认UDR空时,将数据放入缓冲器,然后将接收到的数据freq的低8位发送回PC机子 */
          while ( !( UCSRA & (1<<UDRE)) )//在载入新的要发送的数据前,通过检测UDRE 标志等待发送缓冲器为空。该位在发送缓冲器空时被置"1” ;当发送缓冲器包含需要发送的数据时清零。
      ;
      UDR = qian+0x30;/* 确认UDR空时,将数据放入缓冲器,然后将接收到的数据freq的高8位发送回PC机子 */
          while ( !( UCSRA & (1<<UDRE)) )//在载入新的要发送的数据前,通过检测UDRE 标志等待发送缓冲器为空。该位在发送缓冲器空时被置"1” ;当发送缓冲器包含需要发送的数据时清零。
      ;
      UDR = bai+0x30;/* 确认UDR空时,将数据放入缓冲器,然后将接收到的数据freq的低8位发送回PC机子 */
          
          while ( !( UCSRA & (1<<UDRE)) )//在载入新的要发送的数据前,通过检测UDRE 标志等待发送缓冲器为空。该位在发送缓冲器空时被置"1” ;当发送缓冲器包含需要发送的数据时清零。
      ;
      UDR = 0x2E;/* 确认UDR空时,将数据放入缓冲器,然后将接收到的数据freq的低8位发送回PC机子 */
          
          while ( !( UCSRA & (1<<UDRE)) )//在载入新的要发送的数据前,通过检测UDRE 标志等待发送缓冲器为空。该位在发送缓冲器空时被置"1” ;当发送缓冲器包含需要发送的数据时清零。
      ;
      UDR = shi+0x30;/* 确认UDR空时,将数据放入缓冲器,然后将接收到的数据freq的低8位发送回PC机子 */
             while ( !( UCSRA & (1<<UDRE)) )//在载入新的要发送的数据前,通过检测UDRE 标志等待发送缓冲器为空。该位在发送缓冲器空时被置"1” ;当发送缓冲器包含需要发送的数据时清零。
      ;
          UDR = ge+0x30;/* 确认UDR空时,将数据放入缓冲器,然后将接收到的数据freq的低8位发送回PC机子 */
          while ( !( UCSRA & (1<<UDRE)) )//在载入新的要发送的数据前,通过检测UDRE 标志等待发送缓冲器为空。该位在发送缓冲器空时被置"1” ;当发送缓冲器包含需要发送的数据时清零。
      ;
      UDR = 0x20;/* 确认UDR空时,将数据放入缓冲器,然后将接收到的数据freq的低8位发送回PC机子 */
          send_temp_ok=0;
       }
       }
}

705060359 发表于 2014-6-3 10:31:29

楼主想没想过对于这种有滞后环节的系统PID是不能用的?

比如温度升温过慢,积分容易饱和,产生超调。

705060359 发表于 2014-6-3 10:32:59

楼主可以将三个参数产生的控制大小分别画个曲线,看看是哪个参数不争气

tangcangeng 发表于 2014-6-3 10:43:07

705060359 发表于 2014-6-3 10:32
楼主可以将三个参数产生的控制大小分别画个曲线,看看是哪个参数不争气

你好 非常感谢你第一时间回复请重新看下我的帖子 我重新修改了一下内容 帮我分析一下有可能出现错误的是哪里??我怀疑是我的中断程序写的有问题,中断程序中计算应该导通的交流半波的个数,200个中断当然就能判断出2S的时间了 因为每10mS就是一个半波

tangcangeng 发表于 2014-6-3 10:44:22

705060359 发表于 2014-6-3 10:31
楼主想没想过对于这种有滞后环节的系统PID是不能用的?

比如温度升温过慢,积分容易饱和,产生超调。 ...

程序中有带积分抗饱和的

tangcangeng 发表于 2014-6-3 10:55:56

本帖最后由 tangcangeng 于 2014-6-3 14:06 编辑

如果各位有类似的调试程序请帮帮我一下 给我看下你们写的然后我自己分析一下错误在哪里也可以~~PID程序是自己写的也参考了其他人应该差不多我估计问题出现在中断中对输出半波的处理上,或者是max6675的实时采集上除了问题,因为我的实时采集是在主程序的主循环中的,但是max6675采集并转换完成一次温度输出值需要平均200mS的时间 会不会是这个时间太久了 导致PID计算时的当前反馈量不是真正的当前而是有所延时造成的呢? 但是那个老帖子里头又没有出现这个问题 哎真是苦闷啊

tangcangeng 发表于 2014-6-3 11:11:06

帮自己再顶顶 坐等好心人帮我分析分析了 哎~

705060359 发表于 2014-6-3 11:50:08

楼主把积分项减小试试?

tangcangeng 发表于 2014-6-3 14:05:16

705060359 发表于 2014-6-3 11:50
楼主把积分项减小试试?

8楼的你好 我明白您的意思减少积分就是增大我在程序中写的a1 =(p->Kp)*(p->T)/(p->Ti);
这一句的Ti,以便使得系统趋于稳定使得相位不是那么滞后,但是我从Ziegler-Nichols基础上算出的Ti=37一直增大到Ti=150,感觉好像没什么作用后来又在增大Ti=150的基础上将比例Kp由原来的Kp=11减少到Kp=7,好像也没什么用会不会是u(k)的输出对被控对象的控制这个思想上出问题了呢 就是那个中断函数中写的那些语句~~

wjjcyy 发表于 2014-6-3 14:10:01

先调一个参数,看看震荡周期,再加参数,直接使用别人的全套代码,系统是做不稳定的

tangcangeng 发表于 2014-6-3 14:14:31

本帖最后由 tangcangeng 于 2014-6-3 14:18 编辑

wjjcyy 发表于 2014-6-3 14:10
先调一个参数,看看震荡周期,再加参数,直接使用别人的全套代码,系统是做不稳定的 ...

你好 感谢您的关注 代码自己数学推导以及编写的调参数采用尼克尔斯-齐格勒法,我在这个过程中发现单纯增大Kp后出现的振荡的图像很怪不知道如何解释~~,请见图中哪个振荡的图像,然后我按照那个有点怪怪的振荡图像加了Ki以及Kd上去后就变成了最终最下面那个图像了,一直在69度到75度之间来回振荡,按道理来说此时应该会出现感觉还可以的图像,但是就是没有, 应该是程序有问题 但就是不知道哪个环节出错了 当初怀疑自己i写的PID程序是否有问题 但是对比了网上其他人写的 都是差不多的 应该没什么区别~~哎调了很久了 有点郁闷 所以没办法求助各位了 在这里谢谢大家先了

wjjcyy 发表于 2014-6-3 14:30:23

看样子方法是对的,那就看你的数据处理有没有问题了,看哪里是不是有溢出。

tangcangeng 发表于 2014-6-3 16:06:13

wjjcyy 发表于 2014-6-3 14:30
看样子方法是对的,那就看你的数据处理有没有问题了,看哪里是不是有溢出。 ...

好的 我检查一下 谢谢您的提示

marshallemon 发表于 2014-6-3 16:14:45

先把D=0,加大I看效果

tangcangeng 发表于 2014-6-3 17:25:17

marshallemon 发表于 2014-6-3 16:14
先把D=0,加大I看效果

你好 加大 I 的意思就是减少Ti,也就是较少积分的作用是吧?

tangcangeng 发表于 2014-6-3 17:27:08

marshallemon 发表于 2014-6-3 16:14
先把D=0,加大I看效果

顺便再弱弱的问下这位大侠 能否帮我检查一下我的PID位置式程序写的是否是正确的 还有那个抗积分饱和的思路是不是对的 这个抗积分饱和我是看到人家的思路 自己写出来的 心里很没底~~

yirenonege 发表于 2014-6-3 17:56:54

我感觉你的采集和调整速度太慢了,你调整出的均值都是对的,但是你的采集控制跟不上节奏

tangcangeng 发表于 2014-6-4 07:33:38

yirenonege 发表于 2014-6-3 17:56
我感觉你的采集和调整速度太慢了,你调整出的均值都是对的,但是你的采集控制跟不上节奏 ...

是的因为MAX6675采集需要200mS 这个问题不知道如何解决可是我看过老帖子他也是用MAX6675却能无事不知道是怎么回事

jzkn 发表于 2014-6-4 10:32:26

首先考虑滞后,就是你控制了不一定马上有反馈,容易导致过量调节。解决办法一是加大控制间隔,二是降低KP系数。我做过激光器的温度PID,比你这个应该反应的快一点。我可以贴出我的代码。然后有几本书我当时参考了一下,非常有用。PID我也是自己改写过的。
不过我的温度控制跟你的不一样,我有个引脚是控制加热还是制冷。。。。。我还是贴另外一个功率自动控制的吧,跟你的温度控制稍微近似一点:


void APC ( void )                //PIDCalc
{

#define        PKProportion1                        0.3                //泵浦1比例常数Proportional Const
#define PKIntegral1                                0.01        //泵浦1积分常数Integral Const
#define PKDerivative1                         0.1                //泵浦1微分常数Derivative Const
#define        PKDrvtArf                                0.2                //微分部分α常数

//#define         KProportion                2        // 比例常数Proportional Const
//#define        KIntegral                0.1        // 积分常数Integral Const
//#define         KDerivative         0.1        // 微分常数Derivative Const
//Pump_Power =                 adc(0)*25/1023*200 = 2000;                 10Bits A/D
#define         Desiredvalue        411 // 设定目标Desired value        r(t)

        typedef struct STRUCT_PID
        {
                double         LastError;                 // Error[-1]
                double         SumError;                 // Sums of Errors
                double         LastDrt;                //上次微分值
                int                ControlValue;        //控制量         u(t)

        } STRUCT_PID;
//(DAT实际取值范围为0到4095)
        static xdata STRUCT_PID PID = {0.0, 0.0,0.0, PIDIintControlValue};                 // PID Control Structure
        /*
        double xdata dError, Error;
        double xdata Feedback_In;                        // PID Feedback (Input)                AD                c(t)
        double xdata Response_Out;                 // PID Response (Output)        DA                u(t) change
        */
        double xdata Proportion,Differential;
        Feedback_In = adc ( 0 );         // Read Input
        /*当前误差*/
        Error = Desiredvalue - Feedback_In;                 // 偏差                        e(t)
        /*累加误差*/
        PID.SumError += Error;                                                 // 积分
        /*分离积分*/
        if ( fabs ( Error ) >41 ) //误差超过20mW,取消积分项
                PID.SumError=0;
        /*计算各数据项*/
        Proportion=Error; //比例项
        Differential=PKDerivative1* ( 1-PKDrvtArf ) *Error
                   +PKDrvtArf*PID.LastDrt
                   -PKDerivative1* ( 1-PKDrvtArf ) *PID.LastError;//微分项
        /*死区控制*/
        if ( abs ( Error ) < 2 ) //1-0.48mw
        {
                PID.SumError = 0;
                //PID.LastError = 0;
                return;
        }
        /*增量计算*/
        Response_Out= PKProportion1*Proportion                                                        // 比例项
                      + PKIntegral1*PID.SumError                                                // 积分项
                      + Differential;                                                                               // 微分项
        /*记忆参数*/
        PID.LastDrt = Differential;                        //记忆本次微分值
        PID.LastError= Error;         //记忆本次误差
        /*控制值计算*/
        PID.ControlValue += Response_Out;
        /*控制值极限判断*/
        if ( PID.ControlValue < 0 )
                PID.ControlValue = 0;
        else if ( PID.ControlValue > 4095 )
                PID.ControlValue = 4095;

        AD5322 ( ( unsigned int ) ( PID.ControlValue ),1 );

}

下面是几本电子书,重点推荐《新型PID控制及其应用》我看完前几章就会改写了。
PS:别人的始终只能给你灵感和参考,写出适合自己的才是王道。

jzkn 发表于 2014-6-4 10:44:25

我又仔细看了一下你的代码,你采用原始的PID公式应该是不行的,这样比较难调,建议你看看上面的基本书,使用改进PID算法,这样比较容易调整。

你的这个模型跟电厂锅炉是一样的。

PID说实话比较难搞,希望你耐心一点慢慢调。我的建议是先调好控制间隔和KP系数,然后再根据震荡情况调节后面的积分和微分项。

我手里有一本实体书,是一个搞发电厂锅炉温控的工程师写的,你可以买来读一读,或许有很好的启发,这本书是实干出来的,不是理论。
《自动调节系统解析与PID整定》白志刚 编著 化学工业出版社

电子喵星人 发表于 2014-6-4 10:50:31

我用的是ZN算法,也是你看的那个帖子里的。

开始的时候会有震荡,过一会儿就恒温了。

你看看是不是公式计算代入的参数代错了

tangcangeng 发表于 2014-6-4 11:14:54

jzkn 发表于 2014-6-4 10:32
首先考虑滞后,就是你控制了不一定马上有反馈,容易导致过量调节。解决办法一是加大控制间隔,二是降低KP系 ...

谢谢您的回复谢谢我再根据你资料以及代码提供的多反复试验几次,如果成功 会将我如何改进的过程以及效果都发出来给大家分享

tangcangeng 发表于 2014-6-4 11:15:31

电子喵星人 发表于 2014-6-4 10:50
我用的是ZN算法,也是你看的那个帖子里的。

开始的时候会有震荡,过一会儿就恒温了。


谢谢您的回复谢谢 我再试试各种方法,如果成功 会将我如何改进的过程以及效果都发出来给大家分享

coleyao 发表于 2014-6-4 11:51:24

http://www.amobbs.com/thread-5484520-1-1.html27F 有个对PID算法温控进行仿真的小软件,有空的话看看,或许对你有帮助的!{:handshake:}

tangcangeng 发表于 2014-6-4 13:49:14

coleyao 发表于 2014-6-4 11:51
http://www.amobbs.com/thread-5484520-1-1.html27F 有个对PID算法温控进行仿真的小软件,有空的话看看, ...

十分感谢你们这个坛子里的网友真好大家都提出了很多宝贵的意见   觉得搞技术的不容易啊我搞了一个月都快崩溃了 老板天天催实在谢谢你们 剩下就等我根据你们的建议再努力试试了

tangcangeng 发表于 2014-6-9 09:05:48

jzkn 发表于 2014-6-4 10:44
我又仔细看了一下你的代码,你采用原始的PID公式应该是不行的,这样比较难调,建议你看看上面的基本书,使 ...

热心的朋友你好请问一下 控制间隔是不是指的是PID的计算周期?我发现会不会是我的计算周期太短了导致始终无论怎么调Kp(比例参数)都无法形成一个振荡呢?你看下我的这个图片,Kp从一个较小值一直增大到KP=11.5后的温度数据图像,已经基本令人满意了 就是光调比例系数 看这个图像 超调、精度都相当可以了误差我用软件分析了一下大概在±1度左右但是我就是想让他有等幅振荡出现就是出现不了无论我怎么加大比例参数(后面一直加大到Kp=40) 会不会是我增大PID的就算周期应该就会出现你说的等幅振荡了呢?会不会PID计算周期太短估计我图片中加热的铁块散热的太慢 直接就不用其他两个参数了末了 还是要感谢您的热心回复以及好心的代码我看了 跟我的差不多 谢谢你了

jzkn 发表于 2014-6-9 09:22:48

tangcangeng 发表于 2014-6-9 09:05
热心的朋友你好请问一下 控制间隔是不是指的是PID的计算周期?我发现会不会是我的计算周期太短了导 ...

        首先恭喜你调试又进一步!光看图像你这个控制效果也蛮不错了。但是这个精度如果是在我的项目中话还不够。你想要等幅震荡有点难,因为铁块加热和散热这个操作起来感觉不是很线性。那么你去掉微分和积分系数,只要比例,按一般的理想模型,最后肯定是等幅的震荡。
        根据我有限的经验,比例系数只是控制刚开始调节时到达目标值的控制速度,和最后的稳态振幅。要进一步提高控制精度,只有增加积分和微分项。按照你目前的情况,比例系数可以先不管了,先填加积分项增加稳定性。系数先取小,然后慢慢调整。我倒是觉得微分项对你这个案例来说没什么用。因为微分项是作为预判的,提前防止变化。比如你下一步温度要降低,那么它会将你的加热控制值增加,由于你的铁块散热肯定比较慢,我个人感觉不是很需要微分。当然,你可以先添加积分再添加微分,都看看效果。这个PID都是实际调整试验出来的,光靠理论也不行,毕竟公式都是数学模型,跟你具体的物理模型不一定完全契合。
        我的PID经验其实也不是很丰富,以上只是个人的一点点小建议,仅供参考哈。欢迎继续交流。

tangcangeng 发表于 2014-6-9 10:28:11

jzkn 发表于 2014-6-9 09:22
首先恭喜你调试又进一步!光看图像你这个控制效果也蛮不错了。但是这个精度如果是在我的项目中话还不够 ...

当然,你可以先添加积分再添加微分,都看看效果。好的 我本来是想用ZN法确定出其他I 和D这两个参数的 可是既然振荡一直不出现 也只好按照你的说法 先加I进去 刚开始从一个最小值开始 然后慢慢增加上去看一下效果了这样子的话 I 和D 这两个参数就不能像ZN法那样比较容易确定了谢谢你~

tangcangeng 发表于 2014-6-12 15:19:01

jzkn 发表于 2014-6-9 09:22
首先恭喜你调试又进一步!光看图像你这个控制效果也蛮不错了。但是这个精度如果是在我的项目中话还不够 ...

你好 由于我无法调出等幅振荡周期曲线,因此只能靠手调,下面是两幅最终效果图以便对比,个人觉得单纯P的效果比较好第一幅是纯P图片 第二幅是加入I 和D的图片 超调量一样 但是调节时间纯P环节比较好 但是加入I和D后稳定点好像

tangcangeng 发表于 2014-6-12 16:01:33

各位靠手调基本解决了谢谢各位

jzkn 发表于 2014-6-12 16:18:31

tangcangeng 发表于 2014-6-12 16:01
各位靠手调基本解决了谢谢各位

        恭喜你。效果还是不错的。

tangcangeng 发表于 2014-6-12 16:20:33

jzkn 发表于 2014-6-12 16:18
恭喜你。效果还是不错的。

谢谢 精度在±0.75度左右 有时候会有抖动的噪声 那是MAX6675造成的 如果换成DS18B20可能噪声会小一点

蓝蓝的恋 发表于 2014-6-12 16:46:56

6675精度不是很高吧~{:smile:}

houyusheng 发表于 2014-6-12 18:09:24

弱弱的问一句,温度曲线是怎么测的,用什么测量的?

guozs1984 发表于 2014-6-12 22:01:20

温控要考虑 散热 及 加热 两方面的影响。
还要考虑周围环境温度的影响。

tangcangeng 发表于 2014-6-13 14:04:39

guozs1984 发表于 2014-6-12 22:01
温控要考虑 散热 及 加热 两方面的影响。
还要考虑周围环境温度的影响。

是的 这位网友 是不是搞自平衡车的??
不知道代码写之前的建模你们怎么弄的??

tangcangeng 发表于 2014-6-14 10:15:26

705060359 发表于 2014-6-3 11:50
楼主把积分项减小试试?

你好 确实是应该减小积分   而且这个积分刚开始得特别小 我最后调到Ti=0.025就差不多了

LJW 发表于 2014-6-18 12:54:33

对PID感兴趣,关注

tangcangeng 发表于 2014-6-18 16:54:26

LJW 发表于 2014-6-18 12:54
对PID感兴趣,关注

请学好《信号与系统》、《自动控制原理》再谈数字PID的编程与实现吧

yuyu87 发表于 2014-6-18 17:07:12

tangcangeng 发表于 2014-6-18 16:54
请学好《信号与系统》、《自动控制原理》再谈数字PID的编程与实现吧

不知道楼主调的怎么样了,
我最近也在搞PID,也是用MAX6675,感觉这个温度采集误差有个一两度的误差,
可能我的温度较高误差也相应较大,
我的控制温度在450度左右,

加热的的锡缸,

由于锡缸加热滞后特别明鲜,比如我全功率加热,加热关断后至少50秒后,温度才保持,然后慢慢再下降,

所以PID参数咋弄也调不好,现在误差在8度左右,我看人家的控制温度基本不跳,也就是1度之内

我积分时间为240秒,但感觉有时候振荡周期都超过100秒以上了,

哎,好难搞,

不知道楼主调的怎么样了,

tangcangeng 发表于 2014-6-19 07:43:26

本帖最后由 tangcangeng 于 2014-6-19 07:44 编辑

yuyu87 发表于 2014-6-18 17:07
不知道楼主调的怎么样了,
我最近也在搞PID,也是用MAX6675,感觉这个温度采集误差有个一两度的误差,
可 ...

建议你PID采样周期为50S/10=5S,不要加入什么积分和微分,从单纯比例P开始从小到大慢慢增加看看有否出现基本等幅振荡先,我的是1斤重铁块也是很滞后的,不过你可以看我最后调出来的图像在±0.75度左右,偶尔会有一些±1°的跳跃,那是MAX6675的噪声 ,没办法的事情

yelang1124 发表于 2014-6-19 08:17:19

坛里有一个西门子的自整定的pid代码,pid写的相当好,我跟你的控温方式差不多,轻松0.1,只要是温度采集精度我们是0、01,另外读温度的时间点要选在一个加热过程的最后,有一个热平衡时间,那里读的温度稳定

tangcangeng 发表于 2014-6-19 10:10:21

yelang1124 发表于 2014-6-19 08:17
坛里有一个西门子的自整定的pid代码,pid写的相当好,我跟你的控温方式差不多,轻松0.1,只要是温度采集精 ...

精度按控制来说0.1是可以的 但是MAX6675的精度不高的 而且有噪声 所以我感觉如果是用MAX6675来做温度采集的话 一般±1°就相当不错了

kangup2015 发表于 2016-8-3 14:03:31

jzkn 发表于 2014-6-4 10:32
首先考虑滞后,就是你控制了不一定马上有反馈,容易导致过量调节。解决办法一是加大控制间隔,二是降低KP系 ...

你好,最近也在做控温,看你的描述 滞后系统加大调整间隔 是有效的 但是会增加调整时间 想问兄台怎么兼顾稳定性和调整时间

光明星1号 发表于 2018-3-9 09:23:13

tangcangeng 发表于 2014-6-4 07:33
是的因为MAX6675采集需要200mS 这个问题不知道如何解决可是我看过老帖子他也是用MAX6675却能无事   ...

无意中看到这个老贴,根据我的经验,MAX6675的200ms采样转化时间不会影响PID的响应,这个我做过实验,至少不会影响你这种加热铁块的系统
这种系统的惯性并不大,还是比较容易调节的

光明星1号 发表于 2018-3-9 10:22:18

tangcangeng 发表于 2014-6-12 16:01
各位靠手调基本解决了谢谢各位

ZN法自整定是一种简单,普遍的方法,我觉得你不能放弃自整定,理论只用P(比例),是可以调出等幅震荡的,此时再获取临界参数。
手动调试是出来了,ZN法不行,证明还是有没有解决的部分。

光明星1号 发表于 2018-3-9 10:25:04

蓝蓝的恋 发表于 2014-6-12 16:46
6675精度不是很高吧~

MAX6675是接热电偶的,引入干扰的途径就比DS18B20多的多,这里在乎的不是精度,而是稳定性,有+——0.75的偏差,就是抗干扰没有做好!
页: [1]
查看完整版本: 万般无奈只好求助:请分析一下我的PID温控问题出现在哪?