视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
PID温度控制器
2025-09-22 17:41:41 责编:小OO
文档
一、设计内容

1.1温度控制

本设计以水为测量对象,温度测量电路接收传感器的信号,并将模拟信号通过模/数转换器转换为数字信号,送入单片机系统,与预设的温度对比,通过一定的控制算法,控制继电器的通断,从而控制加热器的工作,使得水温维持在设定的温度。温度控制算法精确控制温度加热,以温度最小为优化目标。

温度是工业控制对象的主要的被控参数之一,如冶金,机械,食品,化工各类工业中广泛使用的各种加热炉,热处理炉,反应炉等。在过去多是采用常规的模拟调节器对温度进行控制,本设计采用了单片微型机对温度实现自动控制。

1.2设计方案

温度控制系统是一种比较常见和典型的过程控制系统。温度是工业生产过程中重要的被控参数之一,当今计算机控制技术在这方面的应用,已使温度控制系统达到自动化、智能化,比过去单纯采用电子线路进行PID调节的控制效果要好得多,可控性方面也有了很大的提高。

温度是一个非线性的对象,具有大惯性的特点,在低温段惯性较大,在高温段惯性较小。对于这种温控对象,一般认为它具有以下的传递函数形式:

这是传统的二位式模拟控制方案,其基本思想与方案一相同,但由于采用上下限比较电路,所以控制精度有所提高。这种方法还是模拟控制方式,因此也不能实现复杂的控制算法使控制精度做得较高,而且不能用数码管显示,对键盘进行设定。

采用C51单片机系统来实现。单片机软件编程灵活、自由度大,可用软件编程来实现各种控制算法和逻辑控制。单片机系统可以使用数码管来显示水温的实际值,能用键盘输入设定值。选用了ATC51芯片,不需要外扩展存储器,可使系统整体结构更为简单。

采用以单片机为控制核心的控制系统,尤其对温度控制,可达到模拟控制所达不到的效果,并且实现显示和键盘设定功能,大大提高了系统的智能化。这也使得系统所测得结果的精度大大提高。

ATC51是一种带4k字节闪烁可编程可擦除只读存储器的低电压,高性能CMOS8位微处理器,俗称单片机。而在众多的51系列单片机中,要算 ATMEL 公司的ATC51更实用,也是一种高效微控制器,因为它不但和8051指令、管脚完全兼容,而且其片内的4K程序存储器是FLASH工艺的,这种工艺的存储器,用户可以用电的方式达到瞬间擦除、改写。而这种单片机对开发设备的要求非常低,开发时间也能大大缩短。

DS18B20是一线式数字温度传感器,它具有微型化、低功耗、高性能抗干扰能力、强易配处理器等优点,特别适合用于构成多点温度测控系统,可直接将温度转化成串行数字信号(按9位二进制数字)给单片机处理,且在同一总线上可以挂接多个传感器芯片。它具有独特的单总线接口方式,仅需使用1个端口就能实现与单片机的双向通讯。采用数字信号输出提高了信号抗干扰能力和温度测量精度。它的工作电压使用范围宽3.0~5.5 V,可以采用外部供电方式,也可以采用寄生电源方式,即当总线DQ为高电平时,窃取信号能量给DS18B20供电。它还有负压特性,电源极性接反时,DS18B20不会因接错线而烧毁,但不能正常工作。可以通过编程而实现9~12位的温度转换精度设置。设定的分辨率越高,所需要的温度数据转换时间就越长,在实际应用中要将分辨率和转换时间权衡考虑。

RS-232接口是个人计算机上的通讯接口之一,是1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。它的全名是“数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准”。该标准规定采用一个25个脚的DB25连接器,对连接器的每个引脚的信号内容加以规定,还对各种信号的电平加以规定。随着设备的不断改进,出现了代替DB25的DB9接口。

二、软件设计

2.1主程序流程图

系统的主程序流程图如图 2-1 所示,当有信号输入时,主程序启动,根据内部设定的条件逐步运行,达到设计目的。

2.2 DS18B20实现温度转换和温度数值读取流程图

图2-2为DS18B20实现温度转换和温度数值读取流程图,用于系统的温度转换和温度数值的读取。

2.3显示流程图

图2-3为系统的显示流程图。主要是通过对传输信号进行显示后,给操作者提供提示。以到达为本系统提供对温度的显示和监控的目的。

三、PID控制

3.1PID简介

PID控制器是一种线性控制器,它根据给定值厂r(t)与实际输出值y(t)构成控制偏差e(t):

                                           (3.1)

将偏差的比例(Proportional)、积分(Integral)和微分(Derivative)通过线性组合构成控制量,对被控对象进行控制,因此称为PID控制。PID控制系统原理如图 3-1 所示。

