51单片机、DS18B20、智能窗帘控制系统

2023-05-16

  • 写在最前面:文章是我的设计报告搬运过来的,嫌排版乱的,可以直接下载设计报告,包含word,keil工程,proteus工程
  • !!!!!!全部文件下载地址
  • 项目意义

21世纪是科技飞速发展的时代,随着国民经济的发展和科学技术水平的提高,特别是计算机技术,通信技术,网络技术,控制技术的迅猛发展,生活现代化得以实现,居住环境向舒适化,安全化发展,智能家居也随之应运而生。由于我国的科技刚刚发展起来,各种科技产品还明显的落后于发达国家,人民的生活也刚刚开始富裕起来,许多智能系统也刚刚在我国兴起。但是,发展前景却广阔。这种系统可以为我们营造出高效、舒适、便捷的居住环境。并且它可以牵动一大批产业。

如此广泛的应用,他的前景也必将非常广阔。随着科学技术的飞速发展,人们的生活观念也在渐渐的发生转变。各种家电也在发生着变化。由于单片机技术和计算机技术的的不断成熟,家电越来越智能化。窗帘也不例外,在欧美等发达国家,智能窗帘系统已广泛应用。智能窗帘在国内算是高端前沿产业,市场广阔,有推广和应用的意义,在发达的欧美市场智能窗帘已经并不新鲜,已经广泛运用于平常百姓家中,所以有必要在国内推广。 随着现代社会的高速发展,人们对室内设计智能化的要求也越来越高,相对于传统的窗帘,智能窗帘更能满足人们对于生活品质的追求。在一年四季中,随着不同的季节、气候,人们对于窗帘打开与闭合的需求是不同的;在每一天中,随着天气的变化及时间段的不同,人们对于窗帘打开与闭合的需求也是不一致的。尤其在智能家居领域克服传统的窗帘的许多缺点,为人们提供了更方便、快捷、舒适安全的生活环境,提供了人类的生活质量。

智能窗帘控制系统的控制方式大体上有三种:光控,时控,遥控。遥控属于半自动类;而光控属于全自动式,因光敏器件的灵敏度较高,十分适合窗帘控制系统的数据采集端。因此,设计一款价格低廉,结构简单,灵敏度高,抗干扰能力强,实现光控、手动控制功能为一体的智能窗帘,具有十分重要的意义。

 

二、总体设计方案


