该智能家居系统以 STC89C52单片机为控制核心,结合 LCD1602 液晶显示屏、L298N电机驱动模块、光敏电阻,ESP8266WiFi模块,DS18B20温度计设计并实现了自动感光窗帘与居室内外温度检测器。经过最终的调试,实现了基本部分和发挥部分的所有功能。温度检测系统在环境温度改变的情况下可以实现误差为 0.5℃的基本温度测量。而智能窗帘系统在光照强度不同的情况下电机表现了不同的转动状态,故该系统具有感光自动开关的功能,同时该系统通过物联网模块实现了用户与窗帘交互的功能,可以手动调节窗帘的开关。以下是我和我的两名队友花了四天三夜共同完成的作品实物图
虽然外观不是很好看?,但是基本可以实现所有所需要的功能,以下是对该作品的设计与总结
一、系统方案
1.系统总体方案设计
2.系统结构框图
二、电路与程序设计
1.各部分电路设计
2.程序设计
三、测试结果
1.测试方案
2.测试结果及分析
四、结论
五、附录.
1.电路原理图
2.程序清单
一、系统方案
1.系统总体方案设计
(1)居室内外温度检测系统
本系统以 STC89C52 芯片作为控制中心,DS18B20 温度传感器为测温元件,LCD1602 液晶显示屏为显示器件。DS1802 数字温度计提供 9 位温度读数,指示器件的温度。信息经过单线接口送入DS1820 或从 DS1820 送出。当信息送入,经过单片机处理后在液晶上显示。其系统框图如图 1 所示。
(2)智能窗帘
本系统由光照检测电路、电机驱动电路以及物联网模块三个部分组成。窗帘自动控制系统的光控功能是可以根据光照的强弱来自动控制窗帘的开闭的,因此需要用到光照传感元器件,在本设计中采用了光敏电阻,并和一个常规电阻串联在一起,根据光线的变化改变光敏电阻的分压值,然后通过 XPT2046数模转换芯片传输给单片机,然后根据转换后的数值对电机的转动状态进行调控。同时用户可以通过物联网模块对电机的转动状态进行了解和调控。其系统框图如图2所示。
2.系统结构框图
二、电路与程序设计
1.各部分电路设计
(1)温度检测模块
在温度检测系统中,该模块起到检测外部环境温度的作用。DS1802 数字温度计提供 9 位温度读数,指示器件的温度。信息经过单线接口送入 DS1820 或从DS1820 送出,因此从中央处理器到 DS1820 仅需连接一条线(和地)。读、写和完成温度变换所需的电源可以由数据线本身提供,而不需要外部电源。
(2)AD 转换模块
为使被检测到的温度数据转换为电信号后传输至单片机,故设计一个 AD 转换模块以达到目的。其中 XPT2046 是一款 4 线制电阻式触摸屏控制器,内含 12位分辨率 125KHz 转换速率逐步逼近型 A/D 转换器。XPT2046 支持从 1.5V 到 5.25V的低电压 I/O 接口。内部自带 2.5V 参考电压,可以作为辅助输入、温度测量和电池监测之用,电池监测的电压范围可以从 0V 到 6V。因此可以满足系统要求。
(3)电机驱动模块
在智能窗帘系统中,电机模块用于使智能窗帘实现自动开关的功能。若要对电机进行 PWM 调速,需设置 IN1 和 IN2,确定电机的转动方向,然后对使能端输出 PWM 脉冲,即可实现调速。当使能信号为 0 时,电机处于自由停止状态;当使能信号为 1 时,且 IN1 和 IN2 为 00 或 11 时,电机处于制动状态,阻止电机转动。因此可在不同情况下,根据外部环境改变电机的转动状态,满足系统要求。 (4)STC90C52本设计选用单片机 STC89C52 作为控制核心,它是宏晶科技推出的新一代超强抗干扰、高速、低功耗的单片机,基于 Intel 标准的 8052,指令代码完全兼容传统的 8051 系列单片机,12 时钟/机器周期和 6 时钟/机器周期可任意选择,最新的 D 版本内集成 MAX810 专用复位电路。
(5)LCD 液晶显示屏
在温度检测系统中用于显示场景的温度数据以及在智能窗帘系统中用于显示光照强度数据。为工业字符型液晶,能够同时显示 16x2 即 32 个字符。
(6)ESP8266-01
为使用户可以随时了解并控制窗帘的开闭状态,故设计物联网模块以实现智能窗帘与用户交互的功能。其中 ESP8266 是一款超低功耗的 UART-WiFi 透传模块,拥有业内极富竞争力的封装尺寸和超低能耗技术,专为移动设备和物联网应用设计,可将用户的物理设备连接到 Wi-Fi 无线网络上,进行互联网或局域网通信,实现联网功能。
2.程序设计
(1)居室内外温度检测系统
本系统以 STC89C52 作为主控芯片,实现温度检测功能。其中温度检测模块检测环境温度,LCD1602 显示温度数据。流程图如图 3 所示。
(2)智能窗帘
本系统以 STC89C52 作为主控芯片,实现窗帘根据环境中光照强度自动开关的功能,且同时用户也可以通过移动终端了解并控制窗帘状态。其中光照检测系统检测环境中光照强度,电机驱动系统控制电机转动状态,物联网模块实现窗帘与用户交互功能。流程图如图 3 所示。
三、测试结果
1.测试方案
(1)居室内外温度检测系统
改变温度检测模块附近环境温度,观察 LCD1602 液晶屏所显示温度数据,测试结果为显示数据与实际环境温度基本吻合。
(2)智能窗帘
首先用手电筒照射装置,使光照强度大于 300,测试结果为窗帘打开,然后将装置放到阴暗处,使光照强度低于 90,测试结果为窗帘关闭。接着按下装置上方按键,将窗帘由自动模式转为手动模式,用手机连接装置的 WiFi 模块,控制窗帘的状态,测试结果为手机发送 1 时窗帘打开,发送 2 时窗帘关闭。
2.测试结果及分析
由测试结果可以看出,温度检测系统与智能窗帘系统可实现题目的基本要求部分和发挥部分的所有功能。其中温度检测系统可以在误差为 0.5℃的情况下检测出环境温度;智能窗帘系统可以实现强光与弱光环境下自动开关。另外部分功能如智能窗帘系统可以通过物联网模块使用户能在移动终控制窗帘状态。
四、结论
温度检测系统与智能窗帘系统实现了基本部分的全部功能以及完成了一些发挥部分,符合所有指标。本系统通过理论计算得到了合理的设计方案,以 STC89C52 单片机为控制核心,结LCD1602 液晶显示屏、L298N 电机驱动模块、光敏电阻,设计并实现了自动感光窗帘与居所内外温度检测器。通过实际测试,温度检测系统在环境温度改变的情况下实现了误差为0.5℃的基本温度测量。而智能窗帘系统在光照强度不同的情况下电机表现了不同的转动状态,故该系统具有感光自动开关的功能,同时该系统通过物联网模块实现了用户与窗帘交互的功能。
五、附录
1.电路原理图
2.程序清单(因代码太长,这里就只放上主程序了,全部源程序包括原理图见文末)
#include<reg52.h>
#include"lcd.h"
#include"temp.h"
#include"XPT2046.h"
void LcdDisplay(int);//LCD显示函数
void UsartConfiguration();//串口初始化函数
void connect_init();//ESP8266初始化函数
uint temp;
uchar CNCHAR[6] = "摄氏度";
uint i=0;
uint j=0;
int flag=1; //手动 or 自动标志位
int ji=1; //正反转停止标志位
uchar receive[10];//接收数组
sbit K1=P3^3; //按键 IO 口
sbit M2PWM = P1^0; //电机 IO 口
sbit M2B = P1^1;
sbit M2A = P1^2;
/*******************************************************************************
* 函 数 名 : delay和delayms
* 函数功能 :10us和1ms的延时
*******************************************************************************/
void delay(unsigned int i)
{
while(i--);
}
void delayms(unsigned int x)
{
unsigned int i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
/*******************************************************************************
* 函数名 :datapros()
* 函数功能 :数据处理光敏函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void datapros()
{
delay(5000);
temp = Read_AD_Data(0xA4); // AIN2 光敏电阻
}
/*******************************************************************************
* 函数名 : main
* 函数功能 : 主函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void main()
{
UsartConfiguration(); //串口初始化
connect_init(); //ESP8266初始化
LcdInit(); //初始化LCD1602
LcdWriteCom(0x88); //写地址 80表示初始地址
LcdWriteData('C');
connect_init(); //再次ESP8266初始化
while(1)
{ datapros(); //数据处理函数
LcdWriteCom(0x8A);
LcdWriteData('0'+temp/1000); //千位
LcdWriteCom(0x8B);
LcdWriteData('0'+temp%1000/100); //百位
LcdWriteCom(0x8C);
LcdWriteData('0'+temp%1000%100/10); //十位
LcdWriteCom(0x8D);
LcdWriteData('0'+temp%1000%100%10/10); //个位
if(flag==1)
{
if(temp<90&&ji==-1)
{
M2PWM=1;
M2B=1;
M2A=0;
delayms(1000); //转动1s
M2PWM=0;
M2B=0;
M2A=0;
ji=1;
}
else if(temp>300&&ji==1)
{
M2PWM=1;
M2B=0;
M2A=1;
delayms(1000); //转动1s
M2PWM=0;
M2B=0;
M2A=0;
ji=-1;
}
else
{
M2PWM=0;
M2B=0;
M2A=0;
}
}
if(!K1) //手动切自动按键
{
delayms(5); //消抖
if(!K1)
{
flag=-flag;
}
}
LcdDisplay(Ds18b20ReadTemp()); //显示温度 光照AD值
}
}
/*******************************************************************************
* 函数名 : LcdDisplay()
* 函数功能 : LCD显示读取到的温度
* 输入 : v
* 输出 : 无
*******************************************************************************/
void LcdDisplay(int temp) //lcd显示
{
uchar datas[] = {0, 0, 0, 0, 0}; //定义数组
float tp;
if(temp< 0) //当温度值为负数
{
LcdWriteCom(0x80); //写地址 80表示初始地址
LcdWriteData('-'); //显示负
//因为读取的温度是实际温度的补码,所以减1,再取反求出原码
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;
//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
//算.5,还是在小数点后面。
}
else
{
LcdWriteCom(0x80); //写地址 80表示初始地址
LcdWriteData('+'); //显示正
tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
//如果温度是正的那么,那么正数的原码就是补码它本身
temp=tp*0.0625*100+0.5;
//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
//算加上0.5,还是在小数点后面。
}
datas[0] = temp / 10000;
datas[1] = temp % 10000 / 1000;
datas[2] = temp % 1000 / 100;
datas[3] = temp % 100 / 10;
datas[4] = temp % 10;
LcdWriteCom(0x82); //写地址 80表示初始地址
LcdWriteData('0'+datas[0]); //百位
LcdWriteCom(0x83); //写地址 80表示初始地址
LcdWriteData('0'+datas[1]); //十位
LcdWriteCom(0x84); //写地址 80表示初始地址
LcdWriteData('0'+datas[2]); //个位
LcdWriteCom(0x85); //写地址 80表示初始地址
LcdWriteData('.'); //显示 ‘.’
LcdWriteCom(0x86); //写地址 80表示初始地址
LcdWriteData('0'+datas[3]); //显示小数点
LcdWriteCom(0x87); //写地址 80表示初始地址
LcdWriteData('0'+datas[4]); //显示小数点
}
/*******************************************************************************
* 函 数 名 :UsartConfiguration()
* 函数功能 :设置串口
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void UsartConfiguration()
{
SCON=0X50; //设置为工作方式1
TMOD|=0X20; //设置计数器工作方式2
PCON|=0X80; //波特率加倍
TH1=0XF3; //计数器初始值设置,注意波特率是4800的
TL1=0XF3;
ES=1; //打开接收中断
EA=1; //打开总中断
TR1=1; //打开计数器
}
void connect_init()
{
char *a="AT+CIPMUX=1\r\n";
char *b="AT+CIPSERVER=1,8080\r\n";
while(*a!='\0')
{
SBUF=*a; //写入要发送的字符
while(!TI); //等待发送完成
TI=0; //发送
a++;
}
delay(500);//这里添加延时函数,延时5ms左右,给ESP8266反应时间
while(*b!='\0')
{
SBUF=*b;
while(!TI); //等待发送完成
TI=0;
b++;
}
}
void UART_SER (void) interrupt 4 //串行中断服务程序
{
char res;
res=SBUF; //取出接受到的数据
RI=0; //清除接受中断标志位
if(res==':'||i>0) //i是全局变量
{
receive[i]=res; //receive数组也是全局变量
i++;
if(res=='\n')
{
if(receive[1]=='1') //添加对收到信息的处理代码 1代表打开窗帘
{
if(flag==-1)
{
M2PWM=1;
M2B=0;
M2A=1;
delayms(1000); // 转动1s
M2PWM=0;
M2B=0;
M2A=0;
}
}
else if(receive[1]=='2') //添加对收到信息的处理代码 2代表关闭窗帘
{
if(flag==-1)
{
M2PWM=1;
M2B=1;
M2A=0;
delayms(1000); //转动1s
M2PWM=0;
M2B=0;
M2A=0;
}
}
i=0;
}
}
}
这是我第一次在CSDN这样官方的IT论坛上发表自己的作品,不仅是希望能给需要学习这方面的人一些指引并且提供我的思路和想法,更是希望这篇文章能够记录下我学习单片机的点滴,这是我学习51这么久以来最有综合性的项目,也可能是我最后一个用51单片机做的项目了(真香警告),接下来就要开始苦逼的学习STM32的道路了?,文章中可能会有些缺陷或者错误,也可能会有因为我水平的原因而做得不足的地方(即将大二的学生),欢迎大佬来指正和讨论,一起学习!!
最后附上全部源代码,原理图以及ESP8266WIFI模块的资料**==
链接:https://pan.baidu.com/s/1dJGa_3IoGPDGS44_TnPzmA
提取码:bkq1
上面的资料失效了 需要的话私聊我