历史上的今天
返回首页

历史上的今天

今天是:2026年03月21日(星期六)

正在发生

2023年03月21日 | pid算法温度控制c语言程序

2023-03-21 来源:elecfans

  温度控制PID自整定原理介绍

  整定PID(三模式)控制器

  整定温度控制器涉及设置比例、积分和微分值,以得到对特定过 程的可能的最佳控制。如果控制器不包含自动整定算法,或者自 动整定算法未提供适合特定应用的足够控制,则必须用试误法对 装置进行整定。


  下面是温度控制器的标准整定步骤。也可以采用其他整定步骤, 但都使用类似的试误法。请注意,如果控制器使用机械式继电器 (而非固态继电器),开始时应使用较长的循环时间(20秒)。


  可能需要用到以下定义 :

  循环时间 – 也称为工作周期,是控制器完成一个通断循环所 用的总时间长度。示例: 对于20秒的循环时间,10秒接通时 间和10秒切断时间代表50%的功率输出。在比例带内时,控 制器将循环接通和切断。


  比例带 – 以满量程的%或度表示的温度范围,控制器的比例 作用发生在此范围内。比例带越宽,在其内发生比例作用的 围绕设定值的区域越大。有时也用增益表示,增益是比例带 的倒数。


  积分,又称为复位,是根据设定值调节比例带宽以补偿偏离 设定值的偏移量(固定偏差)的一个函数,也就是说,它在 系统稳定后将控制的温度调节到设定值。


  微分,又称为速率,感应系统温度上升或下降的速率,并自 动调节比例带,从而将下冲或过冲降到最小。


  PID(三模式)控制器如果正确整定和使用的话,能具有优异的 控制稳定性。通过认真遵守这些指示,操作人员便可实现最快的 响应时间和最小的过冲。整定这种三模式控制器的信息可能不同 于其它控制器整定步骤。对于主输出,通常用自整定功能就可省 去使用此手动整定步骤的需要,但是,需要时可对自整定值进 行调整。


  A.整定加热控制的输出

  启用输出并启动过程。

  过程应在设定值处运行,将用所需热量输入让温度稳定。

  在速率和复位断开的情况下,温度将稳定,并在设定值和实际 温度之间存在稳态偏差,或固定偏差。通过观察显示屏上的测 量值,密切注意此温度是否存在规则的循环或振荡。(振荡可 长达30分钟。)

  pid算法温度控制c语言程序

  4.如果温度没有规则的振荡,将PB除以2(见图1)。让过程 稳定下来,然后再检查是否有温度振荡。如果仍无振荡, 再将PB除以2。重复此操作,直到得到循环或振荡。转至 第5步。

  5.如果马上观察到振荡,将PB乘以2。观察得到的温度几分 钟。如果振荡持续,以系数2不断乘PB,直到振荡停止。

  此时,PB非常接近其临界设置。小心地增大或减小PB设 置,直到温度记录中刚刚出现循环或振荡为止。

  如果甚至在1%的最小PB设置时过程温度仍不发生振荡, 请跳过下面的第6步到第11步,转至第B条。

  在已经达到的“临界”BP设置下,读取设定值与实际温度 之间的稳态偏差,或固定偏差。(由于温度有一点循环, 请使用平均温度。)

  测量相邻波峰或波谷之间的振荡时间,以分为单位 (见图2)。使用图表记录仪最容易进行这种测量,但可每 隔一分钟读取一次测量值,以掌握时间。

  此时,增大PB设置,直到温度偏差(或固定偏差)增大 65%。

  pid算法温度控制c语言程序

  用在“临界”BP设置下得到的初始温度偏差乘以1.65或者 使用方便的线列图I(见图4)就可计算出所需的最终温度偏 差。用试误法尝试几次PB控制的设置,直到得到所需的最终 温度偏差。

  pid算法温度控制c语言程序

  此时您已经完成了得到控制器最佳性能所需的所有测量。 只需再做两项调整 – 速率和复位。

  使用第7步中测得的振荡时间,按以下方法计算复位值, 以每分钟重复次数为单位。

  pid算法温度控制c语言程序

  将此值输入给RESET 1。

  再使用第7步中测得的振荡时间,按以下方法计算速率的 值,以分为单位。

  pid算法温度控制c语言程序

  将此值输入给RATE 1。

  如果出现过冲,可通过减少复位时间来消除。当对复位值 进行了更改时,也应对速率调整进行相应的更改,使速率值 等于:

  pid算法温度控制c语言程序

  即:如果复位 = 2 R/M,则速率= 0.08分钟

  若想在对系统扰动的“响应时间”和“设置时间”之间得到 正确的平衡,可能需要进行多次设定值更改和随之发生的复 位和速率控制时间调整。快速响应常常伴随着较大的过冲, 过程“稳定下来”所需的时间也较短。相反,如果响应较 慢,过程趋向于慢慢滑行到最终值,过冲很小或者没有过 冲。应由系统的要求决定采取哪种动作。

  当得到满意的整定时,应增大循环时间以节省接触器的寿命 (适用于只有时间比例输出的装置(TPRI))。在不造成测量 值因负载循环而振荡的情况下,应尽量增大循环时间。

  转至第C节。

  B. 未观察到振荡时的整定步骤

  在最小PB设置下,测量设定值与实际温度之间的稳态偏 差,或固定偏差。

  增大PB设置,直到温度偏差(固定偏差)增大65%。线列 图I(见图4)提供了计算所需最终温度偏差的简便方法。

  将RESET 1设置为一个较高的值(10 R/M)。将RATE 1设 置为一个对应的值(0.02分)。此时,因复位作用,测 量值应稳定在设定温度。

  由于我们无法确定临界振荡时间,必须用试误法确定复 位和速率调整的最佳设置。在温度稳定在设定值后,将 设定温度的设置增加10度。观察实际温度上升过程中伴 随的过冲。然后将设定温度的设置返回其初始值,再观 察实际温度上升过程中伴随的过冲。 过冲过大表明复位和/或速率值设置得太高。过阻尼响应 (无过冲)表明复位和/或速率值设置得太低。请参看图 7。需要改善性能时,一次改变一个整定参数,并观察设 定值改变时该参数对性能的影响。让参数递增变化,直 到性能得到优化。

  当得到满意的整定时,应增大循环时间以节省接触器的寿 命(适用于只有时间比例输出的装置(TPRI))。在不造成 测量值因负载循环而振荡的情况下,尽量增大循环时间。

  pid算法温度控制c语言程序

  图7:设置复位和/或速率

  C. 整定冷却控制的主输出

  使用与加热相同的步骤。过程应在一个设定值处运行,要求 在温度稳定前进行冷却控制。

  D. PID控制器的简化整定步骤

  下面的步骤是分析过程对步进输入的响应曲线的图形方法。 使用长图记录仪读取过程变量(PV)会更加简单。

  从冷启动(PV在室温下)开始,在控制器不在环路中的 情况下(即开环时)以最大功率给过程供电。记录此开 始时间。

  经过一些延迟后(让热量到达传感器),PV将开始上 升。再经过一段延迟后,PV将达到最大变化速率 (斜率)。记录出现该最大斜率时的时间以及此时的 PV。记录最大斜率,以度/分为单位。关闭系统电源。

  从最大斜率点开始向后到环境温度轴画一条线,得到总 系统延时Td(见图8)。也可以用下面的公式得到延时: Td = 达到最大斜率时的时间-(最大斜率处的PV – 环境温度)/ 最大斜率s

  应用下面的公式获得PID参数:

  比例范围 = Td x 最大斜率x 100/量程 = 量程的%

  复位 = 0.4 / Td =次/分

  速率 = 0.4 x Td = 分

  重启系统,在控制器处在环路中的情况下将过程带到设 定值,并观察响应。如果响应过冲太大或者振荡,可以 在以下方向改变PID参数(稍稍改变,一次改变一个参 数,并观察过程响应):加宽比例带,降低复位值,并增大速率值。

  示例: 图8中的图表记录是在以最大功率给加热炉供电时获 得的。图表比例尺为10?F/cm和5分/cm。控制器范围为 100 ~ 600?F,或者说500?F的量程。

  示例: 图8中的图表记录是在以最大功率给加热炉供电时获 得的。图表比例尺为10°F/cm和5分/cm。控制器范围为 100 ~ 600°F,或者说500°F的量程。

  最大斜率 = 18°F/5分

  = 3.6°F/分

  延时 = Td = 大约7分

  比例带 = 7分x3.6°F/分 x 100/500°F = 5%。

  复位 = 0.4 /7分 = 0.06次/分

  速率 = 0.4 x 7分 = 2.8分

  pid算法温度控制c语言程序

  图8:系统延时



  pid算法温度控制c语言程序

  基于PID算法的温度控制系统 89C51单片机,通过键盘输入预设值,与DS18B20测得的实际值做比较,然后驱动制冷或加热电路。用keil C语言来实现PID的控制。
 

  #include《reg51.h》

  #include《intrins.h》

  #include《math.h》

  #include《string.h》

  struct PID {

  unsigned int SetPoint; // 设定目标 Desired Value

  unsigned int ProporTIon; // 比例常数 ProporTIonal Const

  unsigned int Integral; // 积分常数 Integral Const

  unsigned int DerivaTIve; // 微分常数 DerivaTIve Const

  unsigned int LastError; // Error[-1]

  unsigned int PrevError; // Error[-2]

  unsigned int SumError; // Sums of Errors

  };

  struct PID spid; // PID Control Structure

  unsigned int rout; // PID Response (Output)

  unsigned int rin; // PID Feedback (Input)

  sbit data1=P1^0;

  sbit clk=P1^1;

  sbit plus=P2^0;

  sbit subs=P2^1;

  sbit stop=P2^2;

  sbit output=P3^4;

  sbit DQ=P3^3;

  unsigned char flag,flag_1=0;

  unsigned char high_time,low_time,count=0;//占空比调节参数

  unsigned char set_temper=35;

  unsigned char temper;

  unsigned char i;

  unsigned char j=0;

  unsigned int s;

  /***********************************************************

  延时子程序,延时时间以12M晶振为准,延时时间为30us×time

  ***********************************************************/

  void delay(unsigned char time)

  {

  unsigned char m,n;

  for(n=0;n《time;n++)

  for(m=0;m《2;m++){}

  }

  /***********************************************************

  写一位数据子程序

  ***********************************************************/

  void write_bit(unsigned char bitval)

  {

  EA=0;

  DQ=0; /*拉低DQ以开始一个写时序*/

  if(bitval==1)

  {

  _nop_();

  DQ=1; /*如要写1,则将总线置高*/

  }

  delay(5); /*延时90us供DA18B20采样*/

  DQ=1; /*释放DQ总线*/

  _nop_();

  _nop_();

  EA=1;

  }

  /***********************************************************

  写一字节数据子程序

  ***********************************************************/

  void write_byte(unsigned char val)

  {

  unsigned char i;

  unsigned char temp;

  EA=0; /*关中断*/

  TR0=0;

  for(i=0;i《8;i++) /*写一字节数据,一次写一位*/

  {

  temp=val》》i; /*移位操作,将本次要写的位移到最低位*/

  temp=temp&1;

  write_bit(temp); /*向总线写该位*/

  }

  delay(7); /*延时120us后*/

  // TR0=1;

  EA=1; /*开中断*/

  }

  /***********************************************************

  读一位数据子程序

  ***********************************************************/

  unsigned char read_bit()

  {

  unsigned char i,value_bit;

  EA=0;

  DQ=0; /*拉低DQ,开始读时序*/

  _nop_();

  _nop_();

  DQ=1; /*释放总线*/

  for(i=0;i《2;i++){}

  value_bit=DQ;

  EA=1;

  return(value_bit);

  }

  /***********************************************************

  读一字节数据子程序

  ***********************************************************/

  unsigned char read_byte()

  {

  unsigned char i,value=0;

  EA=0;

  for(i=0;i《8;i++)

  {

  if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/

  value|=0x01《《i;

  delay(4); /*延时80us以完成此次都时序,之后再读下一数据*/

  }

  EA=1;

  return(value);

  }

  /***********************************************************

  复位子程序

  ***********************************************************/

  unsigned char reset()

  {

  unsigned char presence;

  EA=0;

  DQ=0; /*拉低DQ总线开始复位*/

  delay(30); /*保持低电平480us*/

  DQ=1; /*释放总线*/

  delay(3);

  presence=DQ; /*获取应答信号*/

  delay(28); /*延时以完成整个时序*/

  EA=1;

  return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/

  }

  /***********************************************************

  获取温度子程序

  ***********************************************************/

  void get_temper()

  {

  unsigned char i,j;

  do

  {

  i=reset(); /*复位*/

  }while(i!=0); /*1为无反馈信号*/

  i=0xcc; /*发送设备定位命令*/

  write_byte(i);

  i=0x44; /*发送开始转换命令*/

  write_byte(i);

  delay(180); /*延时*/

  do

  {

  i=reset(); /*复位*/

  }while(i!=0);

  i=0xcc; /*设备定位*/

  write_byte(i);

  i=0xbe; /*读出缓冲区内容*/

  write_byte(i);

  j=read_byte();

  i=read_byte();

  i=(i《《4)&0x7f;

  s=(unsigned int)(j&0x0f);

  s=(s*100)/16;

  j=j》》4;

  temper=i|j; /*获取的温度放在temper中*/

  }

  /*====================================================================================================

  Initialize PID Structure

  =====================================================================================================*/

  void PIDInit (struct PID *pp)

  {

  memset ( pp,0,sizeof(struct PID));

  }

  /*====================================================================================================

  PID计算部分

  =====================================================================================================*/

  unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint )

  {

  unsigned int dError,Error;

  Error = pp-》SetPoint - NextPoint; // 偏差

  pp-》SumError += Error; // 积分

  dError = pp-》LastError - pp-》PrevError; // 当前微分

  pp-》PrevError = pp-》LastError;

  pp-》LastError = Error;

  return (pp-》Proportion * Error//比例

  + pp-》Integral * pp-》SumError //积分项

  + pp-》Derivative * dError); // 微分项

  }

  /***********************************************************

  温度比较处理子程序

  ***********************************************************/

  compare_temper()

  {

  unsigned char i;

  if(set_temper》temper)

  {

  if(set_temper-temper》1)

  {

  high_time=100;

  low_time=0;

  }

  else

  {

  for(i=0;i《10;i++)

  { get_temper();

  rin = s; // Read Input

  rout = PIDCalc ( &spid,rin ); // Perform PID Interation

  }

  if (high_time《=100)

  high_time=(unsigned char)(rout/800);

  else

  high_time=100;

  low_time= (100-high_time);

  }

  }

  else if(set_temper《=temper)

  {

  if(temper-set_temper》0)

  {

  high_time=0;

  low_time=100;

  }

  else

  {

  for(i=0;i《10;i++)

  { get_temper();

  rin = s; // Read Input

  rout = PIDCalc ( &spid,rin ); // Perform PID Interation

  }

  if (high_time《100)

  high_time=(unsigned char)(rout/10000);

  else

  high_time=0;

  low_time= (100-high_time);

  }

  }

  // else

  // {}

  }

  /*****************************************************

  T0中断服务子程序,用于控制电平的翻转 ,40us*100=4ms周期

  ******************************************************/

  void serve_T0() interrupt 1 using 1

  {

  if(++count《=(high_time))

  output=1;

  else if(count《=100)

  {

  output=0;

  }

  else

  count=0;

  TH0=0x2f;

  TL0=0xe0;

  }

  /*****************************************************

  串行口中断服务程序,用于上位机通讯

  ******************************************************/

  void serve_sio() interrupt 4 using 2

  {

  /* EA=0;

  RI=0;

  i=SBUF;

  if(i==2)

  {

  while(RI==0){}

  RI=0;

  set_temper=SBUF;

  SBUF=0x02;

  while(TI==0){}

  TI=0;

  }

  else if(i==3)

  {

  TI=0;

  SBUF=temper;

  while(TI==0){}

  TI=0;

  }

  EA=1; */

  }

  void disp_1(unsigned char disp_num1[6])

  {

  unsigned char n,a,m;

  for(n=0;n《6;n++)

  {

  // k=disp_num1[n];

  for(a=0;a《8;a++)

  {

  clk=0;

  m=(disp_num1[n]&1);

  disp_num1[n]=disp_num1[n]》》1;

  if(m==1)

  data1=1;

  else

  data1=0;

  _nop_();

  clk=1;

  _nop_();

  }

  }

  }

  /*****************************************************

  显示子程序

  功能:将占空比温度转化为单个字符,显示占空比和测得到的温度

  ******************************************************/

  void display()

  {

  unsigned char code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};

  unsigned char disp_num[6];

  unsigned int k,k1;

  k=high_time;

  k=k%1000;

  k1=k/100;

  if(k1==0)

  disp_num[0]=0;

  else

  disp_num[0]=0x60;

  k=k%100;

  disp_num[1]=number[k/10];

  disp_num[2]=number[k%10];

  k=temper;

