智能电动门插销-Arduino中文社区 - Powered by Discuz! Archiver

星空太黑 发表于 2016-12-7 21:06

智能电动门插销

本帖最后由 星空太黑 于 2016-12-7 21:06 编辑

    原创项目,转发请注明作者本人。水平有限,高手勿喷。

项目:智能电动门插销
制作人:星空
制作背景:

      步入大学,一直觉得普通门插销只能单侧使用,而且别人敲门还要下床给别人开门很不方便,尤其在冬天(懒惰是科技进步的源泉),所以想做一个电动门插销
制作所需材料及成本:
      所需工具(不计入总成本):
热胶枪(20RMB),热胶枪胶棒(1RMB),厚双面胶(2RMB),桌面级3D打印机(1000RMB),剥线钳(15RMB),减线钳(15RMB),笔记本电脑(画3D模型用的),黄油(用来减小门插销摩擦阻力),绝缘胶布
         所需材料:
arduino nano一块(控制核心,可编程)
杜邦线 若干
中号面包板一块
面包板跳线 若干
20号导线 若干(用于供电)
手机充电器(提供5v电源)
USB手机充电线(要质量好一些的)
9g舵机(用来推动门插销)
3mm直径螺丝螺母若干(需要20对一下)
原理:
通过对arduino编程控制一路舵机转到指定角度,通过一定的机械结构传动,推动门插销实现锁门开门的功能,额外功能:通过红外接收管接收遥控器指令,检测触摸导线上的电容值来实现对门锁的触控。(延伸:通过读卡机读取校园卡的id,当为本宿舍id时打开或关闭门插销,当检测到不是本宿舍id时不做反应)
设计过程:
3D模型的设计用了两周时间,想过好几种方案,本来想用一种在门角用长条零件别住的方案,但是因为考虑到安全性最后还是选择直接用舵机(电机+减速齿轮箱+角度反馈控制)控制门插销的方案,因为这样不会降低门的安全性,因为考虑到arduino和舵机共同供电,电流和功耗的限制,所以选用9g舵机,但是9g舵机的力量很小,所以想了好久最后觉得用杠杆结构既简单又有效。
          电源方案本来打算用电池供电,但计算后发现电池只能待机两天就需要充电,所以选择用手机充电器提供电源
          之后装上红外接收管,把遥控器按键的对应的键值编入程序,使他具有可遥控功能,装上射频卡模块,用来读取校园卡
制作过程:
1.首先是测量舵机的尺寸,并构想它的3D模型,设计机械的结构,然后画3D模型,我用的solidwork,上网查资料和图书馆借书自学了一周,画简单模型没有问题了





2把他们3D打印出来:

把那些传动装置用螺丝拼装好,因为在画模型的时候就把每个活动和不活动的孔的直径都设计好了,所以直接就可以用螺丝组装,把那个舵机比着凹槽放进去用热胶抢固定,就会达到上图的效果
再把面包板粘在外壳的凹槽内插上arduino nano芯片:

将舵机和红外接收管的线接好:

然后就组装好了,为了防止导线脱落,用热熔胶适当固定,尤其是电源线,将背面贴上厚双面胶

然后找到合适的位置贴在门上连接好电源线:

电源线为usb供电,把usb线剪开,会看到里面有红黑绿黄四条线,红和黑两根线分别接出,用20号导线接在面包板上,注意正负极不要接反,
到此,硬件搭建好了,

程序编写:


此程序为好几个程序组合而成,参考程序有:
极客工坊知识库:http://wiki.geek-workshop.com/doku.php
Arduino教程汇总贴(2016.10.6更新):http://www.arduino.cn/thread-1066-1-1.html
Arduino教程(提高篇)——舵机的驱动:http://www.arduino.cn/thread-1038-1-1.html
Arduino教程(提高篇)——红外遥控(接收篇) :http://www.arduino.cn/thread-1220-1-1.html
用arduino直接检测电容值:一个不用外围电路的简易触摸传感器:
http://www.geek-workshop.com/forum.php?mod=viewthread&tid=3335&highlight=%B4%A5%C3%FE
我组合完的程序放在2楼

程序设计:

为了使这么多的程序可以同时兼顾运行,我的方法是随时更新时间,用millis()函数,然后每一个需要延时的函数不用delay(),而是在现有时间上加上延时时间记录在一个变量里,然后在自己定义的时间函数用if函数,检测是否到达这个时间,到了就执行。

就此就完成了,但是根据实际情况还需要不断优化,修改程序,比如触摸开门立即打开,触摸关门延时关闭因为触摸时可能门还没有关到位,还有可能断电从启时是希望它锁门还是开门,这在程序中都是需要优化的。

刷卡功能等做好后再更新此贴
视频刚上传到优酷,过几天更新










星空太黑 发表于 2016-12-7 21:08

#include <IRremote.h>
#include <Servo.h>

String comdata = "";//串口接收到的变量
int RECV_PIN = 11;//红外接收引脚
IRrecv irrecv(RECV_PIN);//初始化红外接收
decode_results results;

