测控综合设计 PID温控器设计.docx
- 文档编号:3814571
- 上传时间:2022-11-25
- 格式:DOCX
- 页数:30
- 大小:330.79KB
测控综合设计 PID温控器设计.docx
《测控综合设计 PID温控器设计.docx》由会员分享,可在线阅读,更多相关《测控综合设计 PID温控器设计.docx(30页珍藏版)》请在冰豆网上搜索。
测控综合设计PID温控器设计
测控综合设计
P
I
D温控器设计
姓名:
学号:
班级:
组员:
——基于Keil与Proteus
PID温控器设计报告
一、设计准备
本次设计的PID温控器是基于51单片机的应用设计与仿真,是结合Proteus仿真工具和KeilC。
固在实验前应把实验中要用到的软件安装到自己的电脑中,并按照自己的喜好与方便设置软件的参数(比如快捷键、背景颜色、文字字体颜色大小等等的设置)。
PID温控器工作原理简单介绍:
电炉内的热电阻温度传感器测出的温度信号经运算放大器放大和模/数转换后,由8051读出电阻炉炉温,控制程序根据当前炉温和目标温度的偏差,按照一的的控制方法控制开关K的开与断,提供适当的热功率,以使炉温尽快趋近目标温度。
PID温控器还通过串口与PC通信,以实现远程监控。
LED和键盘用于人机接口,交流电过零检测部分可使8051只在正弦交流电零点附近控制开关K的通与断,以避免对交流电斩波而造成干扰。
如下的设计原理图:
二、设计过程
1.LED显示器的显示方式
静态显示:
静态显示方式中各LED的断引脚和com端都是独立接线,这种方式的好处是程序相对简单,显示无闪烁;缺点是功耗大。
在三个LED上分别显示数字1,2,3:
编写程序:
#include"absacc.h"
unsignedcharcodeLED_CODES[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
0x82,0xf8,0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e,0xff,0x0c,
0x89,0x7f,0xbf
};
voidmain()
{
XBYTE[0x0000]=LED_CODES[1];
XBYTE[0x0200]=LED_CODES[2];
XBYTE[0x0400]=LED_CODES[3];
while
(1);
}
程序流程图:
仿真运行效果图:
2.PID温控器LED显示(动态显示)
PID温控器LED显示部分的Proteus仿真原理图右上角插入了8255A的方式控制字。
8255A是较复杂的并行接口芯片,在PID温控器主要用作I/O口扩展,用于LED的显示。
在编程时应注意,由于8255A的复位时间较长,在应用程序访问8255A之前,应有足够的延时保证8255A已正确复位,仿真时可不延时,但实际电路中必须加足够的延时。
图中有6位动态扫描共阴级LED,它们的段引脚A~G、DP是并在一起的;引脚1~6是各位LED的com端,相互独立。
8255A端口C经74LS244的同相输出S0~S7作为LED的端驱动信号,当某位LED各段全部点亮时,com端电流会达到120~150mA,所以选用驱动能力较强的ULN2003A作为位驱动器件,也可用三极管驱动。
8255A端口B的PB0~PB5经ULN2003A反相后的输出B0~B5,作为LED的位选信号,排阻R10~R15作为ULN2003A的下拉电阻,由于ULN2003A是反相驱动器,要点亮某位LED,8255A端口B发出的位选信号应为高电平。
编写程序:
/*display.h*/
/*8255A端口地址*/
#defineBASE0x0000
#definePORT_A(BASE)
#definePORT_B(BASE+1)
#definePORT_C(BASE+2)
#definePORT_CONTROL(BASE+3)
#defineLEDS6
#defineCA0
#defineCC1
/*函数声明*/
voidturn_On(charled,charChNumber,charmode);
voidLedsOff();
voidOneByOne(chardatas[]);
externvoidInit8255();
unsignedcharcodeSelect[];
unsignedcharcodeLED_CODES[];
----------------------------------------------------------------------------------------------------------------------
/*display.c*/
#include"absacc.h"
#include"Reg51.h"
#include"display.h"
unsignedcharcodeSelect[]={0x01,0x02,0x04,0x08,0x10,0x20};
unsignedcharcodeLED_CODES[]={0xc0,0xF9,0xA4,0xB0,0x99,
0x92,0x82,0xF8,0x80,0x90,
0x88,0x83,0xC6,0xA1,0x86,
0x8E,0xFF,0x0C,0x89,0x7F,0xBF};
/*初始化8255A*/
voidInit8255()
{
unsignedchari,j;
for(j=0;j<10;j++)
for(i=0;i<255;i++);
XBYTE[PORT_CONTROL]=0x90;
LedsOff();
}
voidturn_On(charled,charChNumber,charmode)
{
if(mode==CA)
XBYTE[PORT_C]=LED_CODES[ChNumber];
else
XBYTE[PORT_C]=~LED_CODES[ChNumber];
XBYTE[PORT_B]=Select[led];
}
voidLedsOff()
{
XBYTE[PORT_B]=0x00;
}
----------------------------------------------------------------------------------------------------------------------
/*main.c*/
#include"reg51.h"
#include"display.h"
voidmain()
{
unsignedintm;
unsignedchari;
Init8255();
i=LEDS-1;
while
(1)
{
LedsOff();
for(m=50;m!
=0;m--);
turn_On(i,i+1,CC);
for(m=50;m!
=0;m--);
if(i==0)i=LEDS-1;
elsei--;
}
}
----------------------------------------------------------------------------------------------------------------------
程序流程图:
仿真运行效果图:
3.PID温控器的键盘设计及Proteus仿真
在LED设计页中删除ULN2003A的驱动部分,在LED设计页中新建一个子电路LED_DRIVER。
用BUTTON元件绘出PID温控器键盘设计图上角的键盘部分,并为行扫描线和列扫描线上的端子命名为row0~row3和col0~col3.
转到ExternalMemory设计页,为8051的P1.0~P1.3A加上连接端子并命名为row0~row3,为P1.4~P1.7加上连接端子并命名为col0~col3。
将仿真模型另存为KeyBoard.dsn仿真模型文件。
编写程序:
/*keycheck.c按键检测c程序*/
#include"absacc.h"
#include"display.h"
#include"reg51.h"
/*延时函数*/
voiddelay()
{
chari;
for(i=255;i!
=0;i--);
}
charkeyCheck(char*row,char*col)
{unsignedchart1,t2,t3,i;
unsignedcharResult=0;
P1=0xf0;t1=P1;
if(t1==0xf0)gotoexit;
for(i=11;i!
=0;i--)
delay();
t1=P1;
if(t1==0xf0)gotoexit;
Result=1;
/*求列号*/
t2=0x80;t1=~t1;
for(i=4;i!
=0;i--)
{
t3=t2&t1;
if(t3!
=0)
{*col=i-1;break;}
elset2=t2>>1;
}
t1=~t1;
t1=t1|0x0f;
P1=t1;
t1=P1;
/*求行号*/
t2=0x08;t1=~t1;
for(i=4;i!
=0;i--)
{
t3=t2&t1;
if(t3!
=0)
{*row=i-1;break;}
elset2=t2>>1;
}
exit:
returnResult;
}
----------------------------------------------------------------------------------------------------------------------
/*main.c显示所识别键的行列号*/
#include"display.h"
#include"absacc.h"
#include"reg51.h"
externcharkeyCheck(char*row,char*col);
voidmain()
{
charrow,col,r;
charstrIndexs[6]={20,20,20,20,20,20};
unsignedchari,k;
Init8255();
while
(1)
{
r=keyCheck(&row,&col);
if(r==0)
{
strIndexs[5]=20;strIndexs[4]=20;
strIndexs[1]=20;strIndexs[0]=20;
}
else
{
strIndexs[5]=0;strIndexs[1]=0;
strIndexs[4]=row;strIndexs[0]=col;
}
for(k=6;k!
=0;k--)
{
LedsOff();
for(i=50;i!
=0;i--);
turn_On(k-1,strIndexs[k-1],CC);
for(i=50;i!
=0;i--);
}
}
}
---------------------------------------------------------------------------------------------------------------------
程序流程图:
本次仿真程序中还需要使用的display.h与display.c在前面已经给出,所以在此及以后都不再给出。
运行本次仿真及其后续PID温控器实例前,应参照下图在KeilC项目选项中正确设定PID温控器的存储器地址范围,以使KeilC产生正确的代码。
运行程序,当按下图中第2行第0列上的按键时,将在LED上显示键的行列号。
仿真运行效果图:
4.PID温控器A/D转换
PID温控器采用ADC0808作为A/D转换器。
在PID温控器的仿真原理图中,74LS161用于提供ADC0808所需的是在信号,其中Q0、Q1、Q2、Q3输出信号的频率分别是其CLK引脚输入是在信号的频率的1/2、1/4、1/8、1/16,CLK输入信号来自于51单片机的ALE引脚,多路开关SW1为ADC0808选取不同的时钟频率。
打开前面完成的仿真模型文件KeyBoard.dsn,并另存为Ads.dsn。
新建一个名为ADC0808的设计页,将下图的内容画在该页中;再进入ExternalMemory设计页,为其中的AT89C51的P3.5加一个端子并命名为START,然后保存仿真文件。
编写程序:
/*ADC0808.c*/
#include"display.h"
#include"absacc.h"
#include"Reg51.h"
#defineADC_08081
#defineADC0808_DATA_PORT0x2000
#defineADC0808_QUERY_PORT0x4000
#defineADC0808_START_PORT0x2000
/*端口查询方式*/
unsignedchargetData2(unsignedcharADC_Chip,unsignedcharchannel)
{
unsignedcharflag=0;
unsignedcharvalue=-1;
unsignedxdataale;
switch(ADC_Chip)
{
caseADC_0808:
P3=P3|0x08;
XBYTE[ADC0808_START_PORT]=channel;
P3=P3&0xdf;
P3=P3|0x20;
P3=P3&0xdf;
flag=P3;
while
(1)
{
ale=1;
flag=flag&0x08;
if(flag==0)break;
flag=P3;
}
value=XBYTE[ADC0808_DATA_PORT];
returnvalue;
break;
}
}
/*函数dispstr将ad转换值和通道号显示在led上*/
voiddispStr(charstrIndexs[],unsignedcharvalue,unsignedcharchannel)
{
chari,k;
for(i=0;i<3;i++)
{
strIndexs[i]=value%10;
value=value/10;
}
strIndexs[4]=channel;
LedsOff();
for(i=50;i!
=0;i--);
for(k=6;k!
=0;k--)
{
LedsOff();
for(i=50;i!
=0;i--);
turn_On(k-1,strIndexs[k-1],CC);
for(i=50;i!
=0;i--);
}
}
/*端口查询并显示*/
voidmain()
{
unsignedcharvalue;
unsignedintk;
charstrIndexs[6]={20,20,20,20,1,12};
Init8255();
while
(1)
{
value=getData2(ADC_0808,1);
for(k=100;k!
=0;k--)
dispStr(strIndexs,value,1);
LedsOff();
}
}
程序流程图:
运行仿真,则LED上以下图的格式显示从ADC0808的通道1所读入的数据,左边两位表示通道号,右边3位为读入的数据。
5.测温放大电路与ADC0808的接口及仿真
打开前面建立的ADC.dsn仿真图,在其中的LED_Keyboard设计页上建立如下图所示的放大电路,电路的输出Ut0连结至ADC0808的输入通道0.
编写程序:
#include"absacc.h"
#include"display.h"
#include"Reg51.h"
#defineADC_08081
#defineADC0808_DATA_PORT0x2000
#defineADC0808_QUERY_PORT0x4000
#defineADC0808_START_PORT0x2000
/*端口查询方式*/
unsignedchargetData2(unsignedcharADC_Chip,unsignedcharchannel)
{
unsignedcharflag=0;
unsignedcharvalue=-1;
unsignedxdataale;
switch(ADC_Chip)
{
caseADC_0808:
P3=P3|0x08;
XBYTE[ADC0808_START_PORT]=channel;
P3=P3&0xdf;
P3=P3|0x20;
P3=P3&0xdf;
flag=P3;
while
(1)
{
ale=1;
flag=flag&0x08;
if(flag==0)break;
flag=P3;
}
value=XBYTE[ADC0808_DATA_PORT];
returnvalue;
break;
}
}
voidmain()
{
unsignedcharvalue;
unsignedlongt;
unsignedchari,m,n;
Init8255();
while
(1)
{
value=getData2(ADC_0808,0);
t=((200*(unsignedlong)value*100)/255+5)/10;
LedsOff();
for(i=200;i!
=0;i--)
for(m=100;m!
=0;m--);
for(i=0;;i++)
{
m=t%10;
if(i==1)
{
LedsOff();
turn_On_WithDot(i,m,CC);
turn_On(i,m,CC);
}
else
{
LedsOff();
turn_On(i,m,CC);
}
for(n=50;n!
=0;n--);
t=t/10;
if(t==0)break;
}
}
}
----------------------------------------------------------------------------------------------------------------------
按原理图设计,LED从右至左编号为0-5位。
被测温度t放大10倍并取整后,其中最后一位实际上代表的是小数,应显示在LED的第0位上;显示温度个位(LED的第1位)值时,应点亮第1位的小数点,其方法是将LED的第1位所显示数字的字型码和小数点的字型码作按位“或”运算得到显示码,详见函数turn_On_WithDot源程序。
/*display.c*/
#include"absacc.h"
#include"Reg51.h"
#include"display.h"
unsignedcharcodeSelect[]={0x01,0x02,0x04,0x08,0x10,0x20};
unsignedcharcodeLED_CODES[]={0xc0,0xF9,0xA4,0xB0,0x99,
0x92,0x82,0xF8,0x80,0x90,
0x88,0x83,0xC6,0xA1,0x86,
0x8E,0xFF,0x0C,0x89,0x7F,0xBF};
/*初始化8255A*/
voidInit8255()
{
unsignedchari,j;
for(j=0;j<10;j++)
for(i=0;i<255;i++);
XBYTE[PORT_CONTROL]=0x90;
LedsOff();
}
voidturn_On(charled,charChNumber,charmode)
{
if(mode==CA)
XBYTE[PORT_C]=LED_CODES[ChNumber];
else
XBYTE[PORT_C]=~LED_CODES[ChNumber];
XBYTE[PORT_B]=Select[led];
}
voidLedsOff()
{
XBYTE[PORT_B]=0x00;
}
voidturn_On_WithDot(charled,charChNumber,charmode)
{
if(mode==CA)
XBYTE[PORT_C]=LED_CODES[ChNumber]|0x7F;
else
XBYTE[PORT_C]=~LED_CODES[ChNumber]|~0x7F;
XBYTE[PORT_B]=Select[led];
}
----------------------------------------------------------------------------------------------------------------------
程序流程图:
测温仿真效果图:
6.炉温闭环PID控制系统仿真模型
到目前为止,整个PID控制的硬件设计已经完成,但对闭环控制而言,控制量u作用与被控对象(电炉)的控制效果我们却不得而知,因为还缺乏被控对象的仿真模型。
按自动控制的知识,被控对象可以用一个传递函数表示,传递函数的确定既可用数学推导的方法,也可用实验的方法确定。
一般而言,电炉的传递函数为K/(1+Ts)*e-〆s,式中的K为增益,T位时间常数,〆为延时时间,在仿真模型中,K取为2,T取为10,〆取为2;传递函数的输入量为电压U,输出量为温度。
在Proteus中,在元件选择页面中输入Laplace关键字在按照需要选择所需的传递函数模型,在本设计中,选择“1?
ORD:
LP”和“OP:
Delay”两种传递函数模型来表示电炉对象,他们分别在1storder和Operators子类中,两模块如下图所示。
用压控电阻表示PT100传感器,在元件选择页面输入VCR,在元件列表区域选择VCR器件,其符号如上图所示。
1?
ORD:
LP参数设置对话框
OP:
Delay参数设置对话框
VCR参数设置对话框
下图是利用“1?
ORD,OP:
Delay”和VCR建立的电炉闭环控制仿真模型,电热丝阻值取为2.5KΩ,PT100用压控电阻(VCR)表示。
在图中,压控电阻接入到温度检测放大子电路AMP中,AMP的输出Vt接至ADC0808的输入通道0.图
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 测控综合设计 PID温控器设计 测控 综合 设计 PID 温控
![提示](https://static.bdocx.com/images/bang_tan.gif)