C51之智能感应垃圾桶

文章目录

    • 前期准备:
    • 超声波模块
    • SG90舵机
    • 1、概念
    • 舵机代码
    • 震动检测模块
    • 蜂鸣器
    • 定时器和中断
    • 项目实物
    • 项目代码:

前期准备:

超声波模块

简介:
超声波传感器模块上面通常有两个超声波元器件,一个用于发射,一个用于接收。

硬件
电路板上有4个引脚:

VCC(正级)
Trig(触发)
Echo(回应)
GND(接地-负极)

主要参数:

工作电压与电流:5V、15mA
感测距离:2~400cm
感测角度:不大于15°
被测物体的面积:不要小于50cm²,且尽量平整
具备温度补偿电路
在超声波模块的触发脚位输入10微秒以上的高电位,即可发射超声波,发射超声波之后,与接收到传回的超声波之前,“响应”脚位呈现高电位。因此,程序可以从“响应”脚位的高位脉冲持续时间,换算出被测物的距离。
超声波模块工作原理
超声波时序图

C51之智能感应垃圾桶_第1张图片

T(发波)

R(接受)

先给 Trig 引脚发送一个 10uS(微秒)的 TTL(高电平)

T就可以发波了

发出的是循环 8 个 40KHz 的脉冲

波发出去后,Echo 引脚就会一直维持高电平,也就是说波在空中传播的过程是一直维持高电平

那么就可以根据Echo 引脚的高电平维持时间,超声波在空气中的物理性质的传输速度,就可以算出障碍物跟发波点的距离

即超声波能在空气中1秒能跑多远,那么就可以通过Echo 引脚的高电平维持时间,换算距离了
C51之智能感应垃圾桶_第2张图片
代码测试(D5D6灯亮灭):

#include	"reg52.h"

sbit D5 = P3^7;
sbit D6 = P3^6;
sbit Trig = P1^5;
sbit Echo = P1^6;


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

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

//配置定时器1
void Timer1Init(void)		
{
	TMOD &= 0xF0;
	TMOD |= 0x10;
	TH1 = 0;
	TL1 = 0;
}

void startHc()
{
	Trig = 0;
	Trig = 1;
	Delay10us();
	Trig = 0;
}


double get_distance()
{
		double time;
		//定时器数据清零,以便下一次测距
		TH1 = 0;
		TL1 = 0;
	  //1.Trig,给Trig端口至少10us的高电平
		startHc();
		//2.echo由低电平跳转到高电平,表示开始发送波
		while(Echo == 0);
		//波发出去的那一下,开启定时器
		TR1 = 1;
		//3.由高电平跳转回店店铺,表示波回来了
		while(Echo == 1);
		//波回来的那一下,我们开始停止定时器
		TR1 = 0;
		//4.计算出中间经过多少时间
		time=(TH1 *256 +TL1)*1.085;//us为单位
		//5.距离=速度(340m/s)*时间/2
		return (time*0.017);

	
}


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

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



void main()
{
	
	double dis;
	
	Timer1Init();
	
	while(1){
		
		dis = get_distance();
		
		if(dis < 10){
			openStatusLight();
		}else{
			closeStatusLight();
		}
		
		
	
	}


}


SG90舵机

C51之智能感应垃圾桶_第3张图片
接线方法:
红-------------------------VCC
棕色----------------------GND
橙色----------------------信号线

C51之智能感应垃圾桶_第4张图片

1、概念

PWM 全称是 Pulse WidthModulation,也就是脉冲宽度调制

2、PWM信号图

3、频率
频率就是开关速度,把一次开关算作一个周期,那么频率就是 1 秒内进行了多少次开关

4、占空比
占空比就是一个周期内高电平时间和低电平时间的比例,一个周期内高电平时间越长占空比就越大,反之占空比就越小。占空比用百分之表示,如果一个周期内全是低电平那么占空比就是 0%,如果一个周期内全是高电平那么占空比就是100%。

舵机代码

#include	"reg52.h"

sbit sg90_con = P1^1;
int jd;
int cnt = 0;





void Timer0Init(void)		//500微秒@11.0592MHz
{
			//定时器时钟1T模式
	TMOD = 0x01;		//设置定时器模式
	TL0 = 0x33;		//设置定时初值
	TH0 = 0xFE;	//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0	= 1;   //打开定时器0中断
	EA = 1;		//打开总中断
}


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

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


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

	
	i = 3;
	j = 26;
	k = 223;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}







void main()
{
	Delay300ms();//让硬件稳定一下
	Timer0Init(); //初始化定时器
	cnt = 0;
	jd = 1;
	sg90_con = 1;
	
	//每隔两秒切换一次角度
	while(1){
		jd = 3;  //90度 1.5ms高电平
		cnt = 0;
		Delay2000ms();
		jd = 1; //0度
		cnt = 0;
		Delay2000ms();
	}


}