本设计包括硬件和软件设计两个部分。模块划分为数据采集、按键控制、液晶显示。电路结构可划分为:温度传感器、光照传感器(用可调电阻代替光敏电阻)、单片机控制电路。本系统采用AT89C51单片机作为核心控制单元,主控芯片将测得的数值与设定值进行比较,并显示在LCD1602液晶显示屏上,当测得的光照度小于或大于设定距离时,控制窗帘开闭。系统总体的设计方框图如图1所示。

  • 光照传感器由光敏电阻和ADC0804模数转换芯片组成。光敏电阻又称光导管,具有在特定波长的光照射下,其阻值迅速减小的特性。这是由于光照产生的载流子都参与导电,在外加电场的作用下作漂移运动,电子奔向电源的正极,空穴奔向电源的负极,从而使光敏电阻器的阻值迅速下降。光敏电阻属半导体光敏器件,除具灵敏度高,反应速度快,光谱特性及r 值一致性好等特点外,在高温,多湿的恶劣环境下,还能保持高度的稳定性和可靠性,可广泛应用于照相机,太阳能庭院灯,草坪灯,验钞机,石英钟,音乐杯,礼品盒,迷你小夜灯,光声控开关,路灯自动开关以及各种光控玩具,光控灯饰,灯具等光自动开关控制领域。

    由于本设计是基于仿真软件来实现的,所以利用电位器分压来模拟光敏电阻的功能。其电阻值大小变化与光照强度成负相关。

    A/D 转换送入单片机的 P1 接口,单片机处理后输出命令控制电机正转或者反转,以实现通过光照控制窗帘的开关功能。

    应用光控原理工作,天亮窗帘自动打开,天黑窗帘自动关闭。由于光敏电阻信号检测后得到的是模拟信号,所以光控电路采集到的模拟信号需要经过A/D 转换后输出数字信号给单片机。A/D 转换的作用是进行模数转换,把接收到的模拟信号转换成数字信号输出。在选择 A/D 转换时,先要确定 A/D 转换精度、转换速度以及转换位数等,A/D 转换的位数确定与整个测量控制系统所需测量控制的范围和精度有关,由于单片机IO口的限制,本设计采用了单通道8 位 A/D 转换器 ADC0804。VCC接电源,A GND、D GEN、VIN-接地;CLK IN接入500khz的时钟信号,RD是数据读写端,低电平读取数据;WR是AD转换开启信号,接收到下降沿即开启AD转换,转换结束后再INTR端输出一个低电平,由于本设计需要连续读取模拟信号,所以INTR引脚可以悬空。VIN+是正极性模拟量输入;DB0-DB7是数据输出端,接入单片机的P1口。硬件电路如图所示。

  • LCD1602液晶显示电路
  • LCD1602简介:LCD1602液晶显示器是广泛使用的一种字符型液晶显示模块。它是由字符型液晶显示屏、控制驱动主电路HD44780及其扩展驱动电路HD44100,以及少量电阻、电容元件和结构件等装配在PCB板上而组成。

    显示原理:点阵图形式液晶由M×N个显示单元组成,假设LCD显示屏有64行,每行有128列,每8列对应1字节的8位,即每行由16字节,共16×8=128个点组成。显示屏上64×16个显示单元与显示RAM区的1024字节相对应,每一字节的内容与显示屏上相应位置的亮暗对应。例如显示屏第一行的亮暗由RAM区的000H~00FH的16字节的内容决定,当(000H)=FFH时,屏幕左上角显示一条短亮线,长度为8个点;当(3FFH)=FFH时,屏幕右下角显示一条短亮线;当(000H)=FFH,(001H)=00H,(002H)=00H…,(00EH)=00H,(00FH)=00H时,在屏幕的顶部显示一条由8条亮线和8条暗线组成的虚线。这就是LCD显示的基本原理。

    字符型液晶显示模块是一种专门用于显示字母、数字和符号等的点阵式LCD,常用16×1,16×2,20×2和40×2等的模块。一般的LCD1602字符型液晶显示器的内部控制器大部分为HD44780,能够显示英文字母、阿拉伯数字、日文片假名和一般性符号。 

    为了让要显示的数据直观的显示出来,本设计选用成本较低,控制方便的LCD1602液晶显示模块,硬件电路如图5所示。D0-D7为数据线;RS为数据命令选择端,高电平时选择数据寄存器、低电平时选择指令寄存器;RW为读写选择端,高电平时进行读操作,低电平时进行写操作。E为使能信号端。VDD接电源正极,VSS接地。

     

    图5 LCD1602液晶显示电路

  • 本设计选用的温度传感器是DS18B20。DS18B20是常用的数字温度传感器,其输出的是数字信号,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。DS18B20数字温度传感器接线方便,封装成后可应用于多种场合。

    单总线是Dallas 的一项专有技术。与目前多数标准串行数据通信方式,如SPI/I2C/MICROWIRE 不同,它采用单根信号线,既传输时钟,又传输数据,而且数据传输是双向的。它具有节省 I/O 口线资源、结构简单、成本低廉、便于总线扩展和维护等诸多优点。1-wire 单总线适用于单个主机系统,能够控制一个或多个从机设备。当只有一个从机位于总线上时,系统可按照单节点系统操作;而当多个从机位于总线上时,则系统按照多节点系统操作。单总线要求外接一个约5k 的上拉电阻。这样,单总线的闲置状态为高电平。不管什么原因,如果传输过程需要暂时挂起,且要求传输过程还能够继续的话,则总线必须处于空闲状态。位传输之间的恢复时间没有限制,只要总线在恢复期间处于空闲状态(高电平)。如果总线保持低电平超过 480us,总线上的所有器件将复位。另外在寄生方式供电时,为了保证单总线器件在某些工作状态下(如温度转换期间 EEPROM写入等)具有足够的电源电流,必须在总线上提供强上拉,如图6所示。

    典型的单总线命令序列如下 :

    第一步:初始化

    第二步:ROM命令(跟随需要交换的数据 )

    第三步:功能命令(跟随需要交换的数据)

    每次访问单总线器件,必须严格遵守这个命令序列,如果出现序列混乱,则单总线器件不会响应主机。但是,这个准则对于搜索 ROM命令和报警搜索命令例外,在执行两者中任何一条命令之后,主机不能执行其后的功能命令,必须返回至第一步。

    具体的时序操作会在软件设计部分展开。

     

    图6 温度传感器电路

  • 5.步进电机驱动电路

    窗帘的开闭动力来源于步进电机。步进电机驱动能力范围内,其输出的角位移或线位移与输入的脉冲个数成正比,不因电源电压、负载变化和环境条件等的变化而变化。所以其输出的角速度或线速度也与输入的脉冲频率成正比,通过改变输入脉冲频率的高低就可以调节步进电机的转速,并能控制步进电机的快速启动,暂停,正反转和加减速等。由于步进电机具有步距误差不积累、运行可靠、结构简单、惯性小、成本低等优点,因此,被广泛使用于计算机外围电路、自动化控制装置以及其他的数字控制装置中,如打印机、钟表、数模转换设备等装置中。

    驱动芯片:使用驱动芯片 ULN2003A。ULN2003A芯片可以直接处理数字信号,例如经过数字逻辑电子电路产生的脉冲信号。该芯片的内部结构由7个NPN达林顿管组成的,并且每一对达林顿管都分别与一个基极电阻串联。通常被广泛应用于单片机、 PLC、仪表电器等控制驱动电路中。特点是电流增益高、 工作电压高、驱动能力强、稳定性能好、体积小、价格低廉等等。

    步进电机:本设计选用的步进电机属于四相八拍电机,输入电压范围为直流5V-12V。当步进电机输入一系列连续的脉冲信号时,步进电机按照相应的运行状态,转动相应的角度。例如,当输入步进电机的通电状态改变一次时,相应的转子也就转过对应的一个步距角,与之相对。步进电机驱动电路如图7所示。

    图7 步进电机驱动电路

  • 系统软件设计
  1. LCD1602驱动程序

