【占坑】抛弃钥匙,寝室RFID门禁系统进化史...
本帖最后由 code-AR 于 2014-4-7 15:26 编辑不知道大家是否在学校生活中常常会有忘带钥匙的情况出现,每当忘带钥匙,室友不在寝室的话,站在寝室外等待各种尴尬。同时不知道是不是学校门锁老旧,开门比较纠结花时间。那时候就有制作自动门锁的想法。后来入手了RFID读卡器,可以正常读取市面上的Mifare S50,S70非接触智能卡,像学校的饭卡就可以读取。就构想了这个基于RFID的寝室门禁系统。
系统原理是基于非接触式卡的序列号是唯一的,制造厂家在产品出厂前已将此序列号固化,不可再更改。这样不同的卡都是唯一的存在,可以利用读卡器读取卡的序列号,来判断卡的拥有者(像我的室友)。基本原理可以参考下图:
寝室RFID门禁系统1.0
首先来一张全景图吧。
(1) 准备工作
制作材料:
Arduino UNO
NOKIA 5110液晶屏
RFID-RC522读卡器
MG-996R舵机
移动电源
首先,是将RFID-RC522和UNO连接起来,这个读卡器是基于SPI通讯。但这里有一个封装比较好的库文件支持RC522,可以自定义SPI针脚位。NOKIA 5110液晶屏也有库文件——支持画图,中文显示,可以自定义针脚位。因为开启门锁需要较强拉力,这样MG-996R所需电量比较大,实际使用时,需要给舵机单独供电。整个电路部分还是比较简单的,只是能够完成最基本的功能展现。
(2) 软件部分
主控部分用的的是Arduino Uno,使用了arduino IDE 1.04。
代码如下:
#include <SPI.h>
#include <RFID.h>
#include <LCD5110_CN.h>
#define servopin 7
#define sensor 0
#define BL 9
LCD5110 myGLCD(2,3,4,5,6);//CLk-SCK,Din-MOSI,DC,RST-IO,CS-CE
extern uint8_t SmallFont[];
RFID rfid(10,8); //D10--读卡器SDA引脚、D8--读卡器RST引脚
//4字节卡序列号,第5字节为校验字节
unsigned char serNum;
void servopulse(int angle)//定义一个脉冲函数
{
int pulsewidth=(angle*11)+500;//将角度转化为500-2480的脉宽值
digitalWrite(servopin,HIGH); //将舵机接口电平至高
delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
digitalWrite(servopin,LOW); //将舵机接口电平至低
delayMicroseconds(20000-pulsewidth);
}
void setup()
{
myGLCD.InitLCD();
Serial.begin(9600);
pinMode(BL,OUTPUT);
pinMode(servopin,OUTPUT);
myGLCD.setFont(SmallFont);
SPI.begin();
rfid.init();
}
void loop()
{
/* int val1=analogRead(sensor);
if(val1>200)
{analogWrite(BL,512);}
else
{digitalWrite(BL,LOW);}*/
//通过光敏,控制5110的背光
long randNumber = random(0, 20);
unsigned char i,tmp;
unsigned char status;
unsigned char str;
unsigned char RC_size;
//找卡
rfid.isCard();
//读取卡序列号
if (rfid.readCardSerial())
{
Serial.print("The card's number is: ");
Serial.print(rfid.serNum);
Serial.print(" , ");
Serial.print(rfid.serNum,BIN);
Serial.print(" , ");
Serial.print(rfid.serNum,BIN);
Serial.print(" , ");
Serial.print(rfid.serNum,BIN);
Serial.print(" , ");
Serial.print(rfid.serNum,BIN);
Serial.println(" ");
if(rfid.serNum==205||rfid.serNum==170||rfid.serNum==219||rfid.serNum==117||rfid.serNum==155){
for(int i=0;i<100;i++)
{
servopulse(45);
if(rfid.serNum==205||rfid.serNum==117||rfid.serNum==155)
{
myGLCD.clrScr();
Serial.println("Welcome Mr.Xiao");
myGLCD.print("Welcome",int(randNumber)+20,int(randNumber));
myGLCD.print("Mr.Xiao",int(randNumber)+20,int(randNumber)+20);
analogWrite(BL,HIGH);
}
if(rfid.serNum==219)
{
myGLCD.clrScr();
Serial.println("Welcome Mr.Yang");
myGLCD.print("Welcome",int(randNumber)+20,int(randNumber));
myGLCD.print("Mr.Yang",int(randNumber)+20,int(randNumber)+20);
digitalWrite(BL,HIGH);
}
if(rfid.serNum==170)
{
myGLCD.clrScr();
Serial.println("Welcome Mr.Huang");
myGLCD.print("Welcome",int(randNumber)+20,int(randNumber));
myGLCD.print("Mr.Huang",int(randNumber)+20,int(randNumber)+20);
digitalWrite(BL,HIGH);
}
} //引用脉冲函数
delay(3000);
for(int i=0;i<100;i++)
{
servopulse(0);
}
}
}
if (!rfid.readCardSerial()){
digitalWrite(servopin,LOW);
digitalWrite(BL,LOW);
}
rfid.halt(); //指挥卡进入睡眠模式
}
这里有两个库文件
(3) 试验品1.0
电路连接的部分结束后,我使用了比较简陋的纸壳将整个装置包装起来,将电路部分固定在了里面。然后将整个包装粘合在门后,其中读卡器是在门缝走线(还好是木门O(∩_∩)O哈哈~)。
这里有个效果视频
http://v.youku.com/v_show/id_XNjQ2MjQzNTY0.html
这里有几个问题,希望可以和大家探讨下:
1.电源供电部分?不知道有没有更好的供电方案,那个舵机供电太烦恼了,不得不用有两头供电的移动电源。
2.有没有自动激活好方法?希望能够实现晚上系统断电,早上系统激活工作。这样可以增强系统续航力。
3.更好的用户界面,像欢迎,查询。用点阵还是液晶屏?
以上只是我想法的最基础版本,可以说是系统1.0版吧,但这样已经完成了最初的预想。我想这个基础版还是有很大的发展空间,完全可以基于此,进一步使整个寝室智能化。下一步我想加强系统的稳定性,以及增加密码键功能,开发出2.0,3.0版本。也希望有兴趣的朋友那个给出宝贵的建议,大家一起分享快乐。
本帖最后由 code-AR 于 2015-5-16 18:52 编辑
占楼备用...
占楼一年多了,还是没填坑。惭愧呀!!!
现在填些坑吧,后来版本我加入了休眠机制,进一步降低了功耗,一块5000mAH的移动电源可以支持一个星期没问题。新版本在我的寝室已经正常工作了半年多了吧。如果还想减低功耗,就要自己绘制电路开板了,麻烦了就搁置了。
硬件方面就是比原来的版本多了个外部唤醒的开关,去除了内部的显示屏,在这里把新的代码贴下
#include<SPI.h>
#include<RFID.h>
#include <Enerlib.h>//低功耗公共库
#define servopin 7
Energy energy; // 宣告"Energy"程式物件
const byte swPin = 2; // 外部开关引脚
byte times = 0; // 记录睡眠状态
volatile byte state = 0;
RFID rfid(10,8);
//4字节卡序列号,第5字节为校验字节
unsigned char serNum;
void servopulse(int angle)//定义一个脉冲函数
{
int pulsewidth=(angle*11)+500;//将角度转化为500-2480的脉宽值
digitalWrite(servopin,HIGH); //将舵机接口电平至高
delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
digitalWrite(servopin,LOW); //将舵机接口电平至低
delayMicroseconds(20000-pulsewidth);
}
void wakeISR() {
if (energy.WasSleeping()) {
state = 1;
}
else {
state = 2;
}
}
void setup()
{
//Serial.begin(9600);
attachInterrupt(0, wakeISR,RISING);//CHANGE);
pinMode(servopin,OUTPUT);
SPI.begin();
rfid.init();
}
void loop()
{
unsigned char i,tmp;
unsigned char status;
unsigned char str;
unsigned char RC_size;
if (state == 1) {
//Serial.println("Was sleeping...");
}
else if (state == 2) {
//Serial.println("Was awake...");
}
state = 0;
//找卡
rfid.isCard();
//读取卡序列号
if (rfid.readCardSerial())
{
if(rfid.serNum==155||rfid.serNum==234||rfid.serNum==219){
for(int i=0;i<100;i++)
{
servopulse(45);
} //引用脉冲函数
delay(3000);
for(int i=0;i<100;i++)
{
servopulse(0);
}
}
}
if (!rfid.readCardSerial()){
digitalWrite(servopin,LOW);
}
if(!rfid.isCard())
{
energy.PowerDown();
}
rfid.halt(); //指挥卡进入睡眠模式
}
低功耗库下方
哈哈,小心读卡模块被人偷走哦~~~~~;P;P;P 读卡器放在门里边读不到卡吗?如果被人拿走不哭死,移动电源多长时间充次电? Cupid 发表于 2014-1-2 17:53 static/image/common/back.gif
读卡器放在门里边读不到卡吗?如果被人拿走不哭死,移动电源多长时间充次电?
一般可以支持3-4天,所以希望改进供电部分。 Damn_intuition 发表于 2014-1-2 17:38
哈哈,小心读卡模块被人偷走哦~~~~~
嗯嗯,直接拿走好了 几十块买个磁性门锁,控制电路依然是你那套东西,完美了 pipapi 发表于 2014-1-2 22:12 static/image/common/back.gif
几十块买个磁性门锁,控制电路依然是你那套东西,完美了
有道理 这个应该是个比较好的方案 我也看一下比如下面这个
http://item.taobao.com/item.htm?spm=a230r.1.14.44.W7ocnI&id=18770053569 pipapi 发表于 2014-1-2 22:12 static/image/common/back.gif
几十块买个磁性门锁,控制电路依然是你那套东西,完美了
这个是寝室,还不太敢拆门锁:) 门是铁的吗?隔着铁不是RC522不能用了吗? 不用时是可以完全断电的吧,在门外加个电源开关,打开才真正供电就可以了吧 好像就是破 木板门龙骨加胶合板那种吧,可惜估计不敢拆,不然背面开洞,读卡模块贴在前面薄板的背面估计就可读了 嗯,在外面放个开关,刷卡的时候再通电,这样能省很多电 chaqing 发表于 2014-1-3 10:18 static/image/common/back.gif
好像就是破 木板门龙骨加胶合板那种吧,可惜估计不敢拆,不然背面开洞,读卡模块贴在前面薄板的背面估计就可 ...
这个的确是,就不知道RFID的模块可不可以通过神马手段增加距离,这样就方便了。 shenhaiyu 发表于 2014-1-3 13:30 static/image/common/back.gif
嗯,在外面放个开关,刷卡的时候再通电,这样能省很多电
这样感觉有些麻烦,还要先启动开关。