智能电动门插销
本帖最后由 星空太黑 于 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函数,检测是否到达这个时间,到了就执行。
就此就完成了,但是根据实际情况还需要不断优化,修改程序,比如触摸开门立即打开,触摸关门延时关闭因为触摸时可能门还没有关到位,还有可能断电从启时是希望它锁门还是开门,这在程序中都是需要优化的。
刷卡功能等做好后再更新此贴
视频刚上传到优酷,过几天更新
#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;
}
}
可以共享一下3D模型吗?:lol
页:
[1]