LCD1602的驱动程序包括:

  1. LCD1602初始化函数:void InitLcd1602();

 

  1. LCD1602忙检测函数:void Read_Busy();

在每次相LCD1602写入数据前,都要读取其工作状态,空闲时方可写入。

 

  1. LCD1602写命令函数:void Lcd1602_Write_Cmd(uchar cmd);

1602 液晶模块内部的控制器共有 11 条控制指令,1602 液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。

 

  1. LCD1602写数据函数:void Lcd1602_Write_Data(uchar dat);

在配置命令函数运行完之后,就可以给1602液晶配置显示数据

 

  1. 显示字符函数:void DisplayOneChar(uchar X, uchar Y, uchar DData);

为了让1602液晶显示字符,编写显示函数,在内部调用写命令函数和写数据函数。

 

  1. DS18B20驱动程序

本设计的重点是DS18B20的驱动程序。由于其采用单总线协议,对于时序的要求及其严格,必须严格遵守其操作时序。

  1. 初始化

unsigned char DS18B20_Init() //初始化

{

uchar i;

DQ = 0;                //将总线拉低

i = 90;    

while(i--);//延时700us

       DQ = 1;                //然后拉高总线,如果DS18B20做出反应会将在15us~60us

后总线拉低

i = 0;

while(DQ)     //等待DS18B20拉低总线

{

        Delay1ms(1);

        i++;

        if(i>7)//等待>5MS

        {

               return 0;//初始化失败

        }

}

return 1;//初始化成功

}

  1. 写命令

void DS18B20_Write(uchar dat) //写命令

