基于51单片机的wifi智能led灯的毕业设计

摘要

      系统基于STC89C52RC单片机设计,拥有自动与手动两种模式,自动模式下可以过热释红外传感器检测是否有人,采用光敏电阻构成的电路检测环境光的强度,从而自动实现灯的自动开启和关闭;手动模式下可以使用wifi连接手机,通过手机app手动控制不同灯的开启和关闭并可控制各LED灯的光亮度,并采用可移动充电式电源供电,满足不同场景的需求。系统简单易行、控制方便,可用于传统照明的节能改造。

设计思路

      本系统基于STC89C52单片机设计,可实现灯具的自动控制;同时,结合esp8266wifi模块通过安卓手机端app与wifi模块进行数据通信,实现对被控对象的无线连接手动控制。主要功能如下:

(1)自动模式: 通过光敏电阻和热释红外传感器分别自动检测光的强弱和是否有人,室内无人或者光照充足时自动灭灯,灭灯时间延时一分钟;有人到且光照不足时自动开灯;该模式即节约了人力资源又节约了大量电能。
(2)手动模式:开启手机wifi,通过手机APP手动控制灯的开启和关闭,使用手机轻松控制灯的开关,方便快捷。

图1 系统框图

基于51单片机WiFi智能家居 基于51单片机的wifi智能小灯_基于51单片机WiFi智能家居


基于51单片机WiFi智能家居 基于51单片机的wifi智能小灯_基于51单片机WiFi智能家居_02

硬件设计

wifi模块

      wifi模块采用esp8266,对wifi模块进行配置就需要使用到AT指令集。其最基础的一些AT指令集在下面贴出,部分会在代码中使用到。

WIFIAT+CIPMUX=1AT+CIPSERVER=1,80	//修改端口号
AT+CWMODE=3				//设置模式
AT+RST					//重启
AT+CWJAP="WiFixdd","xiaojieying"	//搜索并连接路由器
AT+CIPMODE=1				//透传
AT+CIPMUX=0				//单路模式
AT+CIPSTART="TCP","172.29.242.2",8080	//连接手机端
AT+CIPSEND				//进入透传

若想深入研究自行找资料学习AT指令集。

热释电传感器

      HC-SR501 人体红外传感器模块是基于红外技术的自动控制模块,它可以检测人或某些动物发出的红外辐射并输出电信号我们使用的 。

基于51单片机WiFi智能家居 基于51单片机的wifi智能小灯_c语言_03


基于51单片机WiFi智能家居 基于51单片机的wifi智能小灯_物联网_04

电源模块

      电源模块采用18650可充电电池,由于其供电电压为3.6V,不能很好的为电路工作,所以我们通过升压模块对其进行电压放大,以达到标准供电电压5V。并能通过变压充电模块为18650电池充电。

基于51单片机WiFi智能家居 基于51单片机的wifi智能小灯_基于51单片机WiFi智能家居_05

驱动电路

      由于52单片机的IO口驱动能力较弱,无法满足大型LED灯的需要,所以我们在这里通过三极管进行电流放大,该驱动电路通过电阻对单片机IO口进行降压,使得三极管得以导通,并对单片机IO口电流进行放大,以达到驱动该大型灯泡的能力,并给每一个LED灯串联一个限流电阻,已达到保护LED灯延长使用寿命的作用。该电路共使用六个大型LED灯照明,三黄三白,不同颜色交替摆放,已保证单种颜色灯光的照明范围。

基于51单片机WiFi智能家居 基于51单片机的wifi智能小灯_物联网_06


要注意的是实物硬件电路板对led灯的一个布局,以及合理跳线的一个问题。

代码实施

      程序主要模块是通过单片机串口与蓝牙进行通信。由于STC89c52没有独立的波特率发生器,所以我们这里将定时计数器T1改装成波特率发生器,产生9600的标准波特率,并通过串口中断函数对读取数据进行接收,并将串口中断优先级调到最高。

基于51单片机WiFi智能家居 基于51单片机的wifi智能小灯_安卓_07


      下面是手机APP与单片机的简单通信协议,创建单独协议的目的是为了对以后项目扩展,技术升级留下足够的预留空间,并可以保证产品的加密安全性。

基于51单片机WiFi智能家居 基于51单片机的wifi智能小灯_物联网_08


      通过对程序的算法设计,该智能灯泡可达到黑夜可自动控制,有人经过则自动开起,并保持最大可调时间10分钟后自动熄灭。通过手机APP控制LED的开关以及亮度调节,若夜晚通过手机APP开起灯光,人经过后无需手机关闭即可自动关闭,以防止由于忘关造成的电力浪费。以下是主程序流程图。

