51单片机实现智能感应垃圾桶

智能感应垃圾桶

功能描述
检测靠近时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
发生震动时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
按下按键时,垃圾桶自动开盖并伴随滴一声,2秒后关盖

硬件说明
SG90舵机,超声波模块,震动传感器,蜂鸣器
接线说明
舵机控制口 P1.1;超声波Trig接 P1.5 ,Echo接 P1.6 ;蜂鸣器接 P2.0 口; 震动传感器接 P3.2`口(外部
中断0)

开发步骤:

  1. 舵机和超声波代码整合
    舵机用定时器0
    超声波用定时器1
    实现物体靠近后,自动开盖,2秒后关盖
  2. 查询的方式添加按键控制
  3. 查询的方式添加震动控制
  4. 使用外部中断0配合震动控制

代码如下:

#include "reg52.h"
#include "Intrins.h"

//智能感应垃圾桶
sbit D5   		= P3^7;
sbit D6   		= P3^6;
sbit Trig 		= P1^5;
sbit Echo     = P1^6;
sbit sg90_con = P1^1;
sbit sw1			= P2^1;
sbit vibrate 	= P3^2;
sbit beep 		= P2^0;

//用char定义时下面用的时候只需8位就够了,节省单片机存储空间
char count = 0;
char angle ;//定义舵机角度
char mark_vibrate = 0;
char angle_back;

void Delay2000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 15;
	j = 2;
	k = 235;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void Delay150ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 2;
	j = 13;
	k = 237;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}



void Delay10us()		//@11.0592MHz
{
	unsigned char i;

	i = 2;
	while (--i);
}

void Time0Init()
{
	//1. 配置定时器0工作模式位16位计时
	TMOD &= 0xF0;
	TMOD |= 0x01;
	//2. 给初值,定一个0.5ms出来
	TL0=0x33;
	TH0=0xFE;
	//3. 开始计时
	TR0 = 1;
	TF0 = 0;
	//打开定时器0的中断
	ET0 = 1;
	//打开中断总开关
	EA = 1;
}

void Time1Init()
{
	TMOD &= 0x0F;		//设置定时器1模式为16位
	TMOD |= 0x10;		
	
	TL1 = 0;//设置定时器1从0开始数数,不着急启动定时器
	TH1 = 0;
	
	TF1 = 0;
	

}


void startHC()
{
	Trig = 0;
	Trig = 1;
	Delay10us();
	Trig = 0;

}

double get_distance()
{
	double time;//时间
	
	
	TL1 = 0;//定时器数据要清零,以便下一次测距
	TH1 = 0;
	
	//1、Trig,给Trig端口至少10us的高电平,提醒超声波准备发波
	startHC();
	
	//2、Echo,从低变为高,表示开始发波
	while(Echo == 0);
	
	//2.1 波发出去的时候,启动定时器
	TR1 = 1;//开始计时
	
	//3、Echo,由高变为低,表示接收到返回来的波
	while(Echo == 1);
	
	//3.1 波回来的时候,停止定时器
	TR1 = 0;//停止定时器
	
	//4、计算中间经过的时间
	time = (TH1 * 256 + TL1) * 1.085;//us为单位
	
	//5、计算距离 距离= (340m/s) * (时间)/2
	//  340m/s=34cm/ms=0.034cm/us 
	return (0.017 * time);

}

void initSG90_0()
{
	angle = 1;//初始化角度为0度,0.5ms的高电平
	count = 0;//初始化周期
	sg90_con = 1;//一上电就给sg90舵机一个高电平
}

void openStatusLight()
{
		D5 = 0;
		D6 = 1;
}

void closeStatusLight()
{
		D5 = 1;
		D6 = 0;
}

void openDusbin()
{
		angle = 3;//90度,开盖
		if(angle_back != angle){//上一次的角度不等于现在才执行
			count = 0;
			beep 	= 0;
			Delay150ms();//蜂鸣器响300ms
			Delay150ms();
			beep  = 1;
			Delay2000ms();
		}
		angle_back = angle;
}

void closeDusbin()
{
		angle = 1;//0度,关盖
		count = 0;
		angle_back = angle;
		Delay150ms();
}


void EX0_Init()
{
	EX0 = 1;		//打开外部中断0
	IT0 = 0;		//低电平触发外部中断0
}

void main()
{
	
	double dis;//距离
	Time0Init();//初始化定时器0
	Time1Init();//初始化定时器1
	EX0_Init();//打开外部中断0
	initSG90_0();//舵机的初始位置
	
	while(1){
		
		dis = get_distance();//超声波测距
		
		if(dis < 10 || sw1 == 0 || mark_vibrate == 1){//如果小于10cm,或者sw1被按下,或者震动产生的外部中断
			openStatusLight();//开盖,D5亮
			openDusbin();
			mark_vibrate = 0;//软件恢复mark标记
		}else{
			closeStatusLight();//关盖,D6亮
			closeDusbin();
		} 
	
	
	}
}


void Time0Handler() interrupt 1//定时器0中断
{
	
	count++;//统计爆表的次数
	TL0 = 0x33;//重新给初值,使其重新计算0.5ms
	TH0 = 0xFE;
	
	//控制PWM波形
	if(count < angle){
		sg90_con = 1;

}else{
	sg90_con = 0;
}
			
if(count == 40){//爆表了,给变量加1,加个40次就是20ms
		count = 0;//当count为40时,表示20ms,此时让count=0,重新计算下一次的20ms,20ms为舵机一个周期
		sg90_con = 1;
		
}

}

void EX0Handler() interrupt 0//外部中断0
{
		mark_vibrate = 1;//收到震动传感器信号改变标记
}

由于震动感应器的信号不稳定,有时感受到震动也导致单片机没反应过来进行开盖,所以直接给它加一个外部中断实现让震动感应开盖变得灵敏

结果图稍显丑陋,如下:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 9
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值