树莓派DIY自带特效的智能安全门

20170310134914468-0

来自树莓派实验室老司机群 Pokebox 的投稿~,文末有 Pokebox 同学录制的炫酷视频不要错过!

自从上次在树莓派实验室发了那个《用树莓派DIY一个智能家居服务器》后,反响比较强烈~~
直到最近都还有朋友给我发邮件说想学习交流~嗯,那时是刚高考完,现在也上大学了,在学校也有了自己的工作室,于是就在工作室里把家里那套系统搬了过来弄了一下~把工作室小改造了一番。
当然,改造的最多的还是工作室的这扇门~所以这次着重讲的也是这扇门~

20170310134914253-0

20170310134914606-0

之前是这个样子的,普通的机械锁,有个把手,开门全靠钥匙。虽然学校装了电磁门禁,门口旁边也有个刷卡器,但是并没有使用。

20170310140608353-0

20170310140608893-0

现在还是只是用钥匙开门。在得到老师的同意和指示后,召集小伙伴七手八脚的就把门锁先给卸了~

20170310134914138-0

20170310134914763-0

当然,可能到这大家有点看不明白我们打算要干嘛~
先说明一下目的,嗯,由于普通的门锁想要用电子控制,要么得在锁上装舵机,通过机械的方式拉开锁舌开门,要么完全用电磁之类的吸合。之前是打算把这个把手直接拆掉只用上面的电磁门禁,但是这会出现一个问题,万一停电了,门没办法锁;或者出了故障,又没钥匙开门。所以折中方案就是选择这种电机控制的门锁。这种门锁在楼宇门禁还是经常见的,相信大家并不陌生。

在换好锁后,因为锁本身就支持钥匙开门或者按开关开门,所以我就直接弄了根网线,把电源线开关线接出来

20170310140608426-0

然后,把这根网线弄到原来的开门开关上,当然,先把原来的刷卡面板卸了~

20170310134914641-0

这是原来接在外面的刷卡面板的线,埋在出门开关的盒子里……全剪掉,然后拆了刷卡面板,把开关和现在接的网线连接起来,然后调试锁

20170310134914103-0
(做的时候其实是先调试好了锁才考虑用什么方式走线的……一开始打算在门上钻孔走内部,但是不好弄,就直接拉网线走门边控制)

20170310140608761-0

一切调试好后,就把树莓派放上,加上树莓派远控(毕竟结合原来的那套系统嘛,继续考虑手机控制)
树莓派也放上去后,因为把刷卡器拆了,外面的墙上有个洞不好看,先用3D打印机打了块板子临时盖着遮一下……

20170310134914258-0
之后打算在这个位置弄密码键盘,按密码开门。
说干就干,抄起单片机,买几片薄膜键盘,设计好外壳,走起~

20170310134914680-0

先用单片机+薄膜键盘做密码键盘的输入,通过串口把获取到的按键值发给树莓派去识别和操作。这里我用了#号键作为密码输入结束的确定键。
单片机程序和树莓派程序调通后,打印外壳,焊板子(因为体积关系不可能直接塞个直插封装的单片机下去,所以就买了比较方便焊接体积又相对小的DIP封装的单片机,这里用了STC15系列的单片机,可以省掉晶振的焊接)
因为之前还打算设计语音开门,所以留了个麦克风的孔……

单片机读键盘数据的代码如下(单片机使用的是STC15W404AS型号)

#include "STC15W404AS.h"
#include <intrins.h>

#define key_port P1	//键盘接口定义
sbit key_port_0=key_port^0;
sbit key_port_1=key_port^1;
sbit key_port_2=key_port^2;
sbit key_port_3=key_port^3;
sbit BEEP=P5^5;		//蜂鸣器

sbit OPEN=P5^4;		//开门按键
/*******************************
STC15W404单片机一毫秒延时函数
*******************************/
void delay_ms(unsigned int ms)
{
	unsigned char i, j;
	while(--ms){
		_nop_();
		_nop_();
		_nop_();
		i = 11;
		j = 190;
		do
		{
			while (--j);
		} while (--i);
	}
}
/**************************
   串口发送一个字符
**************************/
void com_send_dat( unsigned char dat)
{
	SBUF=dat;
	while (TI== 0);
	TI= 0 ;
}

