基于单片机淬火炉温温度控制课程设计

更新时间:2024-05-27 08:46:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

基于PID控制的淬火炉炉温控制系统设计

1总体方案设计

这次课程设计针对PID控制的淬火炉进行温度控制,设计步骤分为以下几步。 首先进行控制系统的建模和数字控制器设计,设计方案为:选用Ziegler-Nichols方法进行PID参数整定,建立闭环控制系统,用MATLAB仿真,得到达到要求的PID参数。

硬件的设计与实现,单片机选用AT89C52,温度采集用热电偶,配合MAX6675使用,DA转换用DAC0802实现,LCD用来显示温度。系统框图如图1-1。

显示温度 温度采集

图1-1 系统框图

AT89C52单片机 D/A转换 加热电路 A/D转换 软件设计,先编写子程序,包括A/D转换和温度检测子程序,延迟子程序,D/A转换子程序,PID控制程序,最后系统初始化并编写主程序。

最后用protues进行硬件连线和仿真,看能否达到系统要求,对温度进行控制。

1

2控制系统建模和数字控制器设计

2.1设计内容

淬火是生产过程中的一道关键工序,其温度控制的精度直接影响到产品的质量。淬火炉温度控制通常由多个温区。本设计针对一个温区进行温度控制,要求控制温度范围600-800℃,控制精度在±1℃。温度探头选用热电偶。输出0-10mA电流信号通过双向可控硅控制器控制加热电阻两端的电压,输入电流输出电压线性关系。其对象温控数学模型为:

Ke-?s? (2-1) G ( s )

Ts?1其中:时间常数 T=400秒,放大系数 K=100℃/mA,滞后时间 τ=10秒,控制算法选用PID控制。

2.2PID控制器的原理

PID控制器是按照偏差的比例、积分、微分进行控制的调节器的简称,主要针对控制对象进行参数调节。当被控对象的结构和参数不能被完全掌握,或得不到精确的数学模型时,应用PID控制技术最为方便。PID控制器就是根据设定值与实际值的误差,利用比例、积分、微分等基本控制规律,或者把它们适当配合形成有PI,PD和PID等的复合控制规律,使控制系统满足性能指标要求。