图 3-1 PID 控制系统原理图

其控制规律为:

               (3.2)

或者写成传递函数的形式为:

                          (3.3)

式中  :比例系数

:积分时间常数

:微分时间常数

PID控制器各校正环节的作用如下:

(1) 比例环节即时成比例地反映控制系统的偏差信号,偏差一旦产生,控制器立即产生控制作用,以减少偏差;

(2) 积分环节主要用于消除静差,提高系统的无差度。积分作用的强弱取决于积分时间常数,越大,积分作用越弱,反之则越强;

(3) 微分环节能够反映偏差信号的变化趋势(变化速率),并且能在偏差信号值变得太大之前,在系统中引入一个有效的早期修正信号,从而加快系统的动作速度,减少调节时间。

3.2PID控制算法

由于计算机控制是一种采样控制系统,它只能根据采样时刻的偏差值计算控制量。因此,(3.2)式中的积分和微分项不能直接使用,需要进行离散化处理。现令为采样周期,以一系列的采样时刻点代表连续时间,以累加求和近似代替积分,以一阶后向差分近似代替微分,做如下的近似变换:

                                            (3.4)

                                     (3.5)

                          (3.6)

其中,为采样周期,为系统第次采样时刻的偏差值,e()为系统第()次采样时刻的偏差值,为采样序号,=0,1,2,…。

将上面的(3.5)式和(3.6)式代入(3.2)式,则可以得到离散的PID表达式:

                      (3.7)

如果采样周期足够小,该算式可以很好的逼近模拟PID算式,因而使被控过程与连续控制过程十分接近。通常把(3.7)式称为PID的位置式控制算法。

若在(3.7)式中,令:

  (称为积分系数)

 (称为微分系数)

则                      (3.8)

(3.8)式即为离散化的位置式PID控制算法的编程表达式。可以看出,每次输出与过去的所有状态都有关,要想计算,不仅涉及和,且须将历次相加,计算复杂,浪费内存。下面,推导计算较为简单的递推算式。为此,对(3.8)式作如下的变动:

考虑到第次采样时有

                 (3.9)

使(3.8)式两边对应减去(3.9)式,得

   

整理后得

  (3.10)

其中,,,,(3.10)式就是PID位置式得递推形式。

如果令  则 

式中的、、同(3.10)式中的一样。

因为在计算机控制中,、、都可以事先求出,所以,实际控制时只须获得、、三个有限的偏差值就可以求出控制增量。由于其控制输出对应执行机构的位置的增量,故(3.11)式通常被称为PID控制的增量式算式。

增量式PID控制算法与位置式控制算法比较,有如下的一些优点: 

(1)位置式算法每次输出与整个过去状态有关,算式中要用到过去偏差的累加值,容易产生较大的累计误差。而增量式中只须计算增量,算式中不需 要累加,控制增量的确定仅与最近几次偏差采样值有关,当存在计算误差或者精度不足时,对控制量的影响较小,且较容易通过加权处理获得比较好的控制效果;

(2)由于计算机只输出控制增量,所以误动作影响小,而且必要时可以用逻辑判断的方法去掉,对系统安全运行有利;

(3)手动一自动切换时冲击比较小。

鉴于以上优点,本系统的控制算法即采用增量式的PID控制算法。

四、电路设计

4.1功能模块设计

数字温度传感器DS18B20从设备不同的位置采集温度,并将数字信号送入ATC51单片机系统,单片机获取采集的温度值,经过处理后得到当前环境中一个比较稳定的温度值,根据当前设定的温度上下限值,再通过PID控制算法控制继电器的通断,从而控制加热器的工作,使得水温维持在设定的温度。当采集的温度经处理后没有达到设定的温度值时,单片机控制继电器开启升温设备(加热器)。

图4-1 单片机电路图

4.2电路连接设计

4.2.1温度检测电路

温度检测用DS18B20温度传感器,DS18B20是单线数字式测温芯片,它能在现场采集温度数据,并将温度数据直接转换成数字量,并将数字信号送入ATC51单片机系统。图4-2为温度检测电路图。

图4-2温度检测电路图

4.2.2继电器控温电路

当DS18B20采集到温度后,会将温度值传送到单片机。单片机获取采集的温度值,经过处理后得到当前环境中一个比较稳定的温度值,根据当前设定的温度上下限值,再通过PID控制算法控制继电器的通断,从而控制加热器的工作,使得水温维持在设定的温度。

图4-3继电器控温电路图

4.2.3外部电路

启动、复位电路用于系统的开始和重置。

图4-4外部电路图

参考文献

[1] 余锡存主编.单片机原理与接口技术.西安电子科技大学出版社,2001,7.