void init_com(void)		//T2_9600bps@11.0592MHz
{
	SCON = 0x50;
	AUXR |= 0x01;
	AUXR |= 0x04;
	T2L = 0xE0;
	T2H = 0xFE;
	AUXR |= 0x10;
}
/**************************
   键盘扫描函数
**************************/
unsigned char keyscan(void)
{
	unsigned char key,i;
	unsigned char code key_table[16]={0xeb,0x77,0x7b,0x7d,0xb7,0xbb,0xbd,0xd7,0xdb,0xdd,0x7e,0xbe,0xde,0xee,0xe7,0xed};

	key=0xFF;							//输出初始化值
	key_port=0x0f;						//确定行列位置
	if(key_port==0x0f) return(255);		//无键按下返回0
	delay_ms(5);              			//调用延时函数 ,目的是去前沿键抖。
	if(key_port==0x0f) return(255);		//再次判断。目的是确保检测正确
	else
	{
		for(i=0;i<4;i++)	//以下为经典的计算键值(判断闭合键所在的位置)
		{
			key_port=_cror_(0x7f,i);
			if(key_port_0==0) break;
			if(key_port_1==0) break;
	 		if(key_port_2==0) break;
			if(key_port_3==0) break;
		}
		key=key_port;		//取得键值
		for(;key_port!=0x0f;key_port=0x0f);			//等待键松开,目的是去后沿键抖
		for(i=0;key_table[i]!=key && i<16;i++);		//查表取key的值0-F
		key=i;
		return(key);				//带键值返回主调函数
	}
}


/**************************
   键盘扫描测试主函数
**************************/
void main(void)
{
	unsigned char key,nok;
	init_com();			//串口初始化
	nok=0;
	while(1)
	{
		key=keyscan();
		if(key!=0xff)
		{
			BEEP=0;
			com_send_dat(key+0x30);
			delay_ms(20);
			BEEP=1;
		}

		if(OPEN==0)		//如果从里面按下了开关则发送一个字符串
		{
			com_send_dat('Y');
			com_send_dat('E');
			com_send_dat('S');
			com_send_dat('O');
			com_send_dat('P');
			com_send_dat('E');
			com_send_dat('N');
			while(!OPEN);
				delay_ms(10);
		}

	}
}

单片机控制开门的代码

#include <STC12C5A60S2.h>

#include <intrins.h>

sbit IN1=P1^0;		//霍尔传感器1
sbit IN2=P1^1;		//霍尔传感器2
sbit OUT=P2^0;		//门控制

sbit RELAY=P2^1;	//继电器
bit OFLAG = 0;		//状态标记

void Delay100ms(unsigned int t)		//@11.0592MHz
{
	unsigned char i, j, k;

	while(--t)
	{
		//_nop_();
		//_nop_();
		i = 5;
		j = 52;
		k = 195;
		do
		{
			do
			{
				while (--k);
			} while (--j);
		} while (--i);
	}
}

void main(void){
	unsigned char i;
	P1M0=0xff;	//高阻输入
	P1M1=0xff;
	//P2M0=0x00;	//推挽输出
	//P2M1=0xff;
	
	IN1=1;
	IN2=1;
	OUT=1;
	RELAY=1;
	
	while(1){
		if(IN1==0 && OFLAG==0)
		{
			OUT=0;		//开门
			OFLAG=1;	//标志一下现在状态是开门
			for(i=0;i<9;i++)
			{
				
				RELAY=0;
				Delay100ms(3);
				RELAY=1;
				Delay100ms(3);
			}
			RELAY=1;
			OUT=1;
		}
		else if(IN2==0)
		{
			OFLAG=0;
		}
		
	}
}

20170310134914416-0

20170310134914216-0

20170310134914311-0

把薄膜键盘贴上去,板子直接上热熔胶固定。蜂鸣器作为按下按钮时发出滴滴的提示音用~

20170310134914301-0

一切搞定后装壳上墙~
效果其实还是很不错的。

20170310134914468-0

