文章目录
- 前言
- 1 背景
- 2 可实现功能
- 3 制作材料
- 4 设计电路
- 5 设计原理
- 5.1 原理一(人体感应)
- 5.2 原理二(距离感应)
- 5.3 原理三(灯的亮度调节)
- 6 程序设计
- 7 成品模型展示
- 总结
前言
首先我先说说为什么要做这个东西,这个是由于前几天一个朋友突然找我说要交一个作业但又不知道要做什么,我听了作业要求后要求后给出的解决方法,做一个人体感应灯,并答应她帮她做。
1 背景
为什么要做这个灯呢?由于现在大部分楼道灯仍采用声光控制,这就导致晚上时你必须弄出点声响才可以点亮楼道灯,但晚上声音必然会造成扰民,所以这个设计一点也不人性化。因此提出一款基于51开发的人体感应贴心灯,本作品是基于STC89C52单片机开发的人体感应贴心灯。当有人靠近时贴心灯会自动点亮,当人与感应开关距离越来越接近时,灯的亮度也会随之增强。本作品可以用于楼道灯、学生智能台灯、以及人行道的路灯的控制,以优化用户的体验,达到贴心的效果。
2 可实现功能
当人体靠近灯时,灯会自动点亮,此时单片机通过超声波来检测人距离灯的位置,来控制灯的亮度,当人距离灯越近时灯越亮。当附近无人时8秒后灯会自动熄灭。
3 制作材料
4 设计电路
这里设计电路就不多讲了,我主要说说我的51的I/O口分配,电路可以自己设计去焊接。
其实整个作品对初学者来说也是不算难的
5 设计原理
5.1 原理一(人体感应)
我们每个人都会释放红外,所以我们采用一种红外热释电模块用来检测是否有人体靠近。当有人靠近时,红外热释电模块会产生高电平,当没有人时该模块会产生低电平,基于这个原理,我们可以将这两种信号分别送入单片机以控制灯的状态。
5.2 原理二(距离感应)
距离感应我们可以采用超声波模块,超声波模块会自动产生40KHZ的方波,当方波遇到障碍物时会返回,我们只需用单片机测出从发射方波到返回方波的时间就可以求出距离。测试距离=(时间*声速(340m/s))/2。
5.3 原理三(灯的亮度调节)
方法一:灯的亮度跟灯的电压有关,我们可以才用降压法来改变灯的亮度。那么如何实现自动降压?由于51单片机的I/O口只能固定输出5V的电压,所以我准备pwm来模拟电压以实现自动调节灯的亮度。
方法二:一个大的led是由许多小的led组成的,我们可以采用分块控制来实现亮度调节,当需要最亮光强时我们将led全部点亮,当需要弱亮光强时我们点亮部分led以实现亮度调节的功能。
这个作品我才用方法一来实现。
6 程序设计
#include<reg52.h>
#include<intrins.h> //包涵了_nop_()函数声明
typedef unsigned int unint;
typedef unsigned char unchar;
//TRIG 为控制端
sbit TRIG = P0^0; //超声波的 TRIG端 插在了P1.6口
//ECHO 为接收端
sbit ECHO = P0^1; //超声波的 ECHO端 插在了P1.7口
/*还有vcc,gnd 就直接插在了单片机 vcc 和gnd 端口了
*也可以将其插在I/O引脚中 将插 vcc的引脚置高电平,gnd置低电平*/
sbit IN1=P1^1;
sbit IN2=P1^2;
sbit key=P2^0;
unsigned int DGH,DGL,DDH,DDL,c;
unchar flag = 0; //标志定时器是否溢出
void delay_20us(); // 延时20ms
void init_time(); //初始化定时器的函数
/*********中断程序2****用于控制led亮度*********/
void timer2() interrupt 3 using 3 //中断3 T1溢出中断,使用工作组3
{ IN1=!IN1;if(IN1==0) // {IN1=0;TH1=DDH;TL1=DDL;}else{IN1=1;TH1=DGH;TL1=DGL;}
}
void off(void) // 关灯
{ TR1=0;IN1=0;
}
void play(void) //
{ c=700;DGH=(65535-c)/256;DGL=(65535-c)%256;DDH=(65535-(2000-c))/256;DDL=(65535-(2000-c))%256; TR1=1;
}
void play1(void) //
{ c=500;DGH=(65535-c)/256;DGL=(65535-c)%256;DDH=(65535-(2000-c))/256;DDL=(65535-(2000-c))%256; TR1=1;
}
void play2(void) //
{ c=300;DGH=(65535-c)/256;DGL=(65535-c)%256;DDH=(65535-(2000-c))/256;DDL=(65535-(2000-c))%256; TR1=1;
}
void play3(void) //
{ c=100;DGH=(65535-c)/256;DGL=(65535-c)%256;DDH=(65535-(2000-c))/256;DDL=(65535-(2000-c))%256; TR1=1;
}
void init() // 初始化函数
{ TMOD=0x11; // 设置T1,T2定时器工作方式 ET0=1;ET1=1; EA=1; // 打开总开关 TR0=0; // 关闭T0计时器IN2=0;TR1=1; // 打开T1定时器c=500;
}
/*************程序主函数**********************/
void main()
{unint time_data,out_TH0,out_TL0;init();TRIG = 0; // 先给控制端初始化为0while(1){if (key==1){init_time(); //初始化定时器flag = 0; //置溢出标志位为0//控制口发一个10US 以上的高电平TRIG = 1; delay_20us();TRIG = 0;//等待接收端出现高电平while(!ECHO);TR0 = 1; //启动计时器 开始计时while(ECHO); //等待高电平结束TR0 = 0; //关闭低电平out_TH0 = TH0; //取定时器的值out_TL0 = TL0;out_TH0 <<= 8; //右移8位 time_data = out_TH0 | out_TL0; //合并为16位的值 time_data /= 58; // 微秒/58 = 厘米/* 为什么微秒/58 = 厘米* Y米 = (X秒 * 344) 2* X秒 = (2 * Y米) / 344X秒 = 0.0058*Y米* 厘米 = 微秒/58 */if((time_data>=10)&&(time_data<=40)){play();}else if((time_data>=41)&&(time_data<=60)){play1();}else if((time_data>=61)&&(time_data<=80)){play2();}else if((time_data>=81)&&(time_data<=110)){play3();}}else if (key==0)off();}
}
/***********以下全为控制超声波需要的函数**************/void timer0() interrupt 1 //中断函数
{flag=1; //溢出标志位置1
}
void init_time()
{TH0 = 0; //装初值0TL0 = 0;TF0 = 0; //中断溢出标志位ET0 = 1; //开定时器中断
}
void delay_20us() //延时20us
{_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}
7 成品模型展示
整体图
主控电路
灯的电路
点亮效果
无包装,原生态,由于演示视频较大,这里就不上传了。
总结
为什么要用51?其实51的电路很好设计,现在主流的控制器一般都是STM32,但32的电路包括32最小系统都不好焊接,所以选用51。周4刚好我只有一节课,整个作品从设计电路到程序编写,到成品完成只用了半天时间,所以这个作品适合初学者去DIY。小半天就好了,51其实还挺好玩的。