• 简易智能家居系统



    摘要

    关键字:智能家居、51单片机、温度传感器、LED模块、串口显示、AT指令

    智能家居是以住宅为平台,利用综合布线技术、网络通信技术、安全防范技术、自动控制技术、音视频技术将家居生活有关的设施集成,构建高效的住宅设施与家庭日程事务的管理系统,提升家居安全性、便利性、舒适性、艺术性,并实现环保节能的居住环境。作为家庭信息化的实现方式,智能家居已成为社会信息化发展的重要组成部分,物联网因其巨大的应用前景,将是智能家居产业发展过程中一个比较现实的突破口,对智能家居产业的发展具有重大意义。

    家居智能化技术最早在美国开始发展,在智能家居系统中每个设备都能够实现资源共享,它布线简、功能多样灵活,能够帮助主人有效的利用时间、减少浪费,因此深受人们的喜爱。智能家居可以被人们理解成一个过程,或者说是一种系统。通过计算机科技、网络连接技术、简易布线装置,把和家庭有关的一切生活类系统组合在一起,让家庭变得安全、舒适,令人放心。在智能家居网中,智能家居不单拥有传统的家具功能,为人类提供舒适的居住环境还能够使房屋有“思想”,变得智能化。

    在本次课程设计中,我们小组完成了通过温度传感器测量温度并显示温度、通过温度判断是否发生火灾并及时通过蜂鸣器报警、实现按键控制LED灯的亮灭、通过WIFI模块及串口传输等实现手机对LED模块的控制等一系列实验内容,实时模拟智能家居中对温度监控和火警报警,以及客户端控制智能家居等一系列情况,完成设计并实现简易的智能家居系统功能。
    智能家居系统


    一、系统设计要求及总体设计方案

    1.1 设计要求

    1. 51单片机(终端结点)能实现温度的测量,并能将温度在LCD显示器上显示
    2. 51单片机(终端结点)能检测有无火灾发生,并将火警送LCD显示器上显示
    3. 51单片机(终端结点)能实现对D1、D2、D3三盏LED灯的开关的控制,并将灯的工作状态送LCD显示器显示
    4. 51单片机通过串口WIFI模块连接,把WIFI模块设置成透传工作模式,WIFI模块通过路由器连接上所在的网络
    5. 通过网络调试助手将计算机设置成TCP SERVER,并通过网络调试助手实现温度的采集与显示、火警状态显示、LED灯工作状态的显示,并能通过网络调试助手控制LED灯的工作
    6. 用有人手机网络调试助手将手机设置成TCP SERVER,实现用手机显示温度、火警状态、LED灯的工作状态,并能通过手机网络调试助手控制LED灯的工作。

    1.2 总体设计方案

    设计并制作一套简易智能家居系统。系统结构如下图所示。
    框图

    二、终端结点的设计及实现

    2.1单片机最小系统

    1.晶振,至于大小由你单片机时钟周期要求而决定(用于计时,与两个电容并联使用,电容大小由你的晶振决定,一般用22pF)。
    2.复位电路(用于复位)。
    3.电源(用于供电,一般用电脑的USB口供电)。
    4.烧制程序的口(可用串口配合MAX232配合使用,也可以做个并口输入,这个要根据你使用单片机的种类决定,比如ATC可用并口,STC一般只用串口输入等等)。

    2.2 LED灯的控制与工作状态的显示

    要求:用独立按键开关三盏LED灯,并将LED灯的工作状态在LCD1602上显示。

    实验思路:要实现独立按按键控制LED灯的工作,首先要分别用单片机开发板上的K1、K2、K3这三个按键模拟开关,用开发板上的D5、D6、D7三个LED模拟三盏灯,通过程序代码的编写与运行实现软件部分的功能,通过烧录文件,将程序下载到51单片机开发板上。

    2.2.1 硬件设计

    led
    key

    2.2.2 软件设计

    首先将LED灯的按键与51单片机上的引脚相匹配,如:k1控制d1,k2控制d2;
    通过按键控制引脚的高低电平输入来控制led灯亮灭。由于51单片机引脚是非门,所以当按键按下后是低电平,因此在程序设计中赋值要反转。同时在显示屏上显示时用到LcdShowStr(0,1,"1:on “);这个函数,引号前的2个数字表示屏幕的位置,后面引号内的内容表示显示的内容。而以上描述实现了按键控制led灯亮灭以及显示的功能。之后使用以下函数uchar tempdata[6]={0,0,0,‘.’,0,0} ;
    uchar recedata[8]=” ";实现字符串语句输入控制led灯亮灭功能的实现,同时利用单片机的wifi模块实现与手机连接,进而实现手机发送命令语句控制led灯亮灭的实现,同按键控制一样根据判断引脚的高低电平来显示相应的工作状态。

    2.3 温度的测量与显示

    1.LCD1602显示器可调用的函数及功能:

    void Lcd1602_Delay1ms(uint c);   //误差 0us
    void Read_Busy();   //忙检测函数,判断bit7是0,允许执行;1禁止
    void Lcd1602_Write_Cmd(unsigned char cmd);   //写命令
    void Lcd1602_Write_Data(unsigned char dat);   //写数据
    void LcdSetCursor(unsigned char x,unsigned char y);  //坐标显示
    void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str);   //显示字符串
    void InitLcd1602();   //1602初始化
    
    1. 温度传感器DS18B20
      (1)DS18B20是单线数字温度传感器,即“一线器件”,其采用单总线的接口方式 与微处理器连接时 仅需要一条口线即可实现微处理器与 DS18B20 的双向通讯。 单总线具有经济性好,抗干扰能力强,适合于恶劣环境的现场温度测量,使用方便等优点,使用户可轻松地组建传感器网络。 测量温度范围宽,测量精度高 DS18B20 的测量范围为 -55 ℃ ~+ 125 ℃ ; 在 -10~+ 85°C 范围内,精度为 ± 0.5°C 。
      (2)DS18B20进行一次温度的转换,需要主机先作个复位操作,主机再写跳过ROM的操作(CCH)命令,然后主机接着写个转换温度的操作命令,后面释放总线至少一秒,让DS18B20完成转换的操作。
      ds18b20
      (3)读取DS18B20的温度,即读取RAM内的温度数据,需要主机发出复位操作并接收DS18B20的应答(存在)脉冲,然后主机发出跳过对ROM操作的命令(CCH),最后主机发出读取RAM的命令(BEH),随后主机依次读取DS18B20发出的从第0一第8,共九个字节的数据。(如果只想读取温度数据,那在读完第0和第1个数据后就不再理会后面DS18B20发出的数据即可)
      2
      (4)DS18B20的驱动程序:
    void Delay_OneWire(unsigned int t);    //单总线延时函数
    void Write_DS18B20(unsigned char dat);    //通过单总线向DS18B20写一个字节
    unsigned char Read_DS18B20(void);    //从DS18B20读取一个字节
    bit init_ds18b20(void);    //DS18B20设备初始化
    

    (5)处理温度数据(注意)
    在读取温度数据时,是低8位在前,高8位在后,需要将这两个数据合并为一个数据;读取的温度是补码形式表示的,需将转换成原码;求实际温度公式:temp=tp0.0625100+0.5(tp为浮点开数据,temp为无符号整形数据,此数据为实际温度的100倍),乘上100是为温度小数后保留2位,加上0.5起校正数据的作用:将温度数据存入数组时,需将各位数据分离开来,再存入数组,例:
    datatemp[0] = temp / 10000+0x30;
    datatemp[1] = temp % 10000 / 1000+0x30;

    2.4 火灾的监测与报警

    实验思路:用温度传感器DS18B20测量温度,通过火灾传感器检测有无火灾发生,并在显示器上用“fire!!”与“no fire!!”的字样传达信息,通过热感与光感,检测到有火灾或危险情况发生时,启动蜂鸣器报警。
    部分程序如下:

    void init_into(void)
    {
       EX0=1;
       EA=1;
       IT0=0;
    }
    void into(void) interrupt 0
    {
        LcdShowStr(8,0,"fire!!!");
    	sound=1;
    	delay1ms();
    	sound=0;
    	delay1ms();
    }
    if(fire==0)
    {
        uart_sendstring("fire!!!\r\n"); 
    }
    else
    {
        uart_sendstring("no fire!\r\n"); 
    }
    

    2.5 串口的显示与控制

    1.通过串口助手用单个字符控制LED灯工作
    功能说明: 编程时,用变量receivedata接收串口助手发送过来的单个字符数据,分别用字符a、c和e打开D1、D2和D3灯,分别用字符b、d和f关闭D1、D2和D3灯
    2. 通过串口助手用字符串控制LED灯工作
    功能说明: 编程时,用字符数组receivedata接收串口助手发送过来的字符串数据,分别用字符串d1on、d2on和d3on打开D1、D2和D3灯,分别用字符串在d1off、d2off和d3off关闭D1、D2和D3灯

    三、网络传输与控制

    3.1 ESP8266WiFi模块介绍

    ESP8266是一个完整且成体系的WIFI网络解决方案,能够搭载软件应用,或通过另一个应用处理器卸载所有WIFI网络功能。本设计中我们使用的ESP8266是串口型WIFI,速度比较低,不能用来传输图像或者视频这些大容量的数据,主要应用于数据量传输比较少的场合,比如温度信息,一些传感器的开关量等。虽然传输的数据量比较少,但也能一次传输几千字节的数据,而且通信非常稳定,可以满足大多数应用。
    1.ESP8266-WIFI模块支持STA/AP/STA+AP三种工作模式:
    (1)STA模式:ESP8266模块通过路由器连接互联网,手机或电脑通过互联网实现对设备的远程控制。
    (2)AP模式:默认模式,ESP8266模块作为热点,实现手机或电脑直接与模块通信,实现局域网无线控制
    (3)STA+AP模式:两种模式的共存模式,即可以通过互联网控制可实现无缝切换,方便操作。
    ESP8266-WIFI模块仅在单连接状态,支持透传模式(TCP CLIENT透传和UDP透传)。

    3.2 透传工作模式计算机作为TCP SERVER的监控

    1.WIFI模块通过网络和计算机通信的AT指令
    (1)重启wifi模块
    指令:AT+RST
    返回:OK
    (2)设置WIFI模块的工作模式
    指令:AT+CWMODE=3//设置模块为透传工作模式
    返回:OK
    (3)登录路由器
    指令:AT+CWJAP=“TP-LINK_ym2”,“12345678”//登录路由器,路由wifi用户名和密码
    返回:WIFI CONNECTED
    WIFI GOT IP
    (4)连接TCP服务器(wifi模块作为客户端,计算机作为服务器,要先打开监听)
    首先要打开软件网络调试助手,协议类型为TCP Server,点击开始监听。
    指令: AT+CIPSTART=“TCP”,“192.168.0.100”,8080
    返回:Connect OK
    执行以上指令后,wifi模块就会连接到计算机的TCP Server,在网络调试助手上的连接对象栏就会出现WIFI模块的IP地址及端口号
    (5)使能透传模式
    指令:AT+CIPMODE=1
    返回:OK
    (6)透传发送数据
    指令:AT+CIPSEND
    返回:>(在此提示下可以发送数据)
    (7)退出透传数据发送
    指令:+++(去掉串口助手中发送新行选项)
    返回:返回到AT指令模式
    执行了以上的AT指令以后,用串口调试助手和网络调试助手就可以实现WIFI模块通过路由器和计算机进行数据通信了。

    3.3 透传工作模式手机作为服务器的监控

    1.WIFI模块和手机进行通信(WIFI模块作为客户端,手机作为服务器)
    (1)连接TCP服务器(wifi模块作为客户端,计算机作为服务器,要先打开监听),首先在手机上安装有人网络调试助手的APP

    (2)选择tcp server,点击配置,设置手机的端口号,再点击激活后,会在手机屏幕上显示手机的IP和端口号,请一定记住IP和端口号,输入以下指令。
    指令: AT+CIPSTART=“TCP”,“192.168.1.122”,5000//手机的IP和端口号
    返回:CONNECT OK
    执行以上指令后,网络助手上会显示wifi模块的IP和端口号

    (3)多连接 server,AT Demo ESP8266作为服务器,需建立多连接作为服务器,需建立多连接即可以连接多个client。
    最终发送数据:AT+CIPSEND=0,4 // 0是设备的通信号,4表示四个字节
    响应: SEND OK
    接收数据:+IPD,n:xxxxxxxxxx // n表示通信号 ,xxxxx 为数据
    2.WIFI模块通过网络和计算机通信的编程实现:
    delay(20);
    uart_sendstring(“AT+CIPSTART=“TCP”,“192.168.1.101”,8080\r\n”);//设备作为 TCP client 连接 TCP server:
    delay(50);
    uart_sendstring(“AT+CIPMODE=1\r\n”);//使能透传模式
    delay(20);
    uart_sendstring(“AT+CIPSEND\r\n”);//透传发送数据
    delay(20);

    3.4 数据上传到ONENET云平台

    在ONENET云平台上创建一个实验工程,获取虚拟机的ip和key,之后通过透传函数设置新的连接ip,连接到ONENET平台,进而将单片机获取的相应数据传输到平台的虚拟机上,虚拟机对传输的数据进行整理绘制成相应的数据图表显示出来。
    部分程序如下; {“shidu”:22,“wendu”:23}
    POST /devices/284289/datapoints HTTP/1.1
    api-key: UxvFGrtEFZMnfhwF6pa6zV5h9ZwA
    Host: api.heclouds.com
    Content-Length: 69

    {“datastreams”:[{“id”:“ip”,“datapoints”:[{“value”:“192.168.5.88”}]}]}

    四、系统测试

    4.1 本地的控制与工作状态的显示

    4

    4.2远程的控制与工作状态的显示

    4.2.1 透传工作模式计算机作为TCP SERVER的监控测

    5

    4.2.2 透传工作模式手机作为服务器的监控

    6

    五、体会与总结

    在这次的课程实验过程中,前面的基础实验操作,比如开发板上按键对应LED灯的控制,温度传感器对温度的监控与测量,以及蜂鸣器工作室的火警报警功能等,这些都是为后来大的系统功能打基础,由小的功能模块组成大的系统功能实现,这些都是我们小组跟着老师的步伐与思路进行的相对顺利的,也得到了预期的结果。实验过程中,问题主要出现在无线通信的部分,在进行PC机发送指令语句控制单片机功能模块和WIFI模块与手机互连进行数据传输通信时,我们常常出现连接不成功或是操作不当导致乱码的情况,然而在百度查阅资料和询问同学的帮助下,我们一次次攻克了难题,最终通过网络路由互联实现了由手机(客户端)发送命令语句控制单片机开发板上LED灯(家居)亮灭的功能,即模拟智能家居系统中用户直接通过客户端对家具进行控制的智能操作。

    程序代码

     #include"reg51.h"
     #include"lcd.h"
     #include"ds18b20.h"
     #include"string.h"
     #include 
     #define uchar unsigned char
     #define uint unsigned int
     sbit k1=P1^4;
     sbit k2=P1^5;
     sbit k3=P1^6;
     sbit d1=P2^2;
     sbit d2=P2^3;
     sbit d3=P2^4;
     sbit fire=P3^2;
     sbit sound=P2^1;
     uchar count,i=0;
     uchar tempdata[7]={0,0,0,'.',0,0,'\0'} ;
     uchar recedata[8]="        ";
      void delay5ms(void)
     {
         uchar i,j;
         for(i=10;i>0;i--)
    	   for(j=200;j>0;j--)
    	    ;
     }
      void delay1ms(void)
     {
         uchar i,j;
         for(i=2;i>0;i--)
    	   for(j=200;j>0;j--)
    	    ;
     }
      void delay500ms(void)
     {
         uchar i,j,k;
         for(i=10;i>0;i--)
    	   for(j=200;j>0;j--)
    	     for(k=100;k>0;k--)
    	       ;
     }
    
    
     void delay20ms()		//@11.0592MHz
    {
    	unsigned char i, j, k;
    
    	_nop_();
    	_nop_();
    	i = 1;
    	j = 216;
    	k = 35;
    	do
    	{
    		do
    		{
    			while (--k);
    		} while (--j);
    	} while (--i);
    }
    
     void delay(uchar x)
     {
        uchar i,j;
    	while(x--)
    	{
    	    for(j=200;j>0;j--)
    		for(i=248;i>0;i--)
    		  ;
    	}
     }
     void k1scan(void)
     {
         if(k1==0)
    	 {
    	    delay5ms();
    		if(k1==0)
    		{d1=~d1;}
    		do
    		{delay5ms();}
    		while(k1==0);
    	 }
     }
      void k2scan(void)
     {
         if(k2==0)
    	 {
    	    delay5ms();
    		if(k2==0)
    		{d2=~d2;}
    		do
    		{delay5ms();}
    		while(k2==0);
    	 }
     }
      void k3scan(void)
     {
         if(k3==0)
    	 {
    	    delay5ms();
    		if(k3==0)
    		{d3=~d3;}
    		do
    		{delay5ms();}
    		while(k3==0);
    	 }
     }
     void startuptemp(void)
     {
        init_ds18b20();
    	Write_DS18B20(0xcc);
    	Write_DS18B20(0x44);
    	delay500ms();
     }
     int readtemp(void)
     {
        uchar temph,templ;
    	int temp;
    	init_ds18b20();
    	Write_DS18B20(0xcc);
    	Write_DS18B20(0xbe); 
    	templ=Read_DS18B20(); 
    	temph=Read_DS18B20(); 
    	temp=temph;
    	temp=temp<<8;
    	temp=temp|templ;
    	return temp; 
     }
     void tempdealdisp(int temp)
     {
        float tp;
    
    	if(temp<0)
    	{
    	  temp=temp-1;
    	  temp=~temp;
    	  tp=temp;
    	  temp=tp*0.0625*100+0.5;
    	  LcdShowStr(0,0,"-"); 
    	}
    	else
    	{
    	  tp=temp;
    	   temp=tp*0.0625*100+0.5;
    	   LcdShowStr(0,0,"+");   
    	}
    	tempdata[0]=temp/10000+0x30;
    	tempdata[1]=temp%10000/1000+0x30;
    	tempdata[2]=temp%1000/100+0x30;
    	tempdata[3]='.';
    	tempdata[4]=temp%100/10+0x30;
    	tempdata[5]=temp%10+0x30;
    	tempdata[6]='\0';
    	LcdShowStr(1,0,tempdata);
    	LcdShowStr(7,0," ");
     }
     void init_it0(void)
     {
        EX0=1;
    	EA=1;
    	IT0=0;
     }
     void it0(void) interrupt 0
     {
        LcdShowStr(8,0,"fire!!!");
    	sound=1;
    	delay1ms();
    	sound=0;
    	delay1ms();
     }
     void lampworking(void)
     {
            if(d1==0)
    		 {
    		    LcdShowStr(0,1,"1:on "); 
    		 }
    		 else
    		 {
    		    LcdShowStr(0,1,"1:off"); 
    		 }
    		 if(d2==0)
    		 {
    		    LcdShowStr(5,1,"2:on "); 
    		 }
    		 else
    		 {
    		    LcdShowStr(5,1,"2:off"); 
    		 }
    		 if(d3==0)
    		 {
    		    LcdShowStr(10,1,"3:on "); 
    		 }
    		 else
    		 {
    		    LcdShowStr(10,1,"3:off"); 
    		 }
     }
     void uart_init(void)
     {
         SCON=0X50;
    	 TMOD=0X20;
    	 PCON=0X00;
    	 IP=0x02;
    	 TH1=0xF3;         //波特率2400
    	 TL1=0xF3;
    	 ES=1;
    	 EA=1;
    	 TR1=1;
    
     }
     void t0_init(void)
     {
        TMOD=TMOD&0XF0;
    	TMOD=TMOD|0X01;
    	TH0=(65536-50000)/256;
    	TL0=(65536-50000)%256;
    	ET0=1;
    	EA=1;
    	TR0=1;
     }
     void uart_sendstring(uchar *str)
     {
         TR0=0;
    	 while(*str!='\0')
    	 {
    	    SBUF=*str;
    		while(TI==0);
    		TI=0;
    		str++;
    	 }
         TR0=1;
     }
    
     void senddata(void)
    {
         uart_sendstring("POST /devices/35167558/datapoints?type=3 HTTP/1.1\r\n");			  
     	 uart_sendstring("api-key:YH4jdhz=mvLEuhwOSDRXTqHUwFs=\r\n");
    	 uart_sendstring("Host:api.heclouds.com\r\n");		 
    	 uart_sendstring("Content-Length:19\r\n");
    	 uart_sendstring("\r\n");
         uart_sendstring("{\"wendu\":");
         uart_sendstring(tempdata);//12.6    
         uart_sendstring("}\r\n");
         uart_sendstring("\r\n");                        
         delay(100);   
    }
     void t0(void ) interrupt 1
     {
        TH0=(65536-50000)/256;
    	TL0=(65536-50000)%256;
    	count++;
    	if(count==100)
    	{
    		count=0;
    	   senddata();
    	   count=0;
    	}
     }
     void uart_rec(void) interrupt 4
     {
    
        if(RI==1)
    	{
    	   recedata[i]=SBUF;
    	   RI=0;
    	   i++;
    	   if(recedata[i-1]=='9')
    	   {
    	      recedata[i-1]='\0';
    		  i=0;
    	   }
    	  
    	    if(strcmp(recedata,"d1on")==0)
    		{
    		   d1=0;
    		}
    		if(strcmp(recedata,"d1off")==0)
    		{
    		   d1=1;
    		}
    	    if(strcmp(recedata,"d2on")==0)
    		{
    		   d2=0;
    		}
    	    if(strcmp(recedata,"d2off")==0)
    		{
    		   d2=1;
    		}
    	    if(strcmp(recedata,"d3on")==0)
    		{
    		   d3=0;
    		}
    	    if(strcmp(recedata,"d3off")==0)
    		{
    		   d3=1;
    		}
    		}
     }
    
     void tcpserverlogin(void)
     {
        uart_sendstring("AT+RST\r\n");
    	delay(50);
        uart_sendstring("AT+CWMODE=3\r\n");	 
    	delay(20);
    	uart_sendstring("AT+CWJAP=\"45626\",\"123456789\"\r\n");
    
    	delay(100);
    //	uart_sendstring("AT+CIPSTART=\"TCP\",\"56.69.11.54\",8234\r\n");//设备作为 TCP client 连接 TCP server:
    //  uart_sendstring("AT+CIPSTART=\"TCP\",\"192.168.1.101\",8080\r\n");
        uart_sendstring("AT+CIPSTART=\"TCP\",\"183.230.40.33\",80\r\n");
    
    
    	delay(100);
        uart_sendstring("AT+CIPMODE=1\r\n");//使能透传模式
    	delay(20);
    	uart_sendstring("AT+CIPSEND\r\n");//透传发送数据
        delay(20);
      
     }
     main()
     {
         d1=1;
    	 d2=1;
    	 d3=1;
    	 
    	 init_it0();
    	 InitLcd1602(); 
         uart_init();	  
    	
    	  tcpserverlogin();
    	  	 t0_init();
    	 while(1)
    	 {
    	     k1scan();
    		 k2scan();
    		 k3scan();
    		 startuptemp();
    		 tempdealdisp(readtemp());
    		 lampworking();
    		 if(fire==1)
    		 {LcdShowStr(8,0,"no fire");}
    
    	 }
     }
    
  • 相关阅读:
    FPGA SERDESE2 (SDR收发仿真)
    HTML渲染过程
    java中的注解
    Python Spyder下载、安装和使用教程
    01_SpringBoot简介及项目搭建
    MySQL 存储引擎,你了解几个?
    Forest + IDEA = 双倍快乐!ForestX 隆重登场
    Linux进程控制(下)--->进程程序替换
    python基础语言:字符串表示
    【操作系统】内存管理
  • 原文地址:https://blog.csdn.net/qq_41908302/article/details/139886094