智能垃圾桶/zh
概述
用距离测量传感器,在可测量的范围内,感受人体的接近动作,将采集到的红外的强弱会影响它自己阻值,从而改变输出的电压值。处理器通过判断输出的电压值,决定垃圾桶是否开启、开启的方向,从而用以接收垃圾。 材料清单
实验原理
sharp 2y0a21型号的测量传感器,为基于PSD的距离传感器。通过自身电路中热电阻感受外接环境中温度的变化阻值,从而改变传感器两端的电压。但是热电阻的感受温度的变化测量距离有一定的范围,sharp 2y0a21型号的测量距离为10~80cm。在0~8cm左右的距离范围内与距离成正比非线性关系,在10~80cm的距离范围内成反比非线性的关系,平均消耗约为30mA,反应时间约为5ms,并且对背景及温度的适应性较强。有效的测量角度大于40度,输出信号为模拟电压。
舵机是船舶上的一种大甲板机械。舵机的大小由外舾装按照船级社的规范决定,选型时主要考虑扭矩大小。在航天方面,舵机应用广泛。航天方面,导弹姿态变换的俯仰、偏航、滚转运动,都是靠舵机相互配合完成的。舵机在许多工程上都有应用,不仅限于船舶。 舵机主要是由外壳、电路板、无核心马达、齿轮与位置检测器所构成。其工作原理是由接收机发出讯号给舵机,经由电路板上的 IC判断转动方向,再驱动无核心马达开始转动,透过减速齿轮将动力传至摆臂,同时由位置检测器送回讯号,判断是否已经到达定位。 MG996R最大旋转角度为180度,在编写程序代码时,旋转的角度范围为(0~180度)。
距离测量传感器感应两侧的红外线的强度,将感应到的数值传送到核心芯片上,核心芯片通过处理该数据,确定舵机旋转的角度,从而确定垃圾箱是否开门,如果开门开哪侧的门。因为舵机的旋转角度为0~180度,所以最好将平衡位置放在舵机旋转的角度中间。 垃圾箱安装的原理图
距离测量传感器 距离测量传感器的特性
MG996R舵机 MG996R舵机的线路说明,如图所示 舵机(MG996R)的特性
Microduino servo-cin的连线管脚 在程序中,定义舵机的引脚,对应Microduino-Sensorhub/zh一个插槽(一个插槽中有两个管脚)中的一个管脚,离板子较远的一端为数字较小的管脚。 文档调试过程
将Microduino Core、Microduino USBTTL堆叠在一起.用数据线将写好的程序通过Microduino USBTTL上传到Microduino Core上。 注意:最好不要将所有模块堆叠在一起之后再上传程序 打开程序,点击程序编译,编译成功后,在【工具】中选择好【端口】、【板】和【处理器】,选择好【板】和【处理器】之后,点击上传即可 板卡的选择 处理器的选择 端口的选择
将Microduino-Duo-v/zh用螺丝钉固定在垃圾桶上
叠加模块,将Microduino-Core/zh、Microduino-USBTTL/zh、Microduino-BM/zh、Microduino-Duo-v/zh、Microduino-Sensorhub/zh模块叠加在一起(无顺序差别)
安装测量传感器 将测量传感器安放在垃圾箱的两边,固定时要和垃圾箱的侧壁有一定的夹角(45度左右)。
将一字臂安装在垃圾箱的门上
连接线路 Microduino-Sensorhub/zh板需要连接的插槽的的引脚说明。
模块左边的测量传感器接A0,右边的接A2。舵机和Microduino servo-cin/zh连好后,连接线接到Microduino-Sensorhub/zh板的D4插槽
连接垃圾箱门,寻找舵机旋转的中间位置
安装舵机 将舵机的旋转轴旋转到中间位置(防止安装上只能向一个方向旋转)。垃圾桶的门为旋转开关,将舵机安放、固定在旋转轴上,让舵机旋转带动垃圾桶门的旋转
系统测试 通过数据线连接电脑和USB板的USB接口,测试放在两边的测量传感器,修改程序中舵机的选装的角度,调整舵机旋转的角度和方向,使其可以完成用人体感应控制垃圾桶的打开方向。 调试舵机方向的代码函数为myservo.write(),在函数括号内设定舵机旋转的角度即可。 注意:程序中,更改舵机角度时,不可写成负值。 程序说明
#define sensor_vol 300 //sensor_vol core输入(传感器输出)大于这个值:手靠近;小于这个值:没有手
#define servo_vol 93 //舵机旋转到的角度
/*为什么是300?
红外测距传感器输出量为一个0~5V之间的模拟量。测距越近,电压越高。
该模拟量(0~5V)被输入到core模块的A0,A2口(两个模拟输入口)。通过模数转换器(ADC)转换成计算机能识别的量,这个量叫做数字量。数字量为0~1023(5V<-->1023,不同的ADC会有不同的测量范围)
换算关系:
输入电压 | 计算机内部用的数字量
V | V*1023/5.
经实测红外传感器的输出电压在
没有手靠近时为0.3V,对应数字量是,0.3*1023/5=61.38
有手靠近时为1.6V,对应数字量是,1.6*1023/5=61.38=327.36
选择两者中间的一个数作为区别有没有手靠近的标准。
思考,如果换成200可以么?试一试
*/
int potpin[2] =
{
A0, A2
}; //定义传感器的输入管脚
#include "key.h"
#include <Servo.h> //既然用到了舵机,就要加载舵机的库文件,该库文件里包含了对于舵机的各种操作指令。比如myservo.write()
Servo myservo; // create servo object to control a servo
int val[2] = {0, 0}; // variable to read the value from the analog pin
//数组,用来存放两个模拟输入口的输入值(已经被转换为0~1023之间的数字值)
boolean sta[2] =
{
false, false
};//状态标志位。false表示盖子合上了,true表示盖子打开了
//之所以要用两个元素是因为盖子可以两面打开
void setup()
{
Serial.begin(9600);//设置串口波特率,用于和电脑进行串口通信
pinMode(potpin[0], INPUT);
pinMode(potpin[1], INPUT);
myservo.attach(4); //设置舵机控制管脚为D4
myservo.write(servo_vol); // //舵机旋转到servo_vol的角度 垃圾桶盖子合上
key_init();
}
void loop()
{
//------0---------------------------------------------------------------
val[0] = analogRead(potpin[0]); //读入传感器0的输出电压 reads the value of the potentiometer (value between 0 and 1023)
if((val[0] > sensor_vol) && (sta[0] == false)) //当该电压>阈值(有手接近垃圾箱)并且此时盖子是关着的时候,正向打开盖子
{
Serial.println("sta[0]!");
Serial.println("UP");
myservo.write(180); // sets the servo position according to the scaled value
sta[0] = true;
delay(1000);
}
if((val[0] < sensor_vol) && (sta[0] == true)) //当该电压<阈值(没有手接近垃圾箱)并且此时盖子是开的时候,合上盖子
{
Serial.println("DOWN");
myservo.write(servo_vol);
sta[0] = false;
delay(1000);
}
/*为什么要加入sta?
loop函数是不断循环执行的。如果只是“手遮住了传感器就转”,那当手一直遮挡住传感器的时候,盖子就会不断得翻转。
所以我们的逻辑必须是“手遮住了传感器”并且“此时盖子是合上的”时候,才转。
*/
//------------------------------------
val[1] = analogRead(potpin[1]); // reads the value of the potentiometer (value between 0 and 1023)
if((val[1] > sensor_vol) && (sta[1] == false))
{
Serial.println("sta[1]!");
Serial.println("UP");
myservo.write(0); // sets the servo position according to the scaled value
sta[1] = true;
delay(1000);
}
if((val[1] < sensor_vol) && (sta[1] == true))
{
Serial.println("DOWN");
myservo.write(servo_vol);
sta[1] = false;
delay(1000);
}
}
#include "arduino.h"
boolean key_status[NUM_DIGITAL_PINS]; //按键
boolean key_cache[NUM_DIGITAL_PINS]; //检测按键松开缓存
void key_init()
{
for(int a = 0; a < NUM_DIGITAL_PINS; a++)
{
key_status[a] = LOW;
key_cache[a] = HIGH;
}
}
boolean key_get(int _key_pin, boolean _key_type)
{
key_cache[_key_pin] = key_status[_key_pin]; //缓存作判断用
key_status[_key_pin] = analogRead(_key_pin) > sensor_vol; //触发时
switch(_key_type)
{
case 0:
if(!key_status[_key_pin] && key_cache[_key_pin]) //按下松开后
return true;
else
return false;
break;
case 1:
if(key_status[_key_pin] && !key_cache[_key_pin]) //按下松开后
return true;
else
return false;
break;
}
}
视频 |