典型PID控制系统结构图如图2-1,对误差信号分别进行比例、积分、微分、组合控制。 + E(sKP + UR(s) KP TIs- + 被控对象 C(s)

+ KPTD 图2-1 PID控制系统结构图

PID控制算法模拟表达式为:

2

1tde(t)u(t)?K[e(t)?e(t)dt?T P ?0 (2-2) D ]TIdt对应的模拟PID调节器的传递函数为:

D(s)?U(s)1?KP(1??TD)E(s)TIs (2-3)

在计算机控制系统中,PID控制规律的实现必须用数值逼近的方法。当采样周期相当短时,用求和代替积分,用后向差分代替微分,是模拟PID离散化变为差分方程。 数字PID位置型控制算式为:

T k e ( k ) ? e ( k ? 1 ) ] (2-4) u(k)?KP[e(k)??e(i)?TDTIi?0T数字PID增量型控制算式为:

(2-5) ?u(k)?KP[e(k)?e(k?1)]?TIe(k)?KD[e(k)?2e(k?1)?e(k?2)]1K?其中 P 称为比例增益;

?T K I ? K P T 称为积分系数;

ITD K D ? K P 称为微分系数。

T如果单纯的用数字PID控制器去模仿模拟调节器,不会获得更好的效果。因此必须发挥计算机运算速度快、逻辑判断功能强、编程灵活等优势、才能在控制性能上超过模拟调节器。

在单回路控制系统中,由于扰动作用使被控参数偏离给定值,从而产生偏差。自动控

制系统的调节单元将来自变送器的测量值与给定值相比较后产生的偏差进行比例、积分、微分(PID)运算,并输出统一标准信号,去控制执行机构的动作,以实现对温度、压力、流量、也为及其他工艺参数的自动控制。比例作用P只与偏差成正比;积分作用I是偏差对时间的积累;微分作用D是偏差的变化率。

比例控制能迅速反应误差,从而减少稳态误差。除了系统控制输入为0和系统过程值等于期望值这两种情况,比例控制都能给出稳态误差。当期望值有一个变化时,系统过程值将产生一个稳态误差。但是,比例控制不能消除稳态误差。比例放大系数的加大,会引起系统的不稳定。

为了减小稳态误差,在控制器中加入积分项,积分项对误差取决于时间的积分,随着时间的增加,积分项会增大。这样,即使误差很小,积分项也会随着时间的增加而加大,它推动控制器的输出增大使稳态误差进一步减少,直到等于零。

积分(I)和比例(P)通常一起使用,称为比例+积分(PI)控制器,可以使系统在进入稳态后

3

无稳态误差。如果单独用积分(I)的话,由于积分输出随时间积累而逐渐增大,故调节动作缓慢,这样会造成调节不及时,使系统稳定裕度下降。

由于自动控制系统有较大的惯性组件(环节)或有滞后(delay)组件,在调节过程中可能出现过冲甚至振荡。解决办法是引入微分(D)控制,即在误差很大的时候,抑制误差的作用也很大;在误差接近零时,抑制误差的作用也应该是零。

应用PID控制,必须适当地调整比例放大系数KP,积分时间TI和微分时间TD,使整个控制系统得到良好的性能。本次设计采用Ziegler-Nichols方法来PID参数整定。

2.3Ziegler-Nichols方法

Ziegler-Nichols方法是基于系统稳定性分析的PID整定方法.在设计过程中无需考虑任何特性要求,整定方法非常简单,但控制效果却比较理想。

传统的PID经验调节大体分为以下几步:

1关闭控制器的I和D元件,加大P元件,使产生振荡。 2减小P,使系统找到临界振荡点。 3加大I,使系统达到设定值。

4重新上电,观察超调、振荡和稳定时间是否符合系统要求。 5针对超调和振荡的情况适当增加微分项。

以上5个步骤在调节PID控制器时的普遍步骤,但是在寻找合时的I和D参数时,并非易事。

John Ziegler和Nathaniel Nichols发明了著名的回路整定技术使得PID算法在所有应用在工业领域内的反馈控制策略中是最常用的。Ziegler-Nichols整定技术是1942年第一次发表出来,直到现在还被广泛地应用着。

所谓的对PID回路的“整定”就是指调整控制器对实际值与设定值之间的误差产生的反作用的积极程度。如果正巧控制过程是相对缓慢的话,那么PID算法可以设置成只要有一个随机的干扰改变了过程变量或者一个操作改变了设定值时,就能采取快速和显著的动作。

相反地,如果控制过程对执行器是特别地灵敏而控制器是用来操作过程变量的话,那么PID算法必须在比较长的一段时间内应用更为保守的校正力。回路整定的本质就是确定对控制器作用产生的过程反作用的积极程度和PID算法对消除误差可以提供多大的帮助。

4

经过多年的发展,Ziegler-Nichols方法已经发展成为一种在参数设定中,处于经验和计算法之间的中间方法。这种方法可以为控制器确定非常精确的参数,在此之后也可进行微调。

Ziegler-Nichols方法分为两步: 1构建闭环控制回路,确定稳定极限。 2根据公式计算控制器参数。

稳定极限是由P元件决定的。当出现稳态振荡时就达到了这个极限。产生了临界系数Kpcrit和临界振荡周期Tcrit

确定临界系数Kpcrit和临界振荡周期Tcrit后,根据表2-1的公式,计算其他参数:

表2-1 PID参数的计算

控制器类型 KP TI 计算特征数据 TD KI KD P PD PI PID 0.5KPcrit 0.8KPcrit 0.45KPcrit 0.6KPcrit 0.85Tcrit 0.5Tcrit 0.12Tcrit 0.12Tcrit KP/TI KP/TI KPTD KPTD 2.4PID参数的整定

首先建立闭环系统,采用阶跃输入,不加入PID控制器,如图2-2,用MATLAB仿真,得到输出如图2-3。

图2-2 不加PID控制器结构图

5

图2-3 不加PID控制器的阶跃响应

加入PID控制器的结构图如图2-4

图2-4 加入PID控制器的结构图

6

根据Ziegler-Nichols方法,先使积分和微分系数为0,只用比例控制,比例系数从小到大,使阶跃响应出现稳态振荡,当KP?0.655时,得到图2-5所示曲线。

图2-5 KP?0.655时的曲线

由此可知KPcrit=0.655,Tcrit=37,由表2-1可以计算出PID参数:

KP?0.6KPcrit?0.6*0.655?0.393 K?KP0.393I0.5Tcrit?0.5*37?0.021KD?0.12TcritKP?0.12*37*0.393?1.744

图2-6 用计算参数得到的曲线

7

2-6)

2-7) 2-8)