[2] 刘金琨.先进PID控制及其MATLAB仿真[M].北京:电子工业出版社,2003.

[3] 曹巧媛主编.单片机原理及应用(第二版)[M].北京:电子工业出版社,2002.

[4] 康华光主编.电子技术基础[M].北京:高等教育出版社,1998,121-142.

[5] 何立民.单片机高级教程应用[M].北京:北京航空航天大学出版社,2000,3-14.

[6] 金发庆等编.传感器技术与应用[M].北京机械工业出版社,2002.

[7] 秦实宏等.单片机原理与应用技术[M].北京:中国水利水电出版社,2005,27-48.

[8] 陈忠华.基于单片机的温度智能控制系统的设计与实现[D].大连理工大学硕士学位论文,2006.

附录 PID温度控制器程序

#pragma db code

#include

#include "INTRINS.H"

#define   BUSY1    (DQ1==0)               //定义busy信号

sbit DQ1=P3^5;                          //定义18B20单总线引脚

void ds_reset_1(void);                     //声明18B20复位函数

void wr_ds18_1(char dat);                 //声明18B20写入函数

void time_delay(unsigned char time);           //声明延时函数

int get_temp_1(void);                             //声明18B20读入温度函数

void delay(unsigned int x);                 //声明延时函数

void read_ROM(void);                     //声明18B20读ROM函数

int get_temp_d(void);                             //声明获取温度函数

void ds_init(void);                         //声明18B20初始化函数

void ds_getT(void);                         //声明18B20获得温度显示值函数

void hot();

/****************以下定义各种变量********************/

unsigned char ResultSignal;

int ResultTemperatureLH,ResultTemperatureLL,ResultTemperatureH;

unsigned char ROM[8];

unsigned char idata TMP; 

unsigned char idata TMP_d; 

unsigned char f; 

unsigned char rd_ds18_1();

unsigned int TemH,TemL;                    //温度的整数部分和小数部分

unsigned int count;

unsigned int tt1,tt2;                     //定义小数计算部分

void main()

