基于单片机的仓库温度控制系统设计

本设计采用STC89C51单片机,DS18B20温度传感器和LCD1602液晶显示器,实现仓库温度监测和风扇转速控制。系统具备温度上下限设置、掉电存储、蜂鸣器报警等功能,通过按键控制,降低成本并提高实用性。

摘  要

随着科学技术的不断发展带动着电子行业的地位越来越重,现在电子产品几乎在社会的各个领域都可以见到。这些技术的发展有效的带动着社会生产力的发展和信息化的提高,同时电子产品也越来越智能。

本设计采用STC89C51单片机为主控芯片,采用数字型温度传感器DS18B20检测环境温度,通过LCD1602实时显示温度值吗,并且能通过串口发送指令调节风扇转速。系统添加了几个按键,用户可以通过按键进行设置温度的上、下限值,并将数据保存在单片机EEPROM中做到掉电存储的功能。当所采集温度超过上限值时,蜂鸣器鸣叫、LED灯亮、风扇全速转动;当所采集温度低于下限值时,蜂鸣器鸣叫、LED灯亮、风扇停止运转;当所采集温度介于上下限温度之间时,蜂鸣器、LED灯停止工作、风扇中速运转。这个设计简单、成本低、具有实用性。

关键词:智能风扇;DS18B20;温度传感器

 

设计要求:

1、检测仓库温度,当大28度时驱动电机低速转动,当大于 30 度时驱 动电机中速转动,当大于 35 度时驱动电机高速转动;

