基于51单片机的水温控制系统制作
适合于51单片机爱好者
压缩文件里有制作过程、代码与原理图。
本系统设计采用基于PID算法的单片机控制来实现水温的调控。单片机控制部分采用AT89C51单片机为核心,采用软件编程,实现用PID算法来控制PWM波的产生,继而控制电炉的加热来实现温度控制。通过编程对PID各参数的调整,来达到提高加温速度,减小超调的目的。 设计任务和主要内容 一升水在1kw电炉下加热,要求水温在一定范围内可由人工设定,并能在环境温度降低时自动调节,以保证设定的温度基本不变。 - 温度设定范围为40~90℃,最小区分度为1℃,标定温度小于等于1℃。
- 环境温度降低时温度控制的静态误差小于等于1℃。
- 用十进制数码管显示水的温度。
- 采用适当的控制方法,当设定的温度突变时,减小系统的调节时间和超调量。
- 温度控制的静态误差小于等于0.2℃。
- 在设定温度发生突变时,自动打印水温随时间变化的曲线。
- 系统设计原理
该水温控制系统主要由AT89S52单片机控制系统、温度采样转换器、温度控制电路。键盘显示电路等四部分组成,总体框图如上。 (一)总体方案论证 根据题目的要求,我们提出了以下三种方案: 方案1:采用传统的二位模拟控制方法,选用模拟电路,用电位器设定给定值,采用上下限比较电路将反馈的温度值与给定的值比较后,决定加热或者不加热。由于采用的模拟控制方式,系统受环境影响较大,不能实现复杂的控制算法使控制精度做得较高,而且不能用于显示和键盘设定。 方案2:采用单片机AT89S52为核心。采用数字温度传感器DS18B20采集温度变化信号,将其转换成数字信号并通过单片机处理后去控制温度,使其达到稳定。使用单片机具有编程灵活,控制简单的优点,使系统能简单的实现温度的控制及显示,并且通过软件编程能实现各种控制算法使系统还具有控制精度高的特点。 比较上述两种方案,方案2明显改善了方案1的不足,具有控制简单、控制温度精度高的特点,因此本设计电路采用方案2。 (二)各部分电路方案论证 1、温度采样部分 方案1:采用热敏电阻,可满足35℃--95℃的测量范围,但热敏电阻精度、重复性和可靠性都比较差,对于检测精度小于1℃的温度信号是不适用的。 方案2:采用数字温度传感器DS18B20。DS18B20是支持一线总线接口的温度传感器,具有抗干扰性强,体积小,灵活经济的特点。它的测量温度范围为-55℃~+125℃,在-10℃~+85℃范围内,精度为±0.5℃且有9~12位分辨率可调,使用电压为3~5V无需备用电源。此外DS18B20集合了64位光刻ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器,可以直接实现温度的测量和转换,无需再另接外部电路。 方案3:采用温度传感器AD590。AD590具有体积小、质量轻、线性度好、性能稳定等优点。其测量范围在-50℃~+150℃,满刻度范围误差为 ±0.3℃,当电源电压在5~10之间,稳定度为1%时误差只有±0.01℃,此外,AD590是温度—电流传感器,对于提高系统抗干扰能力有很大帮助。 从系统电路设计的复杂度,性价比等方面考虑,决定选用方案2。 2、控制电路部分 方案1:可以用逻辑电路搭建一个控制器,实现PID控制。但系统还要附加显示、温度设定等功能,要附加很多电路,总体的电路设计和制作比较繁琐。 方案2:采用8031芯片,其内部没有程序存储器,需要进行外部拓展,这给电路增加了复杂度。 方案3:本方案的CPU模块采用2051芯片,其内部有2KB单元的程序存储器,不需要外部拓展程序存储器,但由于系统用到较多的I/O口,因此此芯片的资源不够用。 方案4:采用AT89S52单片机,其内部有8KB单元的程序存储器,不需要外部扩展程序存储器,而且其I/O口达32个,完全满足本次设计需要。 比较这4种方案,综合的考虑单片机各部分资源,本次设计选用方案4。 3、加热方案和功率电路的选择 方案1:加热的装置,根据题目,可以使用电热炉进行加热,控制电炉的功率岂可控制加热速度。水温过高时,一般只能关掉电炉,让其自然冷却。为求更好的控制效果,也可以装置一个小风扇,电炉加热时风扇关闭,水温超高时关闭电炉开启风扇加速散热。 方案2:可以采用可控硅控制加热器的工作。通过单片机产生PWM信号来控制可控硅的导通和关断,控制加热器的加热时间,从而控制加热器的功率。 从加热的响应速度考虑,采用方案2。因为加热的功率较大,故电源采用市电220伏。 设计电路图如图2所示
DS18B20 ISP下载口
AT89S52主控电路 MOC3041功率电路 LCD液晶显示
PCB图如下:
功率电路 主控电路
本设计总体包括四个部分:主机控制部分、温度采样转换部分、温度控制部分、键盘显示部分。 - 温度采样转换电路
系统的温度采样转换由DS18B20集成芯片来实现。电路图如右 DS18B20性能描述 测量范围在-55℃~+125℃,在-10℃~+85℃范围内,精度为±0.5℃且有9~12位分辨率可调,使用电压为3~5V,无需备用电源。 DS18B20采用单总线通信技术,通信稳定可靠,且线路简单,容易实现。 其基本的通信过程如下: 主机拉低单总线产生至少480us的Tx复位脉冲; 然后由主机释放总线,进入Rx接收模式,主机释放总线时会产生一个由低电平变为高电平的上升沿; 单总线器件检测到该上升沿后,延时15~60us; 单总线器件通过拉低总线60~240us来产生应答脉冲; 主机接收到从机的应答信号后,说明有单总线器件在线,然后主机就可以开始对从机进行ROM命令和功能命令操作。 DS18B20直接输出数字量,可直接与单片机进行通信,读取测温数据,电路非常简单。使用它,主要工作量集中在了单片机编程上。 此部分电路主要由光电耦合器MOC3041和双向可控硅BTA16组成。以脉宽调制输出控制电炉与电源的接通和断开比例,以通断控制调压法控制电炉的输入功率。MOC3041的内部集成了发光二极管、过零检测电路和一个小功率双向可控硅。当单片机PWM输出为1,MOC3041中的发光二极管发光,用于过零检测电路的同步作用,内部的双向可控硅在过零后马上导通,从而使触发双向可控硅BTA16导通,负载中有电流通过,反之当单片机PWM输出为0,双向可控硅截止,负载中没有电流通过。光电耦合的耐压值为400v,它的输出级由过零触发的双向可控硅构成,它控制着主电路双向可控硅的导通和关闭。控制部分电路图如下
3、单片机控制部分 此部分是该系统的核心,系统的控制采用了单片机AT89S52。单片机AT89S52内部有8KB字节的可编程FLASH存储器和256字节的数据存储器。故系统不必外拓存储器,这样大大减少了系统的硬件电路。电路原理图如下:
4、按键及显示部分 系统仅采用五个按键来进行温度的控制。 在显示方面,我们采用了LCD1602的液晶显示模块,通过软件编程,可以实现所需要的显示。此外,液晶模块的使用也比较简单,只要连接数据总线,选通端口和命令/数据端口即可。 系统的硬件设计尽量简单,故工作任务主要在程序的设计上。
PID算法控制PWM输出:
程图如下
- void timer0() interrupt 1
- {
- uchar flag;
- TH0=0xd8 ; 有
- TL0=0xf0 ;
- TR1=1 ; 无
- P24=1 ; //启动输出
- CJ++;
- if(stemp>Wtemperature) flag=0
- {
- ei=stemp-Wtemperature; flag=1
- E=E+ei;
- ex=ej-ei;
- ej=ei;
- if(ei<6)
- {Ui=U0-Kp*(ei+Ti*E-Td*ex);}
- else Ui=U0-Kp*ei;
- flag=Ui/100;
- switch(flag)
- {
- case 9:{TH1=0xdc;TL1=0xd8;}break;
- case 8:{TH1=0xe2;TL1=0xb4;}break;
- case 7:{TH1=0xe8;TL1=0x90;}break;
- case 6:{TH1=0xec;TL1=0x78;}break;
- case 5:{TH1=0xf0;TL1=0x60;}break;
- case 4:{TH1=0xf2;TL1=0x54;}break;
- case 3:{TH1=0xf4;TL1=0x48;}break;
- case 2:{TH1=0xf8;TL1=0x30;}break;
- case 1:{TH1=0xfc;TL1=0x18;}break;
- case 0:{TH1=0xfd;TL1=0xa8;}break;
- default:{TH1=0xff;TL1=0xfa;}break;
- }
- }
- else {TH1=0xff;TL1=0xfa;}
- }
复制代码程序用T0和T1的嵌套来实现PWM波,T0控制波的频率,T1控制占空比,其效果图如下:
PID控制器: PID控制器采用单片机软件实现。输出PWM控制信号,定时器采用T0,T1的嵌套,T0定时是10MS,T1控制低电平的输出。由于加热器属于带滞后的一阶对象,故式中Kp,Ki,Kd的选择取决于加热器的阶跃响应特性和实际经验,为了实现PID参数的实时整定,各温度区间由实验测取最佳的Kp,Ki,Kd值。
1、动态温控测量 测量方式:接上系统的加热装置,装入1L室温的水,设定温控温度。记录调节时间、超调温度、稳态温度波动幅度等。 测量条件:环境温度18℃,加热器功率1000W。 测量结果数据 2、结果分析 由以上测量结果可见,系统性能基本达到了所要求的指标。 在温控指标中,影响系统性能的因素很多,最关键的是加热器本身的物理 性质及控制算法。传感器必须加上防水设施,故温度传感难免迟滞,加热器的加热本身有延迟,水对流传热也会造成测温的延迟,这些都会直接影响系统的控制性能。控制算法方面,需反复实验比较,在上升时间和超调量之间做权衡,选出综合效果最好的PID系数。 因为是直接接入220V的市电,当电路一通电,板面温度突然升高,以致烧坏电路板。于是之后我们在电路中加上了散热片。 温度传感器DS18B20不能直接浸在水中测温度,故我们将其固定在一导热性相对好的金属筒内,再没入水中测量。 功率电路的输出端原本应该加上一个电容来矫正零相位,然而当硬件电路都装好后,进行调试,发现加热器一直工作,没有办法实现温度的控制,检查发现是电容的问题。当加上电容时,在交流电的作用下,电路直接导通,根本不需要外加控制,故我们去掉了该电容,加热器这才受控。 本系统设计是以AT89S51单片机为核心,采用软件编程,运用PID算法来控制PWM波的产生,继而控制加热器的加热时间来实现温度的控制。在软硬件的调试过程中,出现了不少问题,如电路板发烫,程序不起作用,加热速度较慢等,但是在老师和同学的指导和帮助下,通过电路检查,程序修改等工作,问题基本上都得到了解决。在这一次设计过程中,我们了解了很多专业知识,动手能力也得到了提高。然而,系统还存在着一些问题,如水温达到稳定的时间。
单片机源程序如下:
- /***************************************************************
- 项目名称:水温控制系统设计;
- 功 能:通过STC89C52单片机控制可控硅驱动加过零检测电路作为
- 功率控制电路来控制加热过程,通过键盘扫描来设定水温,
- DS18B20实时测量水的温度,将实际水温与设定水温比较
- 通过PID控制算法调节,是实际水温与设定水温接近。从而
- 达到控制水温的目的。
- 作 者:0903 蔺一锋
- 日 期:2010年11月3日
- ***************************************************************/
- #include<reg52.h>
- #include<stdio.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit s1=P2^0;
- sbit s2=P2^1;
- sbit s3=P2^2;
- sbit s4=P2^3;
- sbit s5=P2^4;
- sbit ds=P2^5;
- sbit beep=P2^6;
- sbit rd=P1^0;
- sbit rs=P1^1;
- sbit wr=P1^2;
- sbit lcden=P1^3;
- sbit PWM=P1^6;
- sbit led1=P1^4;
- sbit led2=P1^5;
- uchar set_temp,keytemp;
- uint temp;
- uchar c;
- bit flag,flag1,flag2;
- float f_temp,t;
- int timecount,z;
- float KP,KI,KD;
- float e1,e2,e3;
- float uk,duk;
- uchar HighL,HighH,PWMH;
- float k;
- uchar code table[]={"设定温度:"};
- uchar code table1[]={"实测温度:"};
- uchar code table2[]={"加热"};
- uchar code table3[]={"保温"};
- uchar code table4[]={"作者:0903锋仔@"};
- uchar code table5[]={"系统初始化"};
- uchar code table6[]={"measured Temperature"};
- uchar code table7[]={"水温控制系统设计"};
- uchar code table8[]={" "};
- void delay(uint z)//延时函数,延时5ms
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- /***************************************
- 键盘扫描函数
- 通过S5,S4,S3,S2,S1键来分别实现温度设定值的
- 粗加,粗减,精加,精减,和确定功能。
- ***************************************/
- void keyscan()
- {
- if(set_temp>=100)//将设定温度限定在0-100度之间
- set_temp=100;
- if(set_temp<=0)
- set_temp=0;
- if(s5==0)//此键按下设定温度加5
- {
- delay(10);
- if(s5==0)
- {
- flag1=0;
- set_temp+=5;
- if(set_temp>=100)
- {
- set_temp=100;
- beep=0;
- delay(1000);
- beep=1;
- }
- }while(s5==0);
- }
- if(s4==0)//此键按下设定温度减5
- {
- delay(10);
- if(s4==0)
- {
- flag1=0;
- set_temp-=5;
- if(set_temp<=0)
- {
- set_temp=0;
- beep=0;
- delay(1000);
- beep=1;
- }
- }while(s4==0);
- }
- if(s3==0)//此键按下设定温度加1
- {
- delay(10);
- if(s3==0)
- {
- flag1=0;
- set_temp++;
- if(set_temp==100)
- {
- set_temp=100;
- beep=0;
- delay(1000);
- beep=1;
- }
- }while(s3==0);
- }
- if(s2==0)//此键按下设定温度减1
- {
- delay(10);
- if(s2==0)
- {
- flag1=0;
- set_temp--;
- if(set_temp==0)
- {
- set_temp=0;
- beep=0;
- delay(1000);
- beep=1;
- }
- }while(s2==0);
- }
- if(s1==0)//确定加热状态(加热与不加热)
- {
- delay(10);
- if(s1==0)
- {
- flag1=1;
- }
- while(s1==0);
- }
- }
- /******************************************
- DS18B20温度采集模块程序设计
- 通过DS18B20实时采集水温,反映给单片机系统
- ******************************************/
- void dsreset()//DS18B20复位函数
- {
- uint i;
- ds=0;
- i=103;
- while(i>0)i--;
- ds=1;
- i=4;
- while(i>0)i--;
- }
- bit tempreadbit()//从DS18B20 RAM读一位数据
- {
- uint i;
- bit dat;
- ds=0;i++;
- ds=1;i++;i++;
- dat=ds;
- i=8;while(i>0)i--;
- return(dat);
- }
- uchar tempread()//从DS18B20 RAM读一字节数据
- {
- uchar i,j,dat;
- dat=0;
- for(i=1;i<=8;i++)
- {
- j=tempreadbit();
- dat=(j<<7)|(dat>>1);
- }
- return(dat);
- }
- void tempwritebyte(uchar dat)//向DS18B20写以字节的数据
- {
- uint i,j;
- bit testb;
- for(j=1;j<=8;j++)
- {
- testb=dat&0x01;
- dat=dat>>1;
- if(testb)//写1
- {
- ds=0;
- i++;i++;
- ds=1;
- i=8;while(i>0)i--;
- }
- else//写0
- {
- ds=0;
- i=8;while(i>0)i--;
- ds=1;
- i++;i++;
- }
- }
- }
- /*void readrom()
- {
- dsreset();
- delay(1);
- tempwritebyte(0x33);
- tempwritebyte(0xbe);
- readrom=tempread();
- }
- void matchrom()
- {
- dsreset();
- delay(1);
- tempwritebyte(0x55);
- }*/
- void tempchange()//启动温度转换
- {
- dsreset();
- delay(1);
- tempwritebyte(0xcc);
- tempwritebyte(0x44);
- }
- float get_temp()//温度值读取与处理函数
- {
- uchar a,b;
- dsreset();
- delay(1);
- tempwritebyte(0xcc);
- tempwritebyte(0xbe);
- a=tempread();
- b=tempread();
- temp=b;
- temp<<=8;
- temp=temp|a;
- f_temp=(float)(temp*0.0625);
- f_temp=f_temp*10;
- return(f_temp);
- }
- /**********************************************
- 12864显示模块
- 显示实际温度制和设定温度值
- **********************************************/
- void write_com(uchar com)//向12864写指令
- {
- rs=0;
- wr=0;
- delay(1);
- P0=com;
- lcden=1;
- delay(1);
- lcden=0;
- delay(1);
- }
- void write_date(uchar date)//向12864写数据
- {
- rs=1;
- wr=0;
- delay(1);
- P0=date;
- lcden=1;
- delay(1);
- lcden=0;
- delay(1);
- }
- void display(float m,uchar n)//显示设定温度、实测温度、加热状态
- {
- uint i,j;
- float b;
- float p;
- uchar a1,a2,a3;
- uchar b1,b2,b3,b4;
- if(n<100)
- {
- a1=0;
- a2=n/10;
- a3=n%10;
- }
- else
- {
- a1=1;
- a2=0;
- a3=0;
- }
- p=m;
- j=(uint)(p*10);
- b1=(uchar)(j/1000);
- b2=(uchar)(j%1000/100);
- b3=(uchar)(j%100/10);
- b4=(uchar)(j%10);
- write_com(0x90+5);//显示设定温度
- write_date(0x30+a1);
- write_date(0x30+a2);
- write_date(0x30+a3);
- write_com(0x88+5);//显示实测温度
- write_date(0x30+b1);
- write_date(0x30+b2);
- write_date(0x2e);
- write_date(0x30+b3);
- write_date(0x30+b4);
- b=((float)(b1*100+b2*10+b3))/10.0;
- i=0;
- if((b+0.2)<n)
- {
- led1=0;
- write_com(0x98+1);
- while(table2[i]!='\0')
- {
- write_date(table2[i]);
- i++;
- }
- flag2=1;
- }
- else
- {
- led1=1;
- i=0;
- write_com(0x98+1);
- while(table8[i]!='\0')
- {
- write_date(table8[i]);
- i++;
- }
- i=0;
- if((b=n)||((b>n)&&((b-0.2)<=n))||((b<n)&&((b+0.2)>=n)))
- {
- led2=0;
- write_com(0x98+4);
- while(table3[i]!='\0')
- {
- write_date(table3[i]);
- i++;
- }
- }
- }
- if(flag2==1)
- {
- flag2=0;
- led2=1;
- i=0;
- write_com(0x98+4);
- while(table8[i]!='\0')
- {
- write_date(table8[i]);
- i++;
- }
- }
- }
- /*****************************************************
- PID控制算法程序设计
- 通过PID控制算法可以使实际水温在设定水温周围呈很小范围的
- 波动,从而使实际水温值接近设定水温值
- *****************************************************/
- void conversion()//定时器2初值处理函数
- {
- uint temp2;
- temp2=65536-PWMH*10;
- HighH=temp2/256;
- HighL=temp2%256;
- }
- void senddate(float y)
- {
- // uint i;
- if(flag==1)
- {
- ES=0;
- flag=0;
- c=0;
- TI=1;
- printf("The measured temp:%f",y);
- // SBUF=1;
- while(!TI);
- TI=0;
- ES=1;
- }
- }
- void init()//初始化函数
- {
- uint i,j;
- TMOD=0x21;
- TH1=0xfd;
- TL1=0xfd;
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- PWMH=0;
- conversion();
- TH2=(65536-50000)/256;
- TL2=(65536-50000)%256;
- rd=1;
- lcden=0;
- write_com(0x30);
- write_com(0x0c);
- write_com(0x01);
- write_com(0x90);
- while(table5[i]!='\0')//系统初始化
- {
- write_date(table5[i]);
- i++;
- delay(20);
- }
- for(j=0;j<=1;j++)//6个点的三次循环
- {
- write_com(0x88+4);
- for(i=0;i<=5;i++)
- {
- write_date(0x2e);
- delay(200);
- }
- delay(100);
- write_com(0x88+4);
- for(i=0;i<=5;i++)
- {
- write_date(0x20);
- }
- delay(100);
- }
- i=0;
- write_com(0x80);//显示 水温控制系统设计标题
- while(table7[i]!='\0')
- {
- write_date(table7[i]);
- i++;
- }
- i=0;
- write_com(0x90);//显示 设定温度
- while(table[i]!='\0')
- {
- write_date(table[i]);
- i++;
- }
- i=0;
- write_com(0x88);//显示 实测温度
- while(table1[i]!='\0')
- {
- write_date(table1[i]);
- i++;
- }
- // tempwritebyte(0x4e);//设定DS18B20的分辨率为11位
- // tempwritebyte(0x5f);
- PWM=0;
- e1=0;
- e2=0;
- e3=0;
- duk=0;
- uk=0;
- KP=20;//PID控制算法参数
- KI=0.061;
- KD=30;
- REN=1;//串口通信设置
- SM0=0;
- SM1=1;
- ET0=1;
- ET2=1;
- TR0=1;
- TR1=1;
- TR2=1;//启动定时器2
- EA=1;
- ES=1;
- }
- void main()
- {
- init();
- while(1)
- {
- keyscan();//调用键盘扫描函数
- tempchange();//启动温度转换
- t=get_temp();//提取实测温度
- display(t,set_temp);//显示设定温度和实测温度
- senddate(t);//向上位机发送数据函数
- if((flag1==1))
- {
- if(timecount>=375)
- {
- timecount=0;
- e1=set_temp-t;
- duk=(KP*(e1-e2)+KI*e1+KD*(e1-2*e2+e3));//PID控制算法式
- uk=uk+duk;
- if(e1>=75)
- {
- z=4;
- }
- else if(e1>=50)
- {
- z=3;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
基于51单片机的水温控制系统.rar
(18.56 MB, 下载次数: 916)
|