推荐阅读

史海拾趣

Cincon公司的发展小趣事

创新是Cincon持续发展的动力。2003年,公司在台北设立了研发中心,专注于电源产品的技术创新和研发。这一举措极大地提升了公司的技术实力和产品创新能力。几年后,Cincon成功设计并制造了LED电源,进一步丰富了产品线,并满足了市场对高效节能照明解决方案的需求。

Colibrys SA公司的发展小趣事

2013年,Colibrys迎来了一个重要的转折点——成为SAFRAN集团公司的一部分。这一转变不仅为公司带来了更多的资源和市场支持,也使其在MEMS领域的技术研发和应用得到了进一步的提升。作为SAFRAN网络的一部分,Colibrys能够充分利用网络提供的服务,将其专业的MEMS制造技能传递给更多的客户。

德索五金(dosinconn)公司的发展小趣事

发展历程:2007年,公司率先在业内引入了ERP系统,实现了企业高效智能的生产管理、财务管理、物流管理和决策管理。这一创新举措极大地提升了客户订单的响应速度,使德索五金电子步入了数字化信息时代。

成果与影响:ERP系统的引入使德索五金电子的管理水平迈上了新的台阶,为企业的快速发展提供了有力支持。

Excelics [Excelics Semiconductor, Inc.]公司的发展小趣事