2、检测仓库温度,将温度数据上传至上位机,上位机收到温度后做出以下反应:当大于 28 度时发送命令 01 驱动电机低速转动,当大于30度时发送命令 02 驱动电机中速转动,当大于 35 度时发送命令 03 驱动电机高速转动。(可加分

 

创新部分:

  1. 添加蜂鸣器报警功能。
  2. 添加了独立按键功能,利用按键控制温控系统温度的上下限,使其温度检                  测具备灵活性。

(3)利用L9110S驱动芯片直接驱动变频散热风扇取代直流电机使现象更明显。

系统硬件方案选择

我们小组经过长时间的讨论,本章节主要介绍系统所用到的器件的选择与对比,进行综合的对比考虑选择出最适合本设计的一组方案。

2.1 硬件方案的选择

由组长牵头,在硬件电路的搭建之前必须明确设计的方案,通过各个模块之间进行比较选择出最适合本设计的硬件,以发挥器件的最大功效。

2.1.1  主控芯片的选择

采用STC89C51单片机作为主控芯片。STC89C51是宏晶科技公司生产的一款低功耗、高性能的八位CMOS微处理器,片内具有8k在线编程Flash存储器。STC89C51单片机的内核采用的是MCS-51内核,指令完全兼容MCS-51,但是该单片机越做了升级使得芯片具有很多传统的51单片机不具备的功能,例如该芯片还有4K的EEPROM存储,在需要使用到掉电存储数据的时候就可以直接使用单片机内部的存储,不在需要在外接存储芯片进行存储。STC89C51单片机具有的开发简单、可在线编程下载、成本低是非常不错的选择。

2.1.2  显示器件的选择

方案一:

采用LED数码管动态扫描显示。LED数码管的价格适中,对于显示数字或者简单的字母会比较合适。但是采用动态扫描法与单片机连接时占用CPU的I/O口较多,并且由于单片机的IO口输出电流不够,所以需要一个驱动电路,通过驱动电路放大电流后控制数码管,还有就是采用数码管进行显示的话显示的内容多了对于电路的焊接机会增大难得容易焊接错误。

方案二:

采用LCD1602液晶显示屏。LCD1602液晶又叫LCD1602字符型液晶。液晶显示功能强大,可以同时显示出16*2即32个字符,可包括数字、字母、符号、或者自定义字符。LCD1602液晶显示器中的每一个字符都是由5*7的点阵组成。LCD1602采用并行数据传输也可以采用串行数据传输,控制简单,和市面上的大多基于HD44780液晶的控制原理完全相同。

综合上述的描述,最终根据本设计中的功能要求考虑采用LCD1602液晶显示器比较合理。

2.1.3  温度传感器的选择

方案一:

使用热敏电阻作为传感器,用热敏电阻与一个相应阻值电阻相串联分压,利用热敏电阻阻值随温度变化而变化的特性,采集这两个电阻变化的分压值,并进行A/D转换。此设计方案需用A/D转换电路,增加硬件成本而且热敏电阻的感温特性曲线并不是严格线性的,会产生较大的测量误差。

方案二:

采用模拟温度传感器AD590,该传感器的输出电流会随温度的变化而变化,从而需要设计电路转换成电压的变化,进而通过A/D转换后接到单片机中,这种方法固然麻烦,而却费用比较高,而却在电流电压转换和A/D转换中会产生误差。

方案三:

采用数字式温度传感器DS18B20,此类传感器为数字式传感器而且仅需要一条数据线进行数据传输,易于与单片机连接,可以去除A/D模块,降低硬件成本,简化系统电路。另外,数字式温度传感器还具有测量精度高、测量范围广等优点。

所以最终我们采用数字型DS18B20作为温度采集芯片。

2.1.4  数据存储芯片的选择

采用STC89C51单片机内部EEPROM存储数据。STC89C5X芯片内部带有2*Xk字节的EEPROM功能,STC89C5X内部通过ISP/IAP技术读写内部FLASH来实现EEPROM。但是在需要将数据写单片机内部EEPROM时先要将该扇区擦除后在写入,否则无法正常的写入。所以该方案不宜使用在存储数据量大的场合。但是可以节省外围电路的搭建,也降低了成本。

2.2  系统总体方案

本设计采用STC89C51单片机为主控芯片,采用数字型温度传感器DS18B20检测环境温度,通过LCD1602实时显示温度值,并且能通过串口发送指令调节风扇转速。系统添加了几个按键,用户可以通过按键进行设置温度的上、下限值,并将数据保存在单片机EEPROM中做到掉电存储的功能。当所采集温度超过上限值时,蜂鸣器鸣叫、LED灯亮、风扇全速转动;当所采集温度低于下限值时,蜂鸣器鸣叫、LED灯亮、风扇停止运转;当所采集温度介于上下限温度之间时,蜂鸣器、LED灯停止工作、风扇中速运转。

本设计的具体的系统方案如下图2.1所示。

 整体电路

3.1  电路原理图

3.2  系统硬件测试

系统硬件电路的测试主要是检测电路是否出现漏焊、短路、断路、虚焊、一些具有方向的元件是否方向弄错、电路设计错误等情况。

对于漏焊、元件方向弄错的检测方法是将实物电路板对照着PCB图的线路,检查每一个元件和导线在实物上是否有出现。如果发现没有或者对不上的情况下需及时的重新对照确定漏焊时及时的补焊。

对于短路、断路、虚焊这些情况采用数字万用表。将数字万用表打到二极管档位,然后通过红表笔和黑表笔碰一起,万用表会发出鸣叫警示。根据这个原理就可以用来检测短路、断路、虚焊。在需要检测的元件或导线的两端用两根表笔检测,如果导通蜂鸣器会鸣叫,如果断开蜂鸣器不叫。这样根据我们所需要检测的情况,在结合检测的现象就可以测出线路是否有问题。

3.3 系统防尘设计

参考风扇防尘罩,在不影响低风力风扇情况下,针对风扇提高防尘性。我们小组利用洗澡球制作一个口袋式渔网状防尘罩,因为洗澡球是以人造纤维编织成的长筒型弹性网,由其两端向中央压挤聚拢形成的皱折体,皱折体圆心同轴两侧以束件束紧固定,皱折体松开周边蓬松向中间聚结形成为洗澡球。风扇转动,形成空气流,而用洗澡球制作而成的防尘罩可以有效正面吸附掉大部分空气中的尘土,其中的孔洞则用于气体流畅通过。

系统重要函数的介绍

4.1  主函数的设计

主函数void main()是程序的入口函数,一个完整的程序必须要包含该函数。在该函数的开头一般都是先对单片机和一些外围器件需要进行初始化才能正常使用的器件进行初始化和重新赋值一些变量,初始化完后进去死循环,如果不进入死循环程序运行一次就会退出,如果加入死循环程序就会不断地进行循环达到实时检测执行的目的。在主程序的设计中需要注意的是主函数中不宜放过多的代码,具体的代码一般都是采用函数进行封装然后在主函数进行调用,这样也可以方便阅读修改。具体流程图如下4.1所示。

系统软件测试

测试所需的工具:KEIL软件、系统硬件、PL2303下载器等。

系统的软件方面通过KEIL软件进行编写,将编写好的程序生成.HEX文件后通过PL2303下载器下载到单片机中。通过观察整个系统运行的状态,然后进行反复的修改调试程序,最终得到一个完善的程序。

在系统软件调试上主要遇到以下几个问题:

(1)在向LCD1602液晶发送清屏指令的时候,LCD1602并未成功的清楚屏幕。

解决方法:通过查阅LCD1602的使用手册,得到清屏的指令的确是0x01和程序上写的完全相同,而却显示屏可以显示出内容这表明程序发送指令是没有错误的,但是显示并未清屏。于是怀疑是否发送了清屏指令后里面进去下一个内容的显示,而LCD1602的处理速度不够,所以并未正真的执行清屏指令。通过添加40ms的延时后,重新下载进程序后发现清屏指令被执行了。通过仔细的阅读手册发现,LCD1602清屏的确需要1.64ms的执行时间,最终程序采用了4ms的延时。

(2)无法向单片机内部的EEPROM正确存储数据,当时数据会变。

解决方法:通过使用现有的显示器件进行观察发现第一次的时候数据为0x00然后存储0xf0进去后断电在上电读取出来的数据的确为0xf0,然后在进行存储0x0f进去后断电在上电读取出来的数据竟然变成了0xff,之后存储什么数据读取出来的都是0xff。最后通过查阅STC89C5X单片机的芯片手册发现51单片机的EEPROM在写入数据之前需要先进行擦除扇区,因为在在原本地址如果是0的可写入0和1,如果为1时只能写入1而0是写入不了的,最终发现这个问题后及时的修改程序在每次存储数据之前先进行擦除一下所要使用的扇区,最终解决了该问题。

附录源码
5.1 main.c文件
#include<reg52.h>		    //头文件定义
#include<DS18B20.h>
#include<EEPROM.h>
#include<LCD1602.h>
#include<INTERRUPT.h>

#define uchar unsigned char	//宏定义
#define uint unsigned int

/*****************灯、蜂鸣器、按键引脚定义*******************/
sbit led = P2^0;	  //LED灯引脚定义
sbit buzz = P1^5; //蜂鸣器
sbit key_set = P3^1;	  //设置键
sbit key_jia = P3^0;	  //加值键
sbit key_jian= P3^2;	  //减值键

/*********************全局变量定义***************************/
uchar Temp_up,Temp_down;//存储温度上限值、下限值
uint  set_f;            //设置选择标记,=0非设置,=1设置上限,=2设置下限
uchar num;				//计数变量

/********************************************************
函数名称:void delayms(uint ms)
函数作用:毫秒延时函数
参数说明:ms为延时的毫秒数
********************************************************/
void delayms(uint ms)
{
	unsigned char i=100,j;
	for(;ms;ms--)
	{
		while(--i)
		{
			j=10;
			while(--j);
		}
	}
}
/********************************************************
函数名称:void display()
函数作用:正常显示温度
参数说明:
********************************************************/
void display()
{
	lcd1602_write_character(0,2,"H:");			  //显示"H"【0:表示第1列,2:表示第2行,所有关于显示都一样】
	lcd1602_write_character(9,2,"L:");
	LCD_disp_char(2,2,ASCII[Temp_up%1000/100]);   //显示【温度上限值】
	LCD_disp_char(3,2,ASCII[Temp_up%100/10]);
	LCD_disp_char(4,2,ASCII[Temp_up%10]);
	LCD_disp_char(5,2,0);					      //显示自定义字符【°】
	LCD_disp_char(6,2,'C');				          //显示【C】	
	
	LCD_disp_char(11,2,ASCII[Temp_down%1000/100]);//显示【温度下限值】
	LCD_disp_char(12,2,ASCII[Temp_down%100/10]);
	LCD_disp_char(13,2,ASCII[Temp_down%10]);
	LCD_disp_char(14,2,0);					      //显示自定义字符【°】
	LCD_disp_char(15,2,'C');				      //显示【C】

	if(fuhao==0)							      //显示温度符号
		LCD_disp_char(3,1,'+');					  //零上
	else
		LCD_disp_char(3,1,'-');					  //零下
	lcd1602_write_character(4,1,temp_t);	      //显示【实际温度值】
	LCD_disp_char(10,1,0);					      //显示自定义字符【°】
	LCD_disp_char(11,1,'C');				      //显示【C】
}
/********************************************************
函数名称:void display2()
函数作用:显示设置温度限值
参数说明:
********************************************************/
void display2()
{
	num++;

	lcd1602_write_character(0,1,"Set limit value");
	lcd1602_write_character(0,2,"H:");
	lcd1602_write_character(9,2,"L:");
	LCD_disp_char(5,2,0);					       //显示自定义字符【°】
	LCD_disp_char(6,2,'C');				           //显示【C】
	LCD_disp_char(14,2,0);					       //显示自定义字符【°】
	LCD_disp_char(15,2,'C');				       //显示【C】
	if(num%2==0)	//偶数次显示,奇数次不显示。这样就会有闪烁效果,可以清楚看到当前设置的是哪个值
	{		
		LCD_disp_char(2,2,ASCII[Temp_up%1000/100]);//显示【温度上限值】
		LCD_disp_char(3,2,ASCII[Temp_up%100/10]);
		LCD_disp_char(4,2,ASCII[Temp_up%10]);

		LCD_disp_char(11,2,ASCII[Temp_down%1000/100]);//显示【温度下限值】
		LCD_disp_char(12,2,ASCII[Temp_down%100/10]);
		LCD_disp_char(13,2,ASCII[Temp_down%10]);
	}
	else			//奇数次不显示
	{	
		if(set_f==1)//设置上限值
			lcd1602_write_character(2,2,"   ");	//显示空格
		if(set_f==2)//设置下限值
			lcd1602_write_character(11,2,"   ");
	}
}
/********************************************************
函数名称:void scan(void)
函数作用:按键检测处理
参数说明:
********************************************************/
void scan(void)
{	
	//设置键,不支持连按
	if(key_set==0)		 //按键按下
	{
		delayms(7);		 //延时消抖
		if(key_set==0)	 //再次确认按下按键
		{
			led=1;	     //关闭报警灯
			buzz=1;	     //关闭蜂鸣器
			feng=1;	     //关闭风扇
			TR0=0;	     //关闭定时器

		    if(set_f==0) //进入设置时,先清除屏幕	
			{
				LCD_write_command(0x01);//清除屏幕显示
				delay_n40us(100);		//延时等待全部清除完毕	
			}
			set_f++;	 //设置变量+1
			if(set_f==3) //如果设置完成,退出设置
			{
				set_f=0; //重置设置变量

				EEPROM_delete(0x2002);		   //擦除扇区
				EEPROM_write(0x2002,Temp_up);  //写入【温度上限值】数据保存

				EEPROM_delete(0x2202);		   //擦除扇区
				EEPROM_write(0x2202,Temp_down);//写入【温度下限值】数据保存
				
				LCD_write_command(0x01);       //清除屏幕显示
				delay_n40us(100);		       //延时等待全部清除完毕
			}
		}
		while(!key_set);                       //等待按键松开
	}
	//加值键,支持连按
	if(key_jia==0&&set_f!=0)   //按键按下,并却在设置模式下				   
	{
		delayms(7);			   //延时消抖
		if(key_jia==0)		   //再次确认按键按下
		{
			if(set_f==1)       //设置【温度上限值】
			{
				if(Temp_up<125)//最大值可设置125℃
					Temp_up++; //温度上限值+1℃			
			}
			if(set_f==2)       //设置【温度下限值】
			{
				if(Temp_down<125&&Temp_down+1<Temp_up)//最大值可设置125℃,并且下限不可超过上限
					Temp_down++;//温度下限值+1℃		 
			}
		}
	}
	//减值键,支持连按
	if(key_jian==0&&set_f!=0)  //按键按下,并却在设置模式下
	{
		delayms(7);			   //延时消抖
		if(key_jian==0)		   //再次确认按键按下
		{
			if(set_f==1)       //设置【温度上限值】
			{
				if(Temp_up!=0&&Temp_up>Temp_down+1)//最小值可设置0℃,并且上限得比下限大
					Temp_up--; //温度上限值-1℃
			}
			if(set_f==2)       //设置【温度下限值】
			{
				if(Temp_down!=0)//最小值可设置0℃
					Temp_down--;//温度下限值-1℃
			}
		}
	}
}
/********************************************************
函数名称:void main()
函数作用:主函数
参数说明:
********************************************************/
void main()
{	
	uint i;   //循环计数

	Temp_up=EEPROM_read(0x2002);	//读取存储的【温度上限值】数据
	Temp_down=EEPROM_read(0x2202);  //读取存储的【温度下限值】数据
	UsartConfiguration();
	DS18B20_init();			 //DS18B20初始化
	LCD_init();				 //LCD1602初始化
	T0_init();				 //定时器初始化
	lcd1602_write_pic(0,pic);//将自定义字符【°】写入LCD1602液晶
	lcd1602_write_character(0,1,"    init...   ");
	for(i=0;i<150;i++)		 //上电先等待DS18B20温度传感器进入正常工作。
		DS18B20_Read_Temperature();//读取温度
	LCD_write_command(0x01);//清除屏幕显示
	delay_n40us(100);		//延时等待全部清除完毕
 	while(1)				 //死循环
	{
		scan();				 //进行按键检测
		if(set_f==0)         //非设置模式,正常显示温度
		{
			i++;			 //循环次数+1
			if(i>=15000)     //每循环15000次,采集一次温度
			{
				i=0;		 //重置循环变量
				EA=0;
				DS18B20_Read_Temperature();//读取温度数据
				EA=1;
				DS18B20_Temperature();	   //将温度数据转换实际温度			
				if(presence==0)			   //判断温度读取正常
				{
					if(Temperature>=Temp_up||Temperature<Temp_down)//判断实际温度是否大于等于上限或小于下限值
					{
						led=0;	     //打开报警灯
						buzz=0;	     //蜂鸣器报警
						TR0=0;
						if(Temperature>=Temp_up)//如果,超过上限值
							 feng=0; //打开风扇
						else				    //否则,低于下限值
							 feng=1; //关闭风扇
					}
					else			 //实测温度处于限值之间
					{	
						led=1; //关闭报警灯
						buzz=1;//关闭蜂鸣器
						PWM=50;//控制PWM=50%
						TR0=1; //开启定时器,PWM控制风扇转速
					} 
					display(); //显示实际温度
				}
				else		   //否则,温度采集失败
				{
					TR0=0;	   //关闭定时器
					feng=1;    //关闭风扇
					lcd1602_write_character(3,1,"   NOT   ");
				}
			}
		}
		else                   //设置模式显示
			display2();	       //显示设置限值
	}
}
/*******************************************************************************
* 函 数 名         :UsartConfiguration()
* 函数功能		   :设置串口
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void UsartConfiguration()
{
	SCON=0X50;			//设置为工作方式1
	TMOD=0X20;			//设置计数器工作方式2
	PCON=0X80;			//波特率加倍
	TH1=0XF3;				//计数器初始值设置,注意波特率是4800的
	TL1=0XF3;
//	ES=1;						//打开接收中断
//	EA=1;						//打开总中断
	TR1=1;					//打开计数器
}

 结论

经过制作设计的这段时间的努力终于将本设计方案要求基本实现。由于时间、水平和经验有限,设计的作品还存在着一些的不足之处。

要想实现一个系统,那必须对整个系统的设计有整体的思路。设计电路是系统功能实现的前提,合理的选用芯片十分关键,合理设置元器件参数更是一个难点。所以需要有扎实的知识基础,既懂软件又懂硬件,会写程序能搭电路,对常用元器件比较了解。焊接电路路需要扎实的基础功及较强的耐心,调试电路是必须认真细心。如有问题,耐心排查,任何小的问题都会影响系统的最终功能,所以必须注意细节,同时完成设计需要投入大量时间和精力,需要极强的毅力。整个设计过程中团队的合作最为重要、各队员既要完成好各自负责的模块也要小组内成员互相协作。在这次的实训中遇到了很多困难,也很努力的去解答。终于明白了“世上无难事,只怕有心人”的意义所在。在遇到问题时首先不能畏惧或躲避,要通过不断的学习及资料的收集来解决问题。成功没有捷径,上帝只垂青那些为目标执着追求的人。

对于这次设计来说既是一次机遇,又是一次挑战。在这次的设计过程中,本次实训学到了很多东西,通过自己的实践,增强了动手能力。通过实际工程的设计也使我了解到书本知识和实际应用的差别。在实际应用中遇到很多的问题,这都需要我们对问题进行具体的分析,并一步一步地去解决它。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值