(((

用计算的参数进行仿真得到图2-6,发现系统超调较大,将积分系数减小,比例和微分系数

KD?1.8时曲线如图2-7所示。 KP?0.36、K进行微调,最后当 I?0.0006、

图2-7 参数调整后得到的曲线

8

3硬件的设计与实现

3.1完整系统电路图

图3-1 完整系统电路图

图3-1为本次设计的完整系统电路图。

9

3.2温度检测

本系统采用热电偶来采集温度,并使用MAX6675作为热电偶放大器和A/D转换。

热电偶是一种感温元件,它把温度信号转换成热电动势信号,通过电气仪表转换成被测介质的温度。热电偶测温的基本原理是两种不同成份的均质导体组成闭合回路,当两端存在温度梯度时,回路中就会有电流通过,此时两端之间就存在Seebeck电动势:热电动势,这就是所谓的塞贝克效应。两种不同成份的均质导体为热电极,温度较高的一端为工作端,温度较低的一端为自由端,自由端通常处于某个恒定的温度下。根据热电动势与温度的函数关系,制成热电偶分度表,分度表是自由端温度在0 ℃时的条件下得到的,不同的热电偶具有不同的分度表。在热电偶回路中接入第三种金属材料时,只要该材料两个接点的温度相同,热电偶所产生的热电势将保持不变,即不受第三种金属接入回路中的影响。因此,在热电偶测温时,可接入测量仪表,测得热电动势后,即可知道被测介质的温度。

Maxim公司新近推出的MAX6675即是一个集成了热电偶放大器、冷端补偿、A/D转换器及SPI串口的热电偶放大器与数字转换器。MAX6675的主要特性如下:简单的SPI串行口温度值输出;0℃~+1024℃的测温范围;12位0.25℃的分辨率;片内冷端补偿;高阻抗差动输入;热电偶断线检测;单一+5V的电源电压;低功耗特性;工作温度范围-20℃~+85℃;2000V的ESD信号。MAX6675是一复杂的单片热电偶数字转换器,内部具有信号调节放大器、12位的模拟/数字化热电偶转换器、冷端补偿传感和校正、数字控制器、1个SPI兼容接口和1个相关的逻辑控制。

3.3温度显示

本次设计的显示部分采用LM016L,可显示2行16列英文字符,有8位数据总线D0-D7,RS,R/W,EN三个控制端口(共14 线),工作电压为 5V。没背光,和常用的1602B功能和引脚一样(除了调背光的二个线脚)。本次设计用LM016L显示炉温温度和用户设定的温度。

3.4D/A转换电路

D/A转换采用DAC0832来实现,DAC0832是双列直插式8位D/A转换器。能完成数

10

字量输入到模拟量(电流)输出的转换。分辨率为8位,转换时间为1μs,满量程误差为±1LSB, 当ILE为高电平,片选信号/CS和写信号/WR1为低电平时,输入寄存器控制信号为1,这种情况下,输入寄存器的输出随输入而变化。此后,当/WR1由低电平变高时,控制信号成为低电平,此时,数据被锁存到输入寄存器中,这样输入寄存器的输出端不再随外部数据DB的变化而变化。

对第二级锁存来说,传送控制信号 /XFER和写信号 /WR2同时为低电平时,二级锁存控制信号为高电平,8位的DAC寄存器的输出随输入而变化,此后,当/WR2由低电平变高时,控制信号变为低电,于是将输入寄存器的信息锁存到DAC寄存器中。

3.5加热电路

加热电路如图3-2。

图3-2 加热电路

当炉温温度低于设定的温度时,L1进行加热,而由于电容,加热的快慢取决于两个温度值的差值。

11

4软件设计

图4-1 主程序流程图

12

开始初始化显示设定温度和实际温度是键盘扫描,是否有键按下改变设定温度并显示出来,将温度转换为电压值否是设定温度是否大于实际温度计算差值PID控制输出否不加热D/A转换加热,速度由差值决定

主程序流程图如图4-1所示。

热电偶检测到的温度经MAX6675放大和A/D转换送入单片机,程序首先在液晶显示器上显示开始设定的温度和实际温度,接着一直扫描键盘,如果KS0按下一次,则设定温度加1,并在液晶显示器上显示出来;如果KS1按下一次,则设定温度减1,在液晶显示器上显示出来。将设定值温度与实际值比较,计算差值,如果实际温度小于设定温度,将差值送入DAC转换器,是加热电路进行加热,如果实际温度大于设定温度,因为没有冷却装置,只能不进行加热,是温度自然将下来。运行过程对键盘扫描重复上述过程。

13

参考文献

[1]潘新民.单片微型计算机实用系统设计.人民邮电出版社, 1992.07 [2]沙占友.单片机外围电路设计[M].北京:电子工业出版社, 2003.01 [3]于海生.微型计算机控制技术.清华大学出版社,2007

[4]孙育才. ATMEL新型AT89S51系列单片机及其应用.清华大学出版社,2005.01 [5]贾金玲.单片机原理及应用.电子科技大学出版社,2004.08

14

附录1 主程序

#include #include #include #include #include #include

#include #define uchar unsigned char #define uint unsigned int uchar m; sbit lcd=P2^0;

15

sbit DOUT=P2^3; sbit SCLK=P2^4; sbit CS=P2^5; sbit le=P2 ^ 1; sbit oe=P2 ^ 2; sbit RELAY=P2^6; sbit KS0=P1^0; sbit KS1=P1^1; sbit KS2=P1^2;

uchar code LcdBuf1[]= {%uchar code LcdBuf2[]= {%uchar Vref=5; uchar a[6]; uchar g[6];

unsigned char sumout; uint SET_TEMP=650;

unsigned int read_max6675(void) { unsigned char i; unsigned int AD=0;

CS=0;

SCLK=0; /*输出数据D15*/

SCLK=1;

for(i=12;i>0;i--) /*读取转换结果*/ { SCLK=0;

if(DOUT==1)

AD++;

AD=AD<<1; /*数据左移*/

SCLK=1;

} SCLK=0;

16

//flag=SO;/*读取D2断偶标志*/ SCLK=1;

SCLK=0;

/*输出数据D1*/

SCLK=1;

SCLK=0;

/*输出数据D0*/

SCLK=1;

CS=1; }

unsigned ADC1() {

long l; uint q=0; return AD;

l=read_max6675();

l=(24489/4100)*l*Vref+1; //转换为电压值

l=l+7500;

g[0]=(l/10000)+'0'; //取得整数值到数组 g[1]=(l/1000)+'0'; g[2]=(l/100)+'0'; //a[3]='.';

//忽略小数

//a[4]=t+'0';

q=(g[0]-'0')*100+(g[1]-'0')*10+(g[2]-'0'); return q ; }

void ADC() {

long t;

17

t=read_max6675();

t=(24489/4100)*t*Vref+1;

//转换为电压值

t=t+7500; a[0]=(t/10000)+'0'; //取得整数值到数组 a[1]=(t/1000)+'0';

a[2]=(t/100)+'0';

}

void constant_temperature()

//恒温{

uint b; b=(a[0]-'0')*100+(a[1]-'0')*10+(a[2]-'0'); if(b<=SET_TEMP) {

RELAY=0; m=SET_TEMP-b; m=(unsigned char)(m/256);

}

else

{

RELAY=1; m=SET_TEMP-b; m=(unsigned char)(m/256); }

}

void delay_ms(uchar ms) {

uint i,j;

for(i=0;i

18

}

for(j=0;j<120;j++);

typedef struct {

double SetPoint; /* 设定目标 Desired Value */

double Proportion; /* 比例常数 Proportional Const */

double Integral; /* 积分常数 Integral Const */ double Derivative; /* 微分常数 Derivative Const */

double LastError; /* 前一项误差 */ double PrevError; /* 前第二项误差 */ double SumError; /* 总误差 */ } PID;

/**************************************************************************** PID计算部分

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

double PIDCalc( PID *pp, double NextPoint ) {

double dError,Error;

double SetPoint;

SetPoint=SET_TEMP;

Error = pp->SetPoint - NextPoint; /* 计算当前偏差 */ pp->SumError += Error; /* 积分《总偏差》*/ dError = pp->LastError - pp->PrevError; /* 当前微分 */ pp->PrevError = pp->LastError;

19

pp->LastError = Error; /* 三个误差值移位 */ return(NextPoint+pp->Proportion * Error + pp->Integral * pp->SumError + pp->Derivative * dError ); /*《返回总的误差值》*/ }

void pid(void) {

PID sPID; double rOut; unsigned char rIn; double x;

sPID.Proportion = 0.36; sPID.Integral = 0.0006; sPID.Derivative = 1.8; sPID.SetPoint = 2.0; {

unsigned char sumout; 进入循环检测状态中 */ unsigned char i;

rIn = ADC1(); for(i=0;i<50;i++)

x = 5.0 * (double)rIn / 256.0; rOut = PIDCalc ( &sPID,x ); sumout=rOut*256/5; } }

void dac0832(out) {

/* 定义PID结构体变量 */ /* PID 响应输出 */ /* PID 反馈 (Input) */ /* 设置 PID 比例系数 */ /* 设置PID积分系数 */ /* 设置PID微分系数 */ /* 设置 PID 输出值 */ /* PID /* 读传感器输出 */ /* 计算PID 输出 */ 20

}

RELAY=0; P3=out; delay(100); RELAY=1;

void key(void ) {

if(KS0==0) delay_ms(1); if(KS0==0) SET_TEMP++; while(!KS0); if(KS1==0) delay_ms(1); if(KS1==0) SET_TEMP--; while(!KS1);

display_onechar(0,9,SET_TEMP/100+'0'); display_onechar(0,10,(SET_TEMP0)/10+'0'); display_onechar(0,11,SET_TEMP+'0'); } main() {

lcd_init();

display_string(0,0,LcdBuf1); display_string(1,0,LcdBuf2); Write_CGRAM(LcdBuf);

//向CGRAM写入自定义的摄氏度符号

display_onechar(0,12,0); //显示自定义的摄氏度符号

21

display_onechar(0,13,1); //显示自定义的摄氏度符号 display_onechar(1,12,0); display_onechar(1,13,1); while(1) {

key(); ADC();

constant_temperature(); display_string(1,9,a); pid();

dac0832(sumout); delay_ms(100);

}

}

附录2 LCD程序

#ifndef LCD_1602_ #define LCD_1602_ #include #include sbit LCD_RS = P2 ^ 0; sbit LCD_RW = P2 ^ 1; sbit LCD_E = P2 ^ 2; #define LCD_DATA P0

unsigned char code LcdBuf[]= {

//自定义汉字 22

5X7;最大能存储64个字节

0x0c,0x12,0x12,0x0c,0x00,0x00,0x00,0x00, 0x0f,0x10,0x10,0x10,0x10,0x10,0x0f,0x00, };

void delay(unsigned int ms) { }

bit lcd_busy()

{ // 测试LCD忙碌状态 bit result; LCD_RS = 0; LCD_RW = 1; LCD_E = 1; _nop_(); _nop_(); _nop_(); _nop_();

result =(LCD_DATA & 0x80); LCD_E = 0; return result; }

unsigned char y; for(;ms>0;ms--)

for(y=120;y>0;y--);

void WriteCommand(unsigned char wdata) {

while(lcd_busy()); LCD_DATA=wdata; LCD_RS=0;

23

LCD_RW=0; LCD_E=1; LCD_E=0; delay(5); LCD_E=1; }

void WriteData(unsigned char wdata) {

while(lcd_busy()); LCD_DATA=wdata; LCD_RS=1; LCD_RW=0; LCD_E=1; LCD_E=0; delay(5); LCD_E=1; }

void lcd_init(void) {

WriteCommand(0x38); WriteCommand(0x38);

WriteCommand(0x38);

delay(5);

WriteCommand(0x08); WriteCommand(0x01); WriteCommand(0x06); WriteCommand(0x0c); }

void set_xy(unsigned char x,unsigned

char y)

24

{

switch (x) {

case 0: y+=0x80; break;

case 1: y+=0xc0; break;

}

WriteCommand(y); }

void display_onechar(unsigned char x,unsigned char y,unsigned char wdate) {

set_xy(x,y); WriteData(wdate); }

void display_string(unsigned char x,unsigned char y,unsigned char *s) {

set_xy(x,y); while(*s) {

WriteData(*s); s++; } }

/******************************************************************/ void Write_CGRAM(unsigned char *p) {

unsigned char i,j,kk;

unsigned char tmp=0x40; //操作CGRAM的命令码 kk=0;

for(j=0;j<2;j++) //64 字节存储空间,可以生成 8 个自定义字符点阵 64X8

25

{

for(i=0;i<8;i++) // 8 个字节生成 1 个字符点阵 {

WriteCommand(tmp+i); //操作CGRAM的命令码+写入CGRAM地址. WriteData(p[kk]); //写入数据 kk++; } tmp += 8; } } #endif

26

附录3 完整硬件电路图

27

本文来源:https://www.bwwdw.com/article/ejg7.html

Top