{

uint i, j;

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

{

        DQ = 0;              //每写入一位数据之前先把总线拉低1us

        i++;

        DQ = dat & 0x01;  //然后写入一个数据,从最低位开始

        i=8;

        while(i--); //延时68us,持续时间最少60us

        DQ = 1;  //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值

        dat >>= 1;

}

}

 

  1. 开始温度转换

DS18B20_Write(0xcc); //跳过ROM操作命令        

       DS18B20_Write(0x44); //温度转换命令

 

  1. 读取ROM

DQ = 0;//先将总线拉低1us

i++;

DQ = 1;//然后释放总线

i++;

i++;//延时6us等待数据稳定

b = DQ;  //读取数据,从最低位开始读取

byte = (byte >> 1) | (b << 7);

i = 4;             //读取完之后等待48us再接着读取下一个数

return byte;

 

       TEMPL = DS18B20_Read();       //读取温度值共16位,先读低字节

       TEMPH = DS18B20_Read();       //再读高字节

       TEMP = TEMPH;

       TEMP <<= 8;

       TEMP |= TEMPL;

       return TEMP;

 

  1. ADC0804 驱动

ADC 0804接收电位器的模拟量输入,转换成8位的数字量送入单片机处理。由于采用连续ADC方式,而一次AD转换时间远小于一次机器周期,所以INTR引脚可以悬空,以节省IO资源。此算法适用于大多数单总线协议器件,以下是部分重要算法:

void ADC_Init()

{

  ADCWR=0;

       delay(1);

  ADCWR=1;   //上升沿,内部寄存器清零,锁存地址

}

void ADC()  //模拟光敏电阻功能

{

       ADCRD=0;      //输出转换得到的数据

       LUX=P1;      

       ADCRD=1;    //读结果

       LUX=LUX*39/1000;  //5V电压分为0~255级 放大到10V

       LV=9-LUX;

}

 

 

 

 

五、系统调试

单片机程序编写采用keil5集成开发环境,仿真软件选用proteus8.6。仿真结果如下图8所示。

单片机检测SW引脚电平,当switch闭合后,就关闭相应中断,这时是自动模式,这时OPEN和CLOSE 再按下就无效了。

在软件编程和仿真调试中,发现两个问题:一是由于DS18B20采用单总线协议,所以其时序操作必须严格遵守技术手册,不然就会出现温度无法读取、数据错误等一系列问题。在数据读取的过程中,其先读取的是低字节在读取高位字节,由于编程书写错误,导致温度数值迟迟不能正常获取,排查多次后,终于发现。二是本仿真中LCD1602通过lable标签的方式和IO口相连,标签格式是D0-D7;但是在ADC0804的数据总线中,也采用了LBL标签,并且格式也是D0-D7,一时的疏忽让我付出了惨重的代价,仿真时,LCD显示不正常,IO口提示黄色短路状态,由于没用遇到过这种情况,当时也不清楚实际的错误在哪,我排查了一晚上,在快要崩溃的时候,发现LBL标签冲突了!遂更改标签格式,仿真正常。

 

 
 

 

 

 

 

图8 仿真效果图

最后是主函数的代码:

#include<reg51.h>
#include"LCD1602.h"
#include"DS18B20.h"
sbit SW = P3^6;      //模式切换
sbit ADCRD = P3^0; 	 //低电平输出
sbit ADCWR = P3^1; 	 //低电平开启adc
bit  gate=1;       	 //自动开关使能位 1有效
uchar minlux = 5;  	 //光照阈值缓存器
uint LUX;        		 //光照度缓存器
uchar LV;        		 //光照等级
uchar sign;     		 //符号位
uchar TEMPtitle[4] = "TEMP";     //显示温度title
uchar ADCtitle[8] = "Min:Now:" ;  //显示光照title
uchar code ASCII[10] = {'0','1','2','3','4','5','6','7','8','9'};//显示字库
uchar cw[8] =  {0x08,0x0c,0x04,0x06,0x02,0x03,0x01,0x09};	//正转
uchar acw[8] = {0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09};  //反转