人才是企业发展的核心竞争力。Excelics Semiconductor深知这一点,因此他们非常重视人才的引进与培养。公司设立了专门的研发部门,吸引了大量优秀的半导体技术人才。同时,他们还建立了完善的培训体系,不断提升员工的技能和素质。这些举措为公司的持续发展提供了坚实的人才保障。

Gardner Denver公司的发展小趣事

人才是企业发展的核心竞争力。Excelics Semiconductor深知这一点,因此他们非常重视人才的引进与培养。公司设立了专门的研发部门,吸引了大量优秀的半导体技术人才。同时,他们还建立了完善的培训体系,不断提升员工的技能和素质。这些举措为公司的持续发展提供了坚实的人才保障。

Aborn Electronics Inc公司的发展小趣事

随着电子行业的快速发展,Aborn Electronics意识到只有不断创新才能在竞争中保持领先。公司加大了对研发的投入,引进了一批高素质的研发人才,并在多个技术领域取得了重要突破。其中,一项关于高效能电源管理技术的创新成果,不仅提高了产品的能效比,还为公司带来了可观的经济效益。这一技术的成功应用,进一步提升了Aborn Electronics在行业内的影响力。

问答坊 | AI 解惑

PC式硬盘录像机死机全接触(一)

PC式硬盘录像机死机全接触 在使用PC式的硬盘录像机的过程中,难免会遇到许多诸如死机等突发故障,对于平时工作正常的较新机子而言,其中大多数死机都是软件停止了响应造成的,只要强制关闭了这些停止响应的软件,电脑即可恢复正常工作,方法是先按 ...…