{

        ds_init();                         //18B20初始化

       while(1)

      {

ds_getT();               //使用该函数获得温度,整数部分存储到TemH,小数部分存储到count的低8位

     if(TMP_d          {

           hot();

          }

    }

/***************18B20初始化函数***********************/

void ds_init(void)

{

    unsigned int k=0;

    ds_reset_1();

    ds_reset_1();                                //reset

    wr_ds18_1(0xcc);                        //skip rom

    _nop_();

    wr_ds18_1(0x7f);

    ds_reset_1();

    wr_ds18_1(0xcc);

    _nop_();  

    wr_ds18_1(0x44);

for(k=0;k<11000;k++)

        time_delay(255);       

    ds_reset_1();

}

void ds_getT(void)

{

    wr_ds18_1(0xcc);

    wr_ds18_1(0xbe);

    TemH=get_temp_1();

    TemL=get_temp_d();

    TemH&=0x00ff;

    TemL&=0x00ff;

    count=(TemH*256+TemL)*6.25;

}

/***************延时程序,单位us,大于10us*************/

void time_delay(unsigned char time)

{

      time=time-10;

     time=time/6;

     while(time!=0)time--;

}

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

/*                reset ds18b20                      */

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

void ds_reset_1(void)

{

     unsigned char idata count=0;  

     DQ1=0;

      time_delay(240);

    time_delay(240);

DQ1=1;

     return;

}

void check_pre_1(void)

{

        while(DQ1);

        while(~DQ1);

   

         time_delay(30);

}

void read_ROM(void)

{

    int n;

    ds_reset_1();

     check_pre_1();

     wr_ds18_1(0x33);

  for(n=0;n<8;n++){ROM[n]=rd_ds18_1();}

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

/*      Read a bit from 1820位读取             */

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

bit tmrbit_1(void)

{

        idata char i=0;

        bit dat;

        

        DQ1=0;_nop_();

      

        DQ1=1;        

      _nop_();

      _nop_();

      _nop_();

    _nop_();

     _nop_();

      _nop_();

      _nop_();

      _nop_();

    _nop_();

     _nop_();

      _nop_();

      _nop_();

      _nop_();

      _nop_();      

        dat = DQ1;

        

        time_delay(50);

      

        return dat;

}

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

/*           read a bety from ds18b20 字节读取  */

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

unsigned char rd_ds18_1()

{

     unsigned char idata i,j,dat=0;

     for(i=1;i<=8;i++)

        {

            j=tmrbit_1();

         dat=(j<<(i-1))|dat;

        }

        return dat;

}

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

/*         write a bety from ds18b20   写字节        */

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

void wr_ds18_1(char dat)

{

        signed char  idata i=0;

        unsigned char idata j;

        bit testb;

     for(j=1;j<=8;j++)

        {

            testb=dat & 0x01;

         dat = dat>>1;

            if(testb)

            {

                    DQ1=0;

                     _nop_();

                _nop_();

                    DQ1=1;

                  time_delay(60);   

               }

            

            else

            {

                    DQ1=0;

                    time_delay(50);

                   

                    DQ1=1;

                     _nop_();

                _nop_();

            }

        }

}

int get_temp_1(void)

{

     unsigned char idata a=0,b=0; 

     unsigned char idata i;

     EA=0;

     

     ds_reset_1();

     check_pre_1();

     

     wr_ds18_1(0xcc); 

     wr_ds18_1(0x44);

     while(BUSY1);

     

     ds_reset_1();

     check_pre_1();

     wr_ds18_1(0xcc);

     wr_ds18_1(0xbe);

     

     a=rd_ds18_1();

     b=rd_ds18_1();

     

     i=b;                                   /*若b为1则为负温   */

  i=(i>>4);

     if(i==0)

     {

         f=0;

      TMP=((a>>4)|(b<<4));

        a=(a&0x0f);

     if (a>8)

        {

            TMP=(TMP+1);

        }

     }

     else 

     {

         f=1;

     a=a>>4;

      b=b<<4;

                  

         TMP=(a|b);

          

         TMP=~TMP;

         TMP=(TMP+1);

     }

     EA=1;

     return(TMP);

}

int get_temp_d(void)

{

     unsigned char idata a=0,b=0; 

     unsigned char idata i,m;

     EA=0; 

     

     ds_reset_1();                               //复位

     check_pre_1();

     

     wr_ds18_1(0xcc);        

     wr_ds18_1(0x44);          

     while(BUSY1);

     

     ds_reset_1();

     check_pre_1();

     wr_ds18_1(0xcc);        

     wr_ds18_1(0xbe);        

     

     a=rd_ds18_1();

     b=rd_ds18_1();

     

         i=b;                                  /*若b为1则为负温   */

  i=(i>>4);

      

     if(i==0)

     {

         f=0;

      TMP=((a>>4)|(b<<4));

        a=(a&0x0f);

        TMP_d=a;

     }

     else 

     {

         f=1;

         a=~a;

         a=(a+1);

         b=~b;

         b=(b+1);

         

         m=a;

      a=a>>4;

      b=b<<4;

                  

         TMP=(a|b);          

         m=(m&0x0f);

         TMP_d=m;

     }

     

     EA=1;

     return(TMP_d);

}void delay(unsigned int x)

{

      unsigned int i;

   for(i=0;i}

void hot()

{}

2.PID控制

#define FiltA  0.1;             //PID输出的滤波系数(0.0-1.0)

#define FiltB  0.9               // PID输出的滤波系数(1-FilterA)

#define Kp    1.75             //PID控制器的比例系数

#define Ki    0.00125           //PID控制器的积分系数

#define Kd    3.0              //PID控制器的微分系数

#define Emax  0.1              //误差积分上限

float Err[4] [2];

float InteR[4] [2];

float OnMs[4] [2];

/*

function:      unsigned char pid(unsigned char i,unsigned char j,unsigned char k,unsigned char l)

description:    this function for pid control

parameter: i:-->channel

j:-->time

                   k:-->set temprature

                      l:-->actual temprature

return: adjust_time-->adjust time

*/

void pid (unsigned char ch,float refval)

{

   Float DiscE,Tmpr;

   Err[ch][1]=refval-GetTmp(GetData7705(ch+l));                       //e(k)

   

   If(Err[ch] [1]>=Emax) InteE[ch] [1]=InteE[ch] [1]=InteE[ch] [0]+Err[ch] [1];

    else                  InteE[ch] [l]= InteE[ch] [0];

   DiscE=Err [ch] [1]-Err[ch] [0];

   Tmpr=Kp*Err[ch] [1]+Ki*InteE[ch] [1]+Kd*DiscE;

   OnMs[ch] [1]=GetOnMs(FiltA*OnMs[ch] [0]+FiltB*Tmpr);

   Err[ch] [0]=Err [ch] [1];

   InteE[ch] [0]=InteE[ch] [1];

   OnMs[ch] [0]= OnMs[ch] [1];

}

/*

function:       float GetOnMs(float OnTime)

description:     output control time

parameter:      none

return:         ftmp

*/

float GetOnMs(float OnTime)

{

   float ftmp;

if(OnTime<=0) ftmp=0;

else if(OnTime>=100) ftmp=100;

   else             ftmp=OnTime;

   return(ftmp);下载本文

显示全文
专题