void TimeOHandler() interrupt 1
{
		
		cnt++;//统计爆表的次数
	
		//重新给初值
		TL0 = 0x33;		//设置定时初值
	  TH0 = 0xFE;
		
		if(cnt < jd){
			
			sg90_con = 1;
		}else{
			sg90_con = 0;
		}
	
		if(cnt == 40){//爆表40次,经过了20ms
			
			cnt = 0;
			sg90_con = 1;
			
		}
		
}




	

震动检测模块

型号:SW-18010P

产品特点
1、采用本公司生产的高灵敏度震动开关,默认用SW-18010P震动传感器

2、比较器输出,信号干净,波形好,驱动能力强,超过15mA

3、工作电压3.3V-5V

4、输出形式:数字开关量输出(0和1)

5、设有固定螺栓孔,方便安装

6、小板PCB尺寸:3.2cm x 1.4cm

7、使用宽电压LM393比较器

接线
1、VCC:接电源正极

2、GND:接电源负极

3、DO:数字量信号输出

4、AO:用此震动传感器此功能无效

注意:电源极性不能反接、否则有可能将芯片烧坏、开关信号指示灯亮时输出低电平、不亮输出高电平、信号输出的电平接近于电源电压

使用方法
1、产品不震动时,震动开关呈断开状态,输出端DO输出高电平,绿色指示灯不亮;

2、产品震动时,震动开关瞬间导通,输出端DO输出低电平,绿色指示灯亮;

3、输出端可以与单片机直接相连,通过单片机来检测高低电平,由此来检测环境是否有震动,起到报警作用

片机直接相连,通过单片机来检测高低电平,由此来检测环境是否有震动,起到报警作用

4、电位器可以调整模块的检测灵敏度

蜂鸣器

定时器和中断

定时器和中断

项目实物

C51之智能感应垃圾桶_第5张图片

项目代码:

#include	"reg52.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 mark_vibrate = 0;
char jd;
char cnt = 0;
char jd_bak;

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

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


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

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


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

	i = 2;
	while (--i);
}
//配置定时器0
void Timer0Init(void)		
{
			//定时器时钟1T模式
	TMOD &= 0xF0;
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x33;		//设置定时初值
	TH0 = 0xFE;	//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0	= 1;   //打开定时器0中断
	EA = 1;		//打开总中断
}

//配置定时器1
void Timer1Init(void)		
{
	TMOD &= 0x0F;
	TMOD |= 0x10;
	TH1 = 0;
	TL1 = 0;
}

void startHc()
{
	Trig = 0;
	Trig = 1;
	Delay10us();
	Trig = 0;
}


double get_distance()
{
		double time;
		//定时器数据清零,以便下一次测距
		TH1 = 0;
		TL1 = 0;
	  //1.Trig,给Trig端口至少10us的高电平
		startHc();
		//2.echo由低电平跳转到高电平,表示开始发送波
		while(Echo == 0);
		//波发出去的那一下,开启定时器
		TR1 = 1;
		//3.由高电平跳转回店店铺,表示波回来了
		while(Echo == 1);
		//波回来的那一下,我们开始停止定时器
		TR1 = 0;
		//4.计算出中间经过多少时间
		time=(TH1 *256 +TL1)*1.085;//us为单位
		//5.距离=速度(340m/s)*时间/2
		return (time*0.017);

	
}


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

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

void initSG90_0()
{
	jd = 1;
	cnt = 0;
	sg90_con = 1;
}

void openDusbin()
{
	//开盖
	char n;
	jd = 3;
	
	if(jd_bak != jd){
		cnt = 0;
		beep = 0;
		for(n=0;n<2;n++)
		Delay150ms();
		beep = 1;
		Delay2000ms();
	}
	
	jd_bak = jd;
	

}


void closeDusbin()
{
	//关盖
	jd = 1;//0度
	jd_bak = jd;
	cnt = 0;
	Delay150ms();
	
}

void EX0_Init()
{
	EX0 = 1;
	IT0 = 0;
}

void main()
{
	
	double dis;
	
	Timer0Init();
	Timer1Init();
	EX0_Init();
	initSG90_0();
	
	while(1){
		//超声波测距
		dis = get_distance();
		
		if(dis < 10 || SW1 == 0 || mark_vibrate == 1){
			//开盖,灯状态,D5亮
			
			openStatusLight();
			openDusbin();
			mark_vibrate = 0;
		}else{
			//关盖,灯状态,D5灭
			closeStatusLight();
			closeDusbin();
		}
		
		
	
	}


}


void TimeOHandler() interrupt 1
{
		
		cnt++;//统计爆表的次数
	
		//重新给初值
		TL0 = 0x33;		//设置定时初值
	  TH0 = 0xFE;
		
		if(cnt < jd){
			
			sg90_con = 1;
		}else{
			sg90_con = 0;
		}
	
		if(cnt == 40){//爆表40次,经过了20ms
			
			cnt = 0;
			sg90_con = 1;
			
		}
		
}

void Ex0_Handler() interrupt 0 //设置外部中断
{
	mark_vibrate = 1;
}

	

你可能感兴趣的:(C51,单片机,嵌入式硬件)