查看全部问答>

求助,在5502中SDRAM的写入过程要用210ns,如何提升速度

在TMS320VC5502中,对SDRAM写操作,居然要210ns,简直无法干活,请教前辈,怎样解决这个问题?我对EMIF的相关寄存器进行设置,如WRITE SETUP 、WRITE STROBE 、WRITE HOLD ,对写操作消耗时间一点都没变化,很郁闷呀,在论坛上有说这是5502本身问题 ...…

查看全部问答>

关于磁珠、磁环的选用

磁珠  磁珠专用于抑制信号线、电源线上的高频噪声和尖峰干扰,还具有吸收静电脉冲的能力。磁珠是用来吸 收超高频信号,像一些RF电路,PLL,振荡电路,含超高频存储器电路(DDR SDRAM,RAMBUS等)都需要在电源输入部分加磁珠,而电感是一种蓄能元 ...…

查看全部问答>

指尖“控制”生活的数字家居

几年前,智能化的生活在大多数人看来是一种遥不可及的梦幻,近年来随着相关产业和技术的成熟,经过大量厂家和房地产开发商的宣传推广,越来越多的住宅小区开始配套相对完善的智能家居系统,人们智能化生活的梦想慢慢变成了现实。在南京,已经有数十 ...…

查看全部问答>

WinCE6.0 系统定制及应用开发 问题

在定制WinCE操作系统的时候,我想添加对C#的支持。可是选项中有 .NET Compact Framework 2.0  跟  .NET Compact Framework 2.0-headless两个选择项目。 请问各位大侠,两个有什么不同呢? 还有就是我刚开始添加的是前者,编 ...…

查看全部问答>

射极跟随器问题

本帖最后由 paulhyde 于 2014-9-15 09:04 编辑 我想用三极管打一个射极跟随器  应该选取什么型号三极管 …

查看全部问答>

关于port1 中断

对于不同的pin中断该如何区分呢?有没有类似P1IV这样的register ?谢谢…

查看全部问答>

看门狗定时时间到,怎么跳不出循环

#include void main(void) { WDTCTL=WDT_ADLY_1000;//设置看门狗定时时间1000ms IE1|=WDTIE;         //WDT使能 P5DIR|=0x02;        //P5.1输出 P5OUT=0X02; _EINT();//中断 ...…

查看全部问答>