智能垃圾桶/zh

来自Microduino Wikipedia
502748957@qq.com讨论 | 贡献2015年10月13日 (二) 06:21的版本
跳转至: 导航搜索

概述

  • 项目名称:Microduino智能垃圾桶
  • 目的:垃圾桶自动开合
  • 难度:中
  • 耗时:2小时
  • 制作者:
  • 简介:

用距离测量传感器,在可测量的范围内,感受人体的接近动作,将采集到的红外的强弱会影响它自己阻值,从而改变输出的电压值。处理器通过判断输出的电压值,决定垃圾桶是否开启、开启的方向,从而用以接收垃圾。

材料清单

  • Microduino设备
模块 数量 功能
Microduino-Core/zh 1 核心板
Microduino-USBTTL/zh 1 下载程序
Microduino-BM/zh 1 供电
Microduino-Duo-v/zh 1 连接垃圾桶
Microduino-Sensorhub/zh 1 与传感器和舵机相连
  • 其他设备
名称 数量 功能
舵机(MG996R) 1 开启、关闭垃圾桶
Microduino servo-cin 1 连接舵机和hub板
sharp 2y0a21 1 在10cm~80cm距离检测红外线
电池 1 供电

实验原理

  • 距离测量传感器

sharp 2y0a21型号的测量传感器,为基于PSD的距离传感器。通过自身电路中热电阻感受外接环境中温度的变化阻值,从而改变传感器两端的电压。但是热电阻的感受温度的变化测量距离有一定的范围,sharp 2y0a21型号的测量距离为10~80cm。在0~8cm左右的距离范围内与距离成正比非线性关系,在10~80cm的距离范围内成反比非线性的关系,平均消耗约为30mA,反应时间约为5ms,并且对背景及温度的适应性较强。有效的测量角度大于40度,输出信号为模拟电压。

  • 舵机(MG996R)

舵机是船舶上的一种大甲板机械。舵机的大小由外舾装按照船级社的规范决定,选型时主要考虑扭矩大小。在航天方面,舵机应用广泛。航天方面,导弹姿态变换的俯仰、偏航、滚转运动,都是靠舵机相互配合完成的。舵机在许多工程上都有应用,不仅限于船舶。 舵机主要是由外壳、电路板、无核心马达、齿轮与位置检测器所构成。其工作原理是由接收机发出讯号给舵机,经由电路板上的 IC判断转动方向,再驱动无核心马达开始转动,透过减速齿轮将动力传至摆臂,同时由位置检测器送回讯号,判断是否已经到达定位。 MG996R最大旋转角度为180度,在编写程序代码时,旋转的角度范围为(0~180度)。

  • 总体结构

距离测量传感器感应两侧的红外线的强度,将感应到的数值传送到核心芯片上,核心芯片通过处理该数据,确定舵机旋转的角度,从而确定垃圾箱是否开门,如果开门开哪侧的门。因为舵机的旋转角度为0~180度,所以最好将平衡位置放在舵机旋转的角度中间。 垃圾箱安装的原理图

Smartlitterbox.png
  • 主要传感器

距离测量传感器 距离测量传感器的特性

  • 可测量的范围:10~80cm
  • 消耗电流:标注值30mA
  • 电源电压:4.5V~5.5V
  • 检测到该范围内的红外线的强度,其大小通过电压值表示出来。
Distancesensor.jpg

MG996R舵机 MG996R舵机的线路说明,如图所示

舵机(MG996R)的特性

  • 旋转角度:180度
  • 工作电压:4.8V-7.2V
  • 空载工作电流: 120mA
  • 堵转工作电流: 1450mA
  • 扭力:4.8V@13kg-cm ,6.0V@15kg-cm
ServoMG996R.png

Microduino servo-cin的连线管脚

Microduino servo-cin.png

在程序中,定义舵机的引脚,对应Microduino-Sensorhub/zh一个插槽(一个插槽中有两个管脚)中的一个管脚,离板子较远的一端为数字较小的管脚。

文档

调试过程

  • 下载程序:

将Microduino Core、Microduino USBTTL堆叠在一切,如下[图5-1]所示。用数据线将写好的程序通过Microduino USBTTL上传到Microduino Core上。 注意:最好不要将所有模块堆叠在一起之后再上传程序

Download1.jpg

打开程序,点击程序编译,编译成功后,在【工具】中选择好【端口】、【板】和【处理器】,选择好【板】和【处理器】之后,点击上传即可 板卡的选择

Download2.jpg

处理器的选择

Download3.jpg

端口的选择

Download4.jpg
  • 搭建:
  • 步骤1

Microduino-Duo-v/zh用螺丝钉固定在垃圾桶上

Litter1.jpg
  • 步骤2

叠加模块,将Microduino-Core/zhMicroduino-USBTTL/zhMicroduino-BM/zhMicroduino-Duo-v/zhMicroduino-Sensorhub/zh模块叠加在一起(无顺序差别)

Litter2.jpg
  • 步骤3

安装测量传感器 将测量传感器安放在垃圾箱的两边,固定时要和垃圾箱的侧壁有一定的夹角(45度左右)。

Litter3.jpg
  • 步骤4

将一字臂安装在垃圾箱的门上

Litter5.jpg
  • 步骤5

连接线路 Microduino-Sensorhub/zh板需要连接的插槽的的引脚说明。

Litter6.png
  • 步骤6

模块左边的测量传感器接A0,右边的接A2。舵机和Microduino servo-cin/zh连好后,连接线接到Microduino-Sensorhub/zh板的D4插槽

Litter7.jpg
  • 步骤7

连接垃圾箱门,寻找舵机旋转的中间位置

Litter8.jpg
Litter9.jpg
  • 步骤8

安装舵机 将舵机的旋转轴旋转到中间位置(防止安装上只能向一个方向旋转)。垃圾桶的门为旋转开关,将舵机安放、固定在旋转轴上,让舵机旋转带动垃圾桶门的旋转

Litter10.jpg
  • 步骤9

系统测试 通过数据线连接电脑和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); 
    } 
} 
  • key.h
#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; 
    } 
} 

视频