Servo myservo;//创建一个舵机控制对象
int pos = 0;    // 该变量用与存储舵机角度位置
int chumo = 0;//此变量用来储存短时间内引线被触发的次数
//int ledPin = 5;//触摸引线所在端口位置
int capval=0;//触摸引线电容值
int men = 0;//此变量用来记录门的开关状态,0为关,1为开
/*~~~~~~~~~~~~~~~~~~~~~~~~~~华丽的分割线~~~~~~~~~~~~~~~~~~~~~~~~~~ */
//时间变量
unsigned long duoji = 0;//舵机控制延时,超过后断开舵机
unsigned long timenow=0;
void setup()
{
        Serial.begin(9600);
        myservo.attach(9);// 该舵机由arduino第九脚控制
        irrecv.enableIRIn();
       
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~华丽的分割线 ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
void loop()
{
        shijian();
        hongwai();
        //chuankou();
        chumopanduan();
        }
void hongwai()
{
        if (irrecv.decode(&results))
        {
                Serial.println(results.value);
                if (results.value == 16753245)      //确认接收到的第一排按键1的编码,此码是预先读出来的按键编码。
                {
                        guanmen();

                }
                else if (results.value == 16769565)
                {
                        kaimen();
                }
                irrecv.resume(); // 接收下一个值
        }
}
void guanmen()
{
        myservo.attach(9);
        myservo.write(175);
        duoji = timenow + 4000;
        men = 0;
}
void kaimen()
{
        myservo.attach(9);
        myservo.write(65);
        duoji = timenow + 1500;
        men = 1;
}
void chuankou()
{
        while (Serial.available() > 0)
        {
                comdata += char(Serial.read());
                delay(2);
        }
        if (comdata.length() > 0)
        {
                Serial.println(comdata);
                if (comdata == "kaimen")
                {
                        delay(100);
                        kaimen();
                        Serial.println(comdata);
                }
                else if (comdata == "guanmen")
                {
                        delay(100);
                        guanmen();
                        Serial.println(comdata);
                }
                comdata = "";
        }
}
void shijian()
{
        //读取当前时间
        timenow = millis();
        //舵机延时检测
        if (duoji != 0)
        {
                if (timenow >= duoji)
                {
                        duoji = 0;
                        myservo.detach();
                }
        }

}
uint8_t readCapacitivePin(int pinToMeasure) {
        // Variables used to translate from Arduino to AVR pin naming
        volatile uint8_t* port;
        volatile uint8_t* ddr;
        volatile uint8_t* pin;
        // Here we translate the input pin number from
        // Arduino pin number to the AVR PORT, PIN, DDR,
        // and which bit of those registers we care about.
        byte bitmask;
        port = portOutputRegister(digitalPinToPort(pinToMeasure));
        ddr = portModeRegister(digitalPinToPort(pinToMeasure));
        bitmask = digitalPinToBitMask(pinToMeasure);
        pin = portInputRegister(digitalPinToPort(pinToMeasure));
        // Discharge the pin first by setting it low and output
        *port &= ~(bitmask);
        *ddr |= bitmask;
        delay(1);
        // Make the pin an input with the internal pull-up on
        *ddr &= ~(bitmask);
        *port |= bitmask;

        // Now see how long the pin to get pulled up. This manual unrolling of the loop
        // decreases the number of hardware cycles between each read of the pin,
        // thus increasing sensitivity.
        uint8_t cycles = 17;
        if (*pin & bitmask) { cycles = 0; }
        else if (*pin & bitmask) { cycles = 1; }
        else if (*pin & bitmask) { cycles = 2; }
        else if (*pin & bitmask) { cycles = 3; }
        else if (*pin & bitmask) { cycles = 4; }
        else if (*pin & bitmask) { cycles = 5; }
        else if (*pin & bitmask) { cycles = 6; }
        else if (*pin & bitmask) { cycles = 7; }
        else if (*pin & bitmask) { cycles = 8; }
        else if (*pin & bitmask) { cycles = 9; }
        else if (*pin & bitmask) { cycles = 10; }
        else if (*pin & bitmask) { cycles = 11; }
        else if (*pin & bitmask) { cycles = 12; }
        else if (*pin & bitmask) { cycles = 13; }
        else if (*pin & bitmask) { cycles = 14; }
        else if (*pin & bitmask) { cycles = 15; }
        else if (*pin & bitmask) { cycles = 16; }

        // Discharge the pin again by setting it low and output
        // It's important to leave the pins low if you want to
        // be able to touch more than 1 sensor at a time - if
        // the sensor is left pulled high, when you touch
        // two sensors, your body will transfer the charge between
        // sensors.
        *port &= ~(bitmask);
        *ddr |= bitmask;

        return cycles;
}//触摸函数
void chumopanduan()
{
        capval = readCapacitivePin(5);
        if (capval >= 8)
        {
                if (chumo >= 20)
                {
                        if (men == 0)
                                kaimen();
                        else if (men == 1)
                                guanmen();
                }
                chumo = 0;
        }
        if (chumo <= 19)
        {
                chumo = chumo + 1;
        }
}

浮尘。 发表于 2017-5-29 15:56

可以共享一下3D模型吗?:lol
页: [1]
查看完整版本: 智能电动门插销