基于51单片机WiFi智能家居 基于51单片机的wifi智能小灯_安卓_09


main.c

#include "reg52.h"
#include"uart.h"
#include"led.h"
#include<stdio.h> 

sbit MAN=P1^4;  

int main()
{ 	 	
  unsigned char dat=0;	
  NewLineReceived = 0;	
  MAN=1;	
  ColorLED_Init();		//LED灯初始化  
  Serial_Init();		//串口初始化  
  ms_delay(1000);	
  WIFI_Init();			//WIFI模块初始化	    	
  timer0_init();		//定时计数器零初始化	
  color_led_pwm(0, 0);  
  while(1)	
  { 			
    if(MAN==0)		
    {			
      color_led_pwm(255, 255);			
      while(MAN==0) ;				
      color_led_pwm(0, 0);		
    }  	 			
    if(NewLineReceived == 1)		
    {	 			
      uart_send_string("Init OK!"); 			
      serial_led();//调用串口解析函数			
      NewLineReceived = 0;		 		
    }	
  }  
}

led.c

#include "reg52.h"
 sbit LED_W = P1^0;
 sbit LED_W1=P1^1;
 sbit LED_W2=P1^2; 
 sbit LED_Y = P1^5;
 sbit LED_Y1 = P1^6;
 sbit LED_Y2 = P1^7;
  unsigned char whitenum=0;
  unsigned char yellownum=0; 
  unsigned char ledWnum=0;
  unsigned char ledYnum=0;
   void ColorLED_Init()
   {	      	LED_W = 1;	LED_W1 = 1;	LED_W2 = 1;   	LED_Y = 1;	LED_Y1 = 1;	LED_Y2 = 1;}
 void color_led_pwm(unsigned char v_iwhite, unsigned char v_iyellow)//点亮相应颜色的灯
 {	whitenum = v_iwhite;	yellownum = v_iyellow; }
  /*** Function       ledRPwmWrite* @author        Danny* @date          2017.08.16* @brief         LED_R产生pwm* @param         void* @retval        void* @par History   无*/ 
 void ledWPwmWrite()
 {	if((whitenum != 0) && (whitenum!=255))	{		if(ledWnum <=  whitenum)		{				LED_W=1;			LED_W1=1;			LED_W2=1;		}		else		{				LED_W=0;			LED_W1=0;			LED_W2=0;		}	}	else if(whitenum==0)		{				LED_W=0;			LED_W1=0;			LED_W2=0;		}	else if(whitenum==255)	   	{				LED_W=1;			LED_W1=1;			LED_W2=1;		}} 
 /*** Function       ledGPwmWrite* @author        Danny* @date          2017.08.16* @brief         LED_G产生pwm* @param         void* @retval        void* @par History   无*/ 
 void ledYPwmWrite()
 {	if((yellownum != 0)&&(yellownum!=255))	{		if(ledYnum<=yellownum)		{			LED_Y=1;			LED_Y1=1;			LED_Y2=1;		}		else		{			LED_Y=0;			LED_Y1=0;			LED_Y2=0;		}	}	else if(yellownum==0)	   {			LED_Y=0;			LED_Y1=0;			LED_Y2=0;		}	else if(yellownum==255)	   {			LED_Y=1;			LED_Y1=1;			LED_Y2=1;		}}   
 void Update_ColorPWM()
 {	ledWPwmWrite();	ledYPwmWrite();} 
 void timer0_init()
 {	TMOD|=0X01;  //定时器T0工作方式1,定时器T1工作方式2    
 TH0=0XFF;    //100us定时,装入初值    
 TL0=0XA4;	TR0=1;		//启动T0工作    
 ET0=1;		//允许T0中断  	
 EA =1;	    //开总中断	
 PT0=0; }	
  void timer0() interrupt 1  
  {     TH0=0XFF;    //50us定时,装入初值   
   TL0=0XD2;  	//控制pwmled	
   ledWnum++;	ledYnum++;	Update_ColorPWM(); 
  }

uart.c

