1、 课程设计说明书 题 目:半导体制冷片温度控制 院 (系):xxxxxxxxxxx学院xxxxx 专 业: xxxxxxxxxxxx 学生姓名: XXXX 学 号: xxxxxxxxxxxx 指导教师: xxxxxxxxxxxxxxx 2012 年 3 月 10 日 摘 要 温度是工业中非常关键的一项物理量,在农业,现代科学研究和各种高新技术的开发和研究中也是一个非
2、常普遍和常用的测量参数。温度控制的原理主要是:将随温度变化而变化的物理参数,通过温度传感器转变成电信号,传给计算机,与给定温度相减后得到偏差,经过控制器后输出给控制对象达到控温的目的。 半导体制冷片是利用半导体材料的Peltier效应,当直流电通过两种不同半导体材料串联成的电偶时,在电偶的两端即可分别吸收热量和放出热量,可以实现制冷的目的。制冷速度与通过的电流大小成正比。 本设计针对用半导体对水箱的制冷模型设计了相应模糊PI控制器对水箱进行计算机恒温控制。 关键词: 半导体制冷 ;STC12C5A08S2;模糊PI;PWM; 引言 1 1 课程设计概述 1 1.1 课程设计题
3、目 1 1.2 主要仪器设备 1 2 硬件设计 1 2.1 单片机部分 1 2.2 串行接口部分 2 2.3驱动电路部分 2 3 软件设计 3 3.1 流程图设计 3 3.1.1 温度控制主程序流程图 3 3.2 控制算法设计 4 3.2.1 控制对象模型 4 3.2.2 PI控制器设计 5 3.2.3 控制器的设计 5 4 系统调试 5 4.1 单片机程序仿真 5 4.2 STC12C5A08S2单片机系统电路调试 6 4.3 驱动电路调试 7 4.4 系统调试 7 5 总结与改进展望 7 6 谢辞 8
4、 引言 温度作为一项热工参数,在工业现场和过程控制中具有至关重要的作用。半导体制冷相对于传统制冷方式,有着体积小,重量轻,无制冷剂而不污染环境,作用速度快,使用寿命长,且易于控制。本文介绍了使用DS18B20作为温度传感器的PWM半导体制冷控制系统。 1 课程设计概述 1.1 课程设计题目 设计半导体制冷片的线性驱动电路和热敏元件的测温电路,再设计PI控制器来调节制冷电压,实现温度控制,控制范围15~25度,控制精度±0.5度,通过键盘进行温度设置,实际温度可以实时显示。 *附加要求:通过RS232或RS485接口与PC机通信,在PC机上进行参数显示和设置。
5、 1.2 主要仪器设备 半导体制冷片(连水箱) 1台 示波器 1台 直流稳压电源 1台 数字万用表 1块 PC机 1台 2 硬件设计 整个系统以单片机STC12C5A08S2为核心部件。在08S2最小系统外围添加了按键,显示,与PC机的通信接口,以及光电耦合PC817和MOS管IRF9540构成的驱动电路。 2.1 单片机部分 本设计选择的单片机芯片是STC12C5A08S2,其原理图如2-1所示。该芯片
6、的P0.0-P0.3用作键盘数字量输入,加入了上拉电阻按键未按下时始终处于高电平状态,读按键值前先给P0口赋值为0; P1.0作为DS18B20的数据输入端口; P2.0-P2.7作LCD1602的数据输出端口; P4.4-P4.6作LCD1602的控制信号; P1.3作为光耦合的控制信号; P3.0和P3.1是STC12C5A08S2的串口,实现上电复位程序下载。 图 2-1 STC12C5A08S2最小系统原理图 2.2 串行接口部分 MAX232通过内部电压倍增及电压反向电路,把TTL电平与RS232电平互换,实现单片机与PC机的串口通信。 图 2-2
7、MAX232及串行接口原理图 2.3驱动电路部分 JPWM为P1.3口的PWM信号输入,作为光耦PC817的触发导通信号,从而产生MOS管IRP9540导通的触发信号,实现对右端负载的控制。如图2-3所示,本电路中还加入了拨动开关可对系统进行开关控制。 图 2-3 驱动部分原理图 3 软件设计 3.1 流程图设计 3.1.1 温度控制主程序流程图 温度控制主程序流程图设计如图 3-1所示。 STC12C5A08S2中的主程序需要完成下几个工作: 1. 调用子函数对系统初始化,其中包括对自身的定时器T0,T1,I/O口,PWM口(P1.3),串口的初始化,以及
8、对外部器件DS18B20和LCD1602的初始化;延时2S钟显示欢迎屏幕,等整个系统电压稳定后读取开机时的温度; 2. 调用子函数读取当前温度值 3. 调用子函数把当前读取的温度以及设定值通过串口送入PC机显示; 4. 调用子函数判断PC机是否有新的数据传送到单片机; 5. 调用子函数,把设定值与当前值相比较,对输出PWM进行控制; 6. 调用子函数刷新当前页面; 7. 调用子函数进行按键判断,依据按键值调用不同的子函数进行翻页或者设置; 图 3-1温度控制主程序流程图 3.2 控制算法设计 3.2.1 控制对象模型 制冷片的水箱模型可近似地认为成一阶惯性
9、环节,从而测量系统阶跃响应可模拟出系统的数学模型,G(s)=1/(T*s+1),其中T等于阶跃响应中调节时间Ts的四分之一。给电流I=0.5A时阶跃响应数据记录如下,其中t=0时,温度约为27℃;t=100时,温度约为24℃。取终值11KΩ的98%,Ts约为54min=3240s,则G(s)=1/(810*s+1)。 1.由此看出,制冷系统是大惯性系统,制冷需要一段时间之后温度才开始下降; 2.至停止制冷后,温度还会有小幅度的下降,而设定温度越低,下降的幅度越小; 3.由于与外界的热交换,温度越低时,水箱的自然升温速度越快。 图 3-2 对象阶跃响应拟合曲线 3.2.2 PI
10、控制器设计 PI调节器的微分方程为:y(t)=Kp[e(t)+1/Ti*∫e(t)dt]。控制器有两种算法,位置型和增量型。位置型算法时,计算每次实际值与设定值的偏差为e0,上次的偏差为e1,则控制量u=kp*e0+ki*(e0+e1)。增量型算法时,u+=e0*ki+(e1-e0)*kp。本次系统中选用的是位置型算法。 3.2.3 控制器的设计 根据制冷片的滞后特点,为了使制冷片能迅速达到设定的温度,应该在离设定温度较远时给负载加上最大功率;又为了防止制冷片的大惯性的特性使系统产生严重的超调,需要提前在一定的范围内进行PI控制以达到最佳效果;而最后阶段,需要预先判断
11、系统的停止工作点,让制冷片的温度扩散的整个水箱,此时停止制冷。 若设定温度大于当前温度时,系统也将停止制冷,等温度慢慢回升。 现设定开始进入PI控制的温度上限为设定值T+1℃,而停止制冷的温度,根据多次实验建立的数据库如下: 设定值温度范围T℃ 停止制冷温度t℃ 23<=T T*0.006 19<=T<23 T+0.7 T<19 T 4 系统调试 4.1 单片机程序仿真 由于PROTEUS中没有我们选用的STC12C5A08S2型号的单片机,因此使用AT89S2的单片机代替。仿真电路如下图所示,仿真时除初始化时当前温度显示为85℃以外,一切工作正常。
12、 图 4-1 系统控制电路仿真电路图 4.2 STC12C5A08S2单片机系统电路调试 STC12C5A08S2最小系统包括晶振和复位电路,按键电路,LCD显示,以及通信下载接口。 由于以前没有使用过这个型号的单片机,也没有做过串口下载器,所以先把串口接口芯片MAX232及其外部电容和单片机的晶振电路接在面包板上,通过串口与单片机连接调试下载功能,由于一开始电源和地之间没有接电容,因此系统不是很稳定,有时可以下载,有时不可以,接入电容之后系统比较稳定了。 依据插在面包板的电路图画原理图以及PCB,板子做出来之后,用万用表测试各点的连接特性,正常。上电,电源指示灯偏暗,
13、把10K的限流电阻换为1K的之后指示灯工作正常。 由于STC12C5A08S2单片机运算速度比89S52快,因此程序中延时子函数一律乘以12。修改管脚使其适应实际的电路板,重新编译后下载程序。液晶没有显示,调节液晶显示偏压信号端的电压,使其接近地,液晶显示正常。接上DS18B20,温度显示正常。用按键进行翻页及设置,按键功能正常。据此,单片机系统板及程序完全工作正常。 4.3 驱动电路调试 驱动电路板做好后进行测试。用外用表测量,各点连接特性正常。分别把PWM输入端接地和接VCC,用示波器观察负载输出电压,输出电压对应为零和为12伏,工作正常,接入PWM信号后,输出变为零,不正常。
14、 用示波器观察MOS管G极电压,发现为锯齿波,上升部分倾斜,下降部分竖直。分析原因为MOS管的S极与电源之间的电阻太大,使通过MOS管的电流太小,MOS管的电容特性使其在一定充电时间内电压不能达到导通,因此输出恒为零。把电阻调小,锯齿波顶部逐渐变平,电阻继续调小,输出的最低电压开始升高不为零。此时继续调节电阻已没有意义,在程序中把PWM输出的波形频率降低,降到最低14HZ。此时G极波形已为方波,继续减小电阻,直到G极输出的最低电压恰好为零,使其能通过更高频率的信号。最后稍微增大该电阻,使其电压被允许在一定范围内波动。 测量连接负载的D极,D极波形为与输入的PWM反向的方波,驱动电路工作正常。
15、 4.4 系统调试 各个部分的调试完成以后,对整个系统进行调试,从室温约27.5℃开始,设置水箱的温度分别为26℃,23℃,20℃。 具体记录的数据如下所示。 表 6-5-1 设定值℃ 最小值℃ 最大值℃ 超调量% 误差范围% 26 25.82 26.18 0.69 ±0.69 23 22.88 23.18 0.52 ±0.78 20 19.94 20.06 0.3 ±0.3 加入算法后,超调量被控制在1%以下,温度下降速度较快,较稳定。 5 总结与改进展望 本次设计中,我完成了包括资
16、料收集,系统设计及仿真,程序编写,电路图与PCB板的绘制腐蚀焊接及调试的全过程,整个系统完成测试后,性能稳定,基本达到了预期的目标。 水箱温度在29~10摄氏度范围内可控(设置值不大于当前室温),LCD液晶温度显示稳定,与之前购买的温度计有大约恒定1℃的温差。传送到PC机的数据显示正常,可以从PC机接收数据对各个参数进行设置。 温度控制算法的设计,在原模糊分段控制的基础上,加上了PI控制,虽然最后由于时间关系,参数中只使用了P,但是可以证明,加入了PI控制的模糊算法比单纯的模糊分段控制取得了更好的效果。 在本次设计中,也存在着可以改进的地方。例如程序中有部分程序段是几
17、乎重复使用的,但在各种情况下,只使用了switch函数分情况讨论,没有总结出特定的函数对所有的情况进行处理,这导致了程序过长,应该还有可以压缩的空间。还有对于参数的调整,只使用了P,没有用到I,而且对于停止控制的位置,也还应该重新配合。这都是需要作出调整的,而且DS18B20检测温度只能精确到0.0625℃,若要再进一步提升各种指标的话,最好换一个精度更高的温度检测手段。 6 谢辞 本次设计能够完成得到了许多帮助,首先感谢赵学军老师,李平老师以及龙超老师的悉心指导,为我们提供了设计的思路,为我们指出了设计的各种不足指出,并一次次为我们解决了调试过程中出现的各种问题。正是有了他们的指导
18、我的设计才得以顺利完成。 感谢一同进行设计的同学们,是他们在我对着板子一筹莫展地时候给我指出了可能的错误,在调试过程中给予我各种意见,并且测量数据时给予我各种帮助,没有他们的帮助,我的设计不能得以完善。 感谢一直教导我的任课老师,是任课老师的谆谆教导,使得我们可以学以致用,完成本次设计一定是基于扎实的理论课基础的。 最后感谢在本次设计中所有帮助过我的老师同学们。参考文献 [1] 胡寿松. 自动控制原理[M] . 北京:科学出版社,2007. [2] 华成英,童诗白. 模拟电子技术基础[M] . 北京:高等教育出版社,2006. [3] 王再英,刘淮霞,陈毅静. 过程控制
19、系统与仪表[M] . 北京:机械工业出版社,2006. [4] 马淑华,王凤文,张美金.单片机原理与接口技术[M] . 北京:邮电大学出版社,2007. [5] 潘新民,王燕芳. 微型计算机控制技术实用教程[M] . 北京:电子工业出版社,2006. [6] 谭浩强. C程序设计[M] . 北京:清华大学出版社,2005. 附 录 主要电路PCB: STC89C5A08S2最小系统 驱动电路 STC12C5A08S2程序 /*************************************************************************
20、/
#include
21、 number[13]="0800320101 CC"; uchar e[4]={0,0,0,0}; uchar us[4]={0,0,0,0}; uchar shou[4]; uchar TL,TH,page,num=0,whi=0; int fub=100,ki=0,kp=50; uchar fus[8]="Fu: 100 ",kps[8]="Kp: 050 ",kis[8]="Ki: 000 "; int TN,TD,Ntemp100,Stemp100=2600,e1=0,e0=0,u=0; bit busy; /***************显示设置*****
22、/ void page0()//初始化欢迎页 { int i; _1602_init(); _1602_writecode(0x00+0x80);//设置显示地址 for(i=0;i<16;i++) //显示欢迎 _1602_writedata(welcome[i]); _1602_writecode(0x40+0x80);//设置显示地址 for(i=0;i<13;i++) //显示学号姓名 _1602_writedata(number[i]); for(i=0;i<40;i++) delay(5000
23、);
}
void page1() //温度显示页
{
int i;
_1602_writecode(0x00+0x80);//设置显示地址
for(i=0;i<12;i++) //显示设定温度
_1602_writedata(settemp[i]);
_1602_writecode(0x40+0x80);//设置显示地址
for(i=0;i<12;i++) //显示现在温度
if(Stemp100>2300) stop=Stemp100*3/500; //关断值的模糊控制
else if(1900 24、op=7;
else stop=0;
e1=e0;
e0=Ntemp100-Stemp100;
e[3]=e0%10;
e[2]=(e0/10)%10;
e[1]=(e0/100)%10;
e[0]=(e0/1000);
_1602_writecode(0x0c+0x80);//设置显示地址
for(i=0;i<4;i++) //显示误差
_1602_writedata(e[i]+0x30);
if(stop 25、 u=255;
if(u<0) u=0;
}
if(e0>=fub) u=0xff; //全开
if(e0<=stop) u=0x00;//关断
us[3]=u%10;
us[2]=(u/10)%10;
us[1]=(u/100)%10;
us[0]=(u/1000);
_1602_writecode(0x4c+0x80);//设置显示地址
for(i=0;i<4;i++) //显示控制量
_1602_writedata(us[i]+0x30);
CCAP0H=u;
}
/***********数据处理,控制*********** 26、/
//改变占空比:CCAP0H=0xff-0xff*占空比/100=0xff-51/20*占空比 ;0x00,输出100%,停止制冷;
/************按键判断处理********************/
uchar keyin(void) //单按键值判断,1--setting,2--up,4--down,8--enter
{
uchar key,come=0;
keys=0x00;
delay(2);
key=keys&0x0f;
if(key!=0) //防抖
s=settemp[6]-0x30;
x=seting2 27、0x06,s);
settemp[6]=x+0x30;
Stemp100+=x*100;
s=settemp[8]-0x30;
x=seting2(0x08,s);
settemp[8]=x+0x30;
Stemp100+=x*10;
}
void setingc(uchar n) //按键的参数设置
{
uchar s,i;
switch(n)
{
case 0:{ fub=0; //模糊量
for(i=4;i<7;i++)
{
s=fus[i]-0x30;
s=seting2( 28、i,s);
fub=fub*10+s;
fus[i]=s+0x30;
}
break;
}
case 1:{ kp=0;
for(i=4;i<7;i++)
{
s=kps[i]-0x30;
s=seting2(i+0x40,s);
kp=kp*10+s;
kps[i]=s+0x30;
}
break;
}
case 2:{ ki=0;
for(i=4;i<7;i++)
29、 {
s=kis[i]-0x30;
s=seting2(i+0x48,s);
ki=ki*10+s;
kis[i]=s+0x30;
}
break;
{
kps[i+3]=shou[i];
s=shou[i]-0x30;
kp=kp*10+s;
}
shou[0]=0;
break;
}
case 'I': { //变量ki
ki=0;
for(i=1;i<4;i+ 30、)
{
kis[i+3]=shou[i];
s=shou[i]-0x30;
ki=ki*10+s;
}
shou[0]=0;
break;
}
}
}
/***********按键判断处理**********************/
/*************PWM初始化********************/
void PWM_init() //PWM初始化
{
TMOD=0x22;//T0工作在方式2,8位重装
TH0=0x00;
TR0=1 31、 //开始计数
CCON=0x00;//关PCA
CH=0; CL=0; //计数寄存器清零
CMOD=0x04;//始终工作;f=定时器0溢出频率;PWM模式禁止中断
CCAPM0=0X42; //PCA0工作在PWM模式
PCA_PWM0=0x00; //若此为为0x02,则输出恒为0;若要调整占空比,需赋值为0;
CCAP0H=0x00;//输出占空比100%
CR=1; //开始计数
}
/**************PWM初始化*******************/
/*************串口初始化*************** 32、/
void Uart_init(void)
{
IE=0x90;
void main()
{
uchar key,i;
P4SW=0x70;//P4为IO口
page=1; //默认页为第一页
PWM_init();
_1602_init();
Uart_init(); //串口初始化
page0(); //显示初始化欢迎页
_1602_writecode(0x01);//清屏
delay(50);//清屏后若无延时则第一个字符显示不出
sent_pc(welcome,16);
sent_pc_byte('\r 33、'); //13,10合起来为回车
sent_pc_byte('\n');
sent_pc(settemp,10);
sent_pc(nowtemp,10);
while(1)
{
k1: gets(); //读取当前温度
sent_pc_byte('\r'); //13,10合起来为回车
sent_pc_byte('\n');
sent_pc(settemp,10); //给PC机送设定温度以及当前温度
sent_pc(nowtemp,10);
control(); //进行控制
if(page==1)
34、 {
page1(); //显示当前温度页
key=keyin();//判断键值
switch(key)
{
case 1: {CCAP0H=0x00;setingt(); goto k1;} //进行设置
case 2:
case 4: { _1602_writecode(0x01);
delay(50);//清屏
page=2; } //上下翻页
}
}
if(page==2)
{
page2(); //显示参数设定页
key=keyin() 35、//判断键值
switch(key)
_1602_writedata(nowtemp[i]);
}
void page2()//参数显示页
{
int i;
_1602_writecode(0x00+0x80);//设置显示地址
for(i=0;i<8;i++) //显示Fuzzy
_1602_writedata(fus[i]);
_1602_writecode(0x40+0x80);//设置显示地址
for(i=0;i<8;i++) //显示kp
_1602_writedata(kps[i]);
for(i= 36、0;i<8;i++) //显示ki
_1602_writedata(kis[i]);
_1602_writecode(0x0c+0x80);//设置显示地址
_1602_writedata(whi+0x30);
_1602_writedata(' ');
_1602_writedata(' ');
_1602_writedata(' ');
}
/**************显示设置*********************/
/**********数据处理,控制*********************/
void gets() //读取温度并计 37、算
{
result_18b20();
TL=read_18b20(); //先读的是温度值低位
TH=read_18b20(); //接着读的是温度值高位
TN=TH*16+TL/16;//整数部分
TD=TL&0x0f; //小数部分
TD=TD*100/16;
Ntemp100=TN*100+TD;
nowtemp[9]=Ntemp100%10+0x30;
nowtemp[8]=(Ntemp100/10)%10+0x30;
nowtemp[6]=(Ntemp100/100)%10+0x30;
nowtemp[5]=(Nt 38、emp100/1000)%10+0x30;
nowtemp[4]=(Ntemp100/10000)+0x30;
}
void control() //对PWM值进行控制
{
int i,stop;
{
delay(10);
key=keys&0x0f;
if(key!=0)
{
come=key;
}
}
while(keys); //等待弹起
return(come);
}
uchar seting2(uchar adr,uchar shezhi) //单个数字设置
{
bit 39、c=1;
uchar s=shezhi,key;
_1602_writecode(adr+0x80);
while(c)
{
key=keyin();
switch(key)
{
case 2: {s++; s=s%10;goto k2;}
case 4: { if(s==0) s=9;
else s--;
goto k2;}
case 8: c=0;
}
_1602_writecode(adr+0x80);
k2: if(key)
_1602_writedata(s+0x30) 40、
}
return(s);
}
void setingt() //温度设置
{
uchar s,x;
Stemp100=0;
s=settemp[5]-0x30;
x=seting2(0x05,s);
settemp[5]=x+0x30;
Stemp100+=x*1000;
}
}
}
//依据从PC机一次性传入的四位数据的第一位进行判断,本程序只用到以下几个参数,若有需要可随时添加
void setting_pc() //PC机的参数设置
{
uchar i,s;
switch(shou[0])
41、{
case 'S': { //修改设定值
settemp[5]=shou[1];
settemp[6]=shou[2];
settemp[8]=shou[3];
Stemp100=0;
s=settemp[5]-0x30;
Stemp100+=s*1000;
s=settemp[6]-0x30;
Stemp100+=s*100;
s=settemp[8]-0x30;
Stemp100+=s*10;
shou[0]=0;//清空暂存的首位
42、break;
}
case 'F': { //修改模糊量,此处模糊量定义为系统开始进行PI运算的上限
fub=0;
for(i=1;i<4;i++)
{
fus[i+3]=shou[i];
s=shou[i]-0x30;
fub=fub*10+s;
}
shou[0]=0;
break;
}
case 'P': { //变量kp
kp=0;
for(i=1;i<4;i++)
43、
SCON=0x50;//模式一:8位,波特率可调;不是地址筛选模式;可接收
PCON=0x00;//SMOD=0
TH1=253; //253,波特率9600;208,波特率600
TL1=253;
TR1=1;
busy=0;
}
/***************串口中断********************/
void Uart() interrupt 4
{
if(RI)
{
RI=0;
if(num==4) num=0;
shou[num]=SBUF; //一次性把4位数存入shou中
num++;
44、
if(num==4) setting_pc(); //判断PC机传入的数据
}
if(TI)//发送完成进入中断
{
TI=0;
busy=0;
}
}
void sent_pc_byte(uchar x)
{
while(busy); //等待上次传送完成
busy=1; //标志位置1,标示正忙
SBUF=x;
}
void sent_pc(char *s,int n) //从下位机到上位机发送
{
int i;
for(i=0;i 45、i));
}
}
{
case 1: {whi++;
if(whi==4) whi=0;
goto k1;} //进行设置
case 2:
case 4: { _1602_writecode(0x01);
delay(50);//清屏 page=1;
goto k1;} //上下翻页
case 8: setingc(whi);
}
}
for(i=0;i<3;i++)
delay(5000);
}
} 46、
DS18B20头文件
#ifndef _ds18b20_h_
#define _ds18b20_h_
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P1^0;
bit flagt;
void delay_18b20(uint i)
{
i=i*12;
while(i--);
}
void start_18b20() /*****初始化程序****/
{
DQ=1;
delay_18b20(15);
DQ=0;
delay_18b20 47、80);
DQ=1;
delay_18b20(10);
while(!DQ);
}
uchar read_18b20() /** 读一个字节**/
{
uchar da=0x00,i;
for(i=0;i<8;i++)
{
DQ=1;
delay_18b20(3);
DQ=0;
da=da>>1;
DQ=1;
if(DQ)da=da|0x80;
delay_18b20(10);
}
return(da);
}
v 48、oid write_18b20(unsigned char date) /*写一个字节*/
{
unsigned char i;
LCD1602头文件
#ifndef _LCD1602_h_
#define _LCD1602_h_
#define date P2
sbit RS=P4^6;//寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器
sbit RW=P4^5;//读写信号线,高电平时进行读操作,低电平时进行写操作
sbit E=P4^4;//使能端,当E端由高电平跳变成低电平时,液晶模块执行命令
49、
void delay(uint n) //延时函数
{
int i;
n=n*12;
for(i=0;i 50、 date=x;
delay(3);
E=1;
delay(3);
E=0;
}
for(i=0;i<8;i++)
{
DQ=0;
DQ=date&0x01;
delay_18b20(5);
DQ=1;
date=date>>1;
}
delay_18b20(5);
}
void result_18b20()
{
start_18b20();
write_18b20(0xcc);
write_18b20(0x44);
delay_18b20(50);
st