void delay(uint x) //延时 1 ms
{
	uint i,j;
	for(i=x;i>0;i--)
		for(j=120;j>0;j--);
}
void ADC_Init() 
{
  ADCWR=0;
	delay(1);
  ADCWR=1;   //上升沿,内部寄存器清零,锁存地址
}
void ADC()  //模拟光敏电阻功能
{
	ADCRD=0;      //输出转换得到的数据
	LUX=P1;		    //读结果
	ADCRD=1;    
	LUX=LUX*39/1000;  //5V电压分为0~255级 放大到10V,等级L0-L9
	LV=9-LUX;
	DisplayOneChar(5, 1, 'L');
	DisplayOneChar(6, 1,ASCII[minlux] );   //光照阈值
	DisplayOneChar(13, 1, 'L');
	DisplayOneChar(14, 1, ASCII[LV]);      //显示光照等级
	delay(1);
}
void Motor_cw()  //正转
{
	uchar i;
	uchar j=2;
	while(j--)
	{
		for(i=0;i<8;i++)
		{	
			P2=cw[i];
			delay(100);
		}
	}
}
void Motor_acw()  //反转
{
	uchar i;
	uchar j=2;
	while(j--)
	{
		for(i=0;i<8;i++)
		{	
			P2=acw[i];
			delay(100);
		}
	}
}
void AutoControl()  //每到一次阈值启动电机转两圈就停止
{
	if(gate==1)  
	{
		if(LV==minlux)
		{
			Motor_cw();
			gate=0;
		}
	}
	else if(gate==0)
	{
		if(LV==(minlux-1))
		{
			Motor_acw();
			gate=1;
		}
	}
	else gate=1;
}
void int0() interrupt 0 //手动开启窗帘
{
	Motor_acw();
}
void int1() interrupt 2  //手动关闭窗帘
{
	Motor_cw();
}
void INC() interrupt 1
{
	if(minlux<9)
		minlux++;
}
void DEC() interrupt 3
{
	if(minlux>0)
		minlux--;
}
void SYS_Init()
{
	uchar i;
	TMOD=0X66;
	TH0=0XFF;
	TL0=0XFF;
	TH1=0XFF;
	TL1=0XFF;
	EA=1;  //开总中断
	ET0=1; //定时器中断0,1,扩展成为外部中断
	ET1=1;
	TR0=1;
	TR1=1;
	InitLcd1602();
	for(i=0;i<4;i++)
	{
		DisplayOneChar(i+2, 0, TEMPtitle[i]);  //显示“temp:”
		DisplayOneChar(i, 1, ADCtitle[i]);     //显示“Min”
		DisplayOneChar(i+8, 1, ADCtitle[i+4]); //显示"Now"
	}
}
void Datapros(int temp)	 //数据处理函数
{ 
	if(temp<0)				//当温度值为负数
  {
		sign = '-'; 	  
		temp=~temp;    //补码减1再取反求出原码
		temp=temp+1;
  }
 	else
  {			
		sign = ' ';   //温度为正,不显示正符号
	}
	temp*=6.25;
	DisplayOneChar(6, 0,':');
	DisplayOneChar(7, 0,sign);
	DisplayOneChar(8, 0,ASCII[(temp / 1000%10)]);
	DisplayOneChar(9, 0,ASCII[(temp/ 100 %10)]);
  DisplayOneChar(10, 0,'.');
	DisplayOneChar(11, 0,ASCII[(temp/ 10 % 10)]);
	DisplayOneChar(12, 0,0xDF);   //。
	DisplayOneChar(13, 0,'C');    //C
}
void AUTOEN()
{
	if(!SW)
	{
		EX0=0;
		EX1=0;
	  AutoControl();
	}
	else 
	{
		EX0=1; //开外部中断0
		IT0=1; //配置外部中断0 下降沿有效
		EX1=1;
		IT1=1;
	}
}	
void main()
{
	SYS_Init();
  while(1)
	{
	  Datapros(GetTemp());	 //数据处理函数
		ADC_Init();  //ADC初始化函数
		delay(1);
		ADC();       // start ADC
		AUTOEN();
		delay(1);
	}
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

51单片机、DS18B20、智能窗帘控制系统 的相关文章

随机推荐