#include "reg52.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 #include"led.h"
 bit NewLineReceived = 0;       //串口接收完成标志位bit StartBit  = 0;             //协议开始标志int g_num=0;				   //定义变量int g_packnum=0;char InputString[50] = {0};    //用来储存接收到的内容 /*** Function       StringFind* @author        Danny* @date          2017.08.16    * @brief         字符串查找* @param[in]     pSrc:源字符串; pDst:查找的字符串; v_iStartPos:源字符串起始位置* @param[out]    void* @retval        void* @par History   无*/int StringFind(const char *pSrc, const char *pDst, int v_iStartPos)  {  	int i, j;      for (i = v_iStartPos; pSrc[i]!='\0'; i++)  	  //判断是否到了源字符串的结束符    {          if(pSrc[i]!=pDst[0])  					  //与所要查找的字符串的第一个字节作比较        	continue;                 j = 0;          while(pDst[j] !='\0' && pSrc[i+j]!='\0')  //判断是否到了所要查找字符串以及源字符串的结束符        {              j++;              if(pDst[j]!=pSrc[i+j])              break;          }          if(pDst[j]=='\0')  						  //判断是否到了所要查找字符串的结束符            return i;      }      return -1;  }  /*** Function       uart_send_byte* @author        Danny* @date          2017.08.16* @brief         串口发送一个字符* @param[in]     data:字符* @param[out]    void* @retval        void* @par History   无*/void uart_send_byte(unsigned char dat){   SBUF = dat;	          //把数据放到SBUF中   while(TI == 0);	      //未发送完毕就等待   TI=0;                  //发送完毕后,要把TI重置0} /*** Function       uart_send_string* @author        Danny* @date          2017.08.16* @brief         串口发送一个字符串* @param[in]     void* @param[out]    void* @retval        void* @par History   无*/void uart_send_string(unsigned char *str){	while(*str != '\0')		     //判断指针str是否指向字符串的末尾	{	   uart_send_byte(*str);     //往串口上发送字符串	   str++;					 //指针自增,按照一个字节一个字节发送字符串	}}				   /*** Function       Serial_Init* @author        Danny* @date          2017.08.16* @brief         串口初始化函数* @param         void* @retval        void* @par History   无*/void Serial_Init(){  	SCON=0x50;      //[bit6:5]SM1 SM2 = 1 0;[bit4]REN=1  /*	AUXR=0x11;      //[bit4]BRTR=1,允许独立波特率发生器运行;[bit0]SIBRS=1,                    //独立波特率作为串口1的波特率发生器,此时定时器1释放	BRT=0XFD;       //独特波特率发生器定时器(产生波特率9600) */	TMOD|=0X20;		PCON=0;	TH1=TL1=0XFD;	TR1=1;  	ES=1;			//开串口中断  	EA=1;			//开总中断	PS=1;} /*** Function       serial_IRQHandler* @author        Danny* @date          2017.08.16* @brief         串口中断处理接收串口数据函数* @param         void* @retval        void* @par History   无*/void serial_IRQHandler(void) interrupt 4 using 1  //串行口中断,第一组寄存器{	 	unsigned char date = 0;   	if(RI)  	{    	RI=0;					       //清除接收中断标志位		date=SBUF;				       //串行口接收到的数据		if(date == '$')		{	  		StartBit = 1;		       //协议开始	  		g_num = 0;		}		if(StartBit == 1)		{			InputString[g_num]=date;   //将接收到的数据存储到定义的数组中		}		if(StartBit == 1 && date == '#')		{	  		NewLineReceived = 1;	   //串口接收完成标志	  		StartBit = 0;			   //协议关闭	  		g_packnum = g_num;		   		}		g_num++;					    //g_num自增		if(g_num >= 80)		{			g_num=0;				    //将g_num清零			StartBit=0;			NewLineReceived=0;		    //串口接收完成标志		}  	}}/******************************************************************函 数: void ms_delay(int t)功 能: 毫秒级延时参 数: 无返回值: 无*******************************************************************/void ms_delay(int t)  { 	int i,j; 	for(i=t;i>0;i--) 		for(j=110;j>0;j--); }/******************************************************************函 数: void WIFI_Init(void)功 能: wifi初始化(名字:esp8266;密码:1234567890)参 数: 无返回值: 无*******************************************************************/ void WIFI_Init(void) {	ES = 0;	TI = 1; 	printf("AT+RST\r\n");	ms_delay(1000) ;	printf("AT+CWMODE=3\r\n");	ms_delay(1000) ;	printf("AT+CIPMUX=1\r\n");	ms_delay(1000) ;	printf("AT+CIPSERVER=1,8080\r\n"); 	ms_delay(1000) ;printf("AT+CIOBAUD=9600\r\n"); // 设置与单片机一致的波特率 	ms_delay(1000) ;	while(!TI);	TI = 0;	ES = 1;} /*void WIFI_Init(void) {	ES = 0;	TI = 1; 	uart_send_string("AT+RST\r\n");	ms_delay(1000) ;	uart_send_string("AT+CWMODE=3\r\n");	ms_delay(1000) ;	uart_send_string("AT+CIPMUX=1\r\n");	ms_delay(1000) ;	uart_send_string("AT+CIPSERVER=1,8080\r\n"); 	ms_delay(1000) ;uart_send_string("AT+CIOBAUD=9600\r\n"); // 设置与单片机一致的波特率 	ms_delay(1000) ;	while(!TI);	TI = 0;	ES = 1;}  */void serial_led(){	 //解析蓝牙APP发来的灯控信息    //如:$JC,CLW255,CLY000# 亮白灯	if (StringFind((const char *)InputString, (const char *)"CLW", 0) > 0) //判断是否查找到了字符串"CLW" 	{		int m_kp, i, ii, white, yellow;								   //定义变量		char m_skp[5] = {0}; 		//寻找以CLW开头,,结束中间的字符											   //定义数组存放数据		i = StringFind((const char *)InputString, (const char *)"CLW", 0); //查找到字符串"CLW"的位置赋值给i		ii = StringFind((const char *)InputString, (const char *)",", i);  //查找到字符串","的位置赋值给ii		if (ii > i)														   //判断ii与i的关系大小		{						memcpy(m_skp, InputString + i + 3, ii - i -3);				//从InputString + i + 3所指的内存地址的起始位置开始拷贝(ii-i-3)个字节到m_skp所指的内存地址的起始位置中			m_kp = atoi(m_skp);											   //将找到的字符串m_skp转换成整形数赋值给m_kp			white = m_kp;		} 		 		//寻找以CLY开头,#结束中间的字符		i = StringFind((const char *)InputString, (const char *)"CLY", 0); //查找到字符串"CLY"的位置赋值给i		ii = StringFind((const char *)InputString, (const char *)"#", i);  //查找到字符串","的位置赋值给ii		if (ii > i)														   //判断ii与i的关系大小		{			memset(m_skp, 0x00, sizeof(m_skp));							   //清空m_skp中的数据			memcpy(m_skp, InputString + i + 3, ii - i -3);			//从InputString + i + 3所指的内存地址的起始位置开始拷贝(ii-i-3)个字节到m_skp所指的内存地址的起始位置中			m_kp = atoi(m_skp);											   //将找到的字符串m_skp转换成整形数赋值给m_kp			yellow = m_kp;			//sprintf(ReturnTemp, "%d", green);			//uart_send_string(ReturnTemp);			color_led_pwm(white, yellow);                              //点亮相应颜色的灯			NewLineReceived = 0;  			memset(InputString, 0x00, sizeof(InputString));               //清空串口数据						return;		}	}	if (StringFind((const char *)InputString, (const char *)"JC", 0) == -1 )  //判断是否查找到了字符串"4WD"	{		//点灯判断    	if (InputString[1] == 'W')       //白灯    	{			if(InputString[2]=='1')      		color_led_pwm(255, 0);			if(InputString[2]=='0')      		color_led_pwm(0, 0);    	}    	else if (InputString[1] == 'Y')  //黄灯    	{      		if(InputString[2]=='1')      		color_led_pwm(0, 255);			if(InputString[2]=='0')      		color_led_pwm(0, 0);    	}    	else if (InputString[1] == 'O')  //全部灯    	{      		if(InputString[2]=='1')      		color_led_pwm(255,255);			if(InputString[2]=='0')      		color_led_pwm(0, 0);    	}    		}
 }

由于格式问题,代码格式是乱的,可自行整理,并添加.h文件,或通过下方链接下载。

手机APP程序

      可自行制作或下载第三方软件WiFi调试助手。
凭借其开放性的巨大优势,安卓平台在设备开发应用中广受欢迎。安卓平台允许开发者根据自己的喜好和应用需求,设计出具有不同特色的实用软件。同时,安卓平台还能够适配多种硬件开发平台,对于硬件开发门槛要求低,极大地方便了用户对其进行相关的开发研究。此外,凭借其巨大的优势,安卓平台在当前开发平台领域中呈现逐年上升的趋势。因此在本设计中采用安卓平台进行本项目的设计开发。