这一切弄完了,试了一两天发现还是有点不够完美,上面的电磁锁我们也打算利用起来。
由于这个门锁是电磁感应式锁门的,不是碰撞式锁门,所以在关门时锁上的传感器感应到锁口的磁铁时才视为当前是关门状态,然后才伸出锁舌锁门。如果我们用常规的关门方式带门就走,门在关上瞬间由于惯性会反弹一下,所以在关门的时候不得不温柔的拉上门,等锁舌伸出后才能走。但是由于装了这个锁没把手,关门就成了比较蛋疼的事情。
刚好,如果加上上面的电磁锁,在关门的时候吸住门,这样门就不会弹开了。但是,还有个问题……如果让电磁锁一直通电的话,下面的锁开了,上面还吸着门,门还是打不开。如果不吸,又会出现关门比较麻烦的事情。就算用树莓派来控制,在输入密码的时候开门自动断开它的电源同时开锁,但是如果是用钥匙开的话,就没办法打开它了。怎么办?如何才能做到开锁后门磁断开,能顺利开门,关门的时候又可以加磁吸住门同时无论用密码还是远程或是直接用钥匙开门都能打开电磁锁呢?

我反复研究了一下这个锁,发现里面有3个霍尔传感器,一个是之前说的用来判断锁是否处于关门状态自动锁上的,另外两个传感器位于锁舌附近,是拿来判断锁舌位置的。因为发现这个锁在开着门的状态如果强行拉出锁舌,会报警,几秒后自动收回锁舌。在处于关门状态时,如果长期没动,锁舌也会自动伸出锁门。
正好,利用这两个判断锁舌位置的传感器就可以完成在锁舌收回的时候断开电磁锁开门。
这里我又单独用了一块单片机来判断这些传感器的位置并控制门磁,不使用树莓派一起控制的目的是防止万一树莓派死掉了,这部分独立的电路还能保证门锁可以正常打开。

这样一番改造后,工作室的门就可以通过多种方式开门,既可以使用密码盘输入密码进入,也可以远程通过手机或者电脑开门,在停电或者故障的时候,还可以使用备用的钥匙开门。这样做就可以很好的分配用户权限,因为可以设置每个人的密码都不一样,这样就可以通过识别不同人的密码判断谁在什么时间进入了工作室,连考勤都可以省了~管理员还可以通过远程查看登录记录知道今天谁来了谁没来;或是管理员出门在外有外来人员想参观工作室的时候,就可以远程开门给领导老师进去检查参观,就不会造成因为人不在而进不了门的尴尬~
以及在有人来访的时候,还可以设置访客密码,演示的时候使用这个访客密码进入树莓派会播放欢迎的语音,并向墙壁投影一个虚拟人物欢迎~提升工作室的科技感~
嗯,之后还打算继续完善这个工作室,把空调,电灯之类的控制完善起来,变成一个全智能的工作室~

20170310140608288-0

20170310140608178-0

20170310140608651-0

最后让我们视频预览一下这个智能门有什么炫酷特效,欢迎弹幕吐槽!

(bilibili 吐槽请移步 http://www.bilibili.com/video/av9021381/)

编者提示:本文中有关树莓派作为上位机如何通过串口与单片机进行通信,树莓派实验室之前的文章有介绍相应的方法,可以参考:
https://shumeipai.nxez.com/2017/01/31/raspberry-serial-programming-python-example.html
https://shumeipai.nxez.com/2015/03/26/raspberry-pi-serial-programming-sending-and-receiving.html

这是一篇发布于 8年 前的文章,其中的信息可能已经有所发展或是发生改变,请了解。


14 评论

  1. 作者用单片机读取键盘数据和开锁,树莓派负责逻辑处理并作为上位机控制这些单片机。语音 数据记录全在pi上。

  2. 你好,请问树莓派如何接收并处理电脑上myeclipse编写的程序的结果,并实现门控功能呢,这样是否可行?

  3. 你好,我最近在做人脸识别开锁,现在人脸识别已实现,请问下树莓派通过摄像头识别后,树莓派与锁通过什么实现门控功能?谢谢您!

发表评论

你的邮件地址不会公开


*