一日在淘宝闲逛,看到一个电动锁芯,价格比较便宜,做工精良,顺便买了回来,打算改造下大门,现在指纹锁比较流行,使用也最方便,车都无钥匙进入了,大门指纹开锁是必须的。淘宝搜一下,指纹锁真贵,好的要几千大洋,最便宜的要500块。所以准备自己做一个指纹锁。
一、材料准备
1、电动锁芯
这个锁芯大部分防盗门都可以装上。
2、指纹模块
淘宝的指纹模块有光学和电容式的两种,电容式的体积小,价格便宜点。最便宜的100块,就这个了。参数看着很强大,什么几百组指纹,识别准确率巴拉巴拉,都不关心,串口通讯,应该很好控制。
3、单片机
算了一下16脚够用了,STC15W408AS SOP16 的手上有现成的。
4、电机控制
此锁芯电机5V可以转,力小转速慢,12V应该是正常工作电压,空载电流100mA,堵转电流700mA左右。
本打算用继电器控制,两个继电器正反转,结实耐用,控制简单,但体积太大。手上还有几个L9110H H桥驱动/全桥驱动/电机驱动芯片DIP-8。这个芯片标的最大耐压12V,我用5V开关电源测试,发热比较大,12V开关电源秒烧。2S电池8.2V工作倒不热,3S电池秒烧。连着烧了两个。所以还是选2S 8.4V工作电压稳妥点。
5、5V供电
7805就行,据说效率不高, mini 360 降压模块,一直用这个,应该效率高点。
6、辅材
主要材料就这些了,还需要无源蜂鸣器,发出宾馆磁卡锁那样 滴滴答的音乐,按键提示等各种不同的音调。按钮,电阻电容,发光二极管若干。
二、原理图
1、 电源部分
实测发现 mini 360 降压模块静态功耗非常大,什么都不接,只接Vin 静态电流十几毫安,如果电池供电,2000mAh的18650锂电,只为这一个模块待机,只能坚持100个小时,也就是4天。根本不能用呀。看来这个模块需要改造,通过资料发现电源芯片的第7脚是en引脚,模块中是直接用10K电阻接在Vin上,保证通电给高电平,只要把这个引脚引出来,用单片机控制电瓶就可以关断降压模块。
图中这个引脚。
改造之后的样子。经过测试关闭之后的待机电流只有uA级别了,满足电池供电需求了。
但是问题来了。单片机把供电关闭之后自己也没电了,所以再也醒不过来了,额……
怎么办呢,只有给单片机单独供电,让单片机一直活着,才可以控制其他部件。
最终的电路图如下:
BAT为2S 18650电池,BAT1是一个旧手机的电池。电路复杂了,两个电池插座,两个电源开关,还要两个电池电压检测程序。
2、 电机控制部分
电机驱动模块,用两个1欧姆精度1%电阻并联做采样电阻,根据电流控制电机停止。
3、电源模块控制,蜂鸣器电路,指示灯电路
因为手上只有2302mos管,所以就用的这个,下拉电阻10K~100K都可以,考虑到待机功耗,所以选了100K的。用8050也可以,电阻阻值、位置换一下。
4、按钮电路
门外一个按钮,用来唤醒单片机指纹开锁,上锁。门内两个按钮一个用来直接开锁上锁,另一个用来录入指纹,清除指纹。
5 MCU部分
1.电源模块控制
2. 2S电池电压
3.电机电流检测
4.按钮2
5. 空
6. VCC BAT1单独供电
7. 蜂鸣器
8. GND
9. 10. 串口连接指纹模块
11.内部按钮
12. 外部按钮 并联 红外接收头
13. 14. 指示灯
15. 16. 电机正反转控制
三、PCB
手工热转印,蚀刻,单层板。制作门内门外分两块,
测试过程中发现,老人的指纹磨损,很难识别,所以加入了红外密码开锁,红外接收头和门外按钮公用一个引脚。
四、程序部分
/****************************************************************************
/*2016-12-21 指纹模块测试,写指纹
门外按钮 短按 按下红灯亮,等待搜索指纹,正确红灯灭,蜂鸣器123,错误蜂鸣器4
门外按钮 长按 反转反锁
门内按钮1,短按绿灯亮,直接开锁
门内按钮1,长按 反转反锁
门内按钮2 长按 等待管理员指纹录入,检测5次,正确,录入新指纹 连续录入5次,正确红灯闪烁,5次后,熄灭
门内按钮2 长长按 等待管理员指纹录入,检测5次,正确,清除所有指纹
/*2016-12-24 所有功能实现 加入休眠功能
/*2017-1-15 单片机测量电机电流,电池电压,内部带隙电压
滴滴滴滴滴滴 单片机电池低 滴答滴答滴答 电机电池低压
/*2017-1-22 加入红外遥控密码开锁
*************************************************************/
#include "intrins.h"
#include "IR.h"
#include <SERIAL.c>
#include <usartdrive.c>
#include "time0.h" //定时器初始化 软件延时函数
#include "stc_ad.h" //adc函数
/*****************************/
//51单片机的时钟晶振大小为11.0592Mhz
/****************************/
//typedef unsigned char uchar;
//typedef unsigned int uint;
#define MAX 0x0e //电机堵转电流
#define BatLow 176 //电池电压最低值
#define batVPin 3 //电池电压管脚
#define CurrPin 4 // 电机电流管脚
#define ClocsKey 0xFF //红外锁门 按键代码
#define btnOut P_IR_RX //外部按钮和红外接收公用一脚
sfr P5 = 0xC8; //xxxx,1111 端口5
sfr P0M0 = 0x94; // 0000,0000
sfr P0M1 = 0x93; //
sfr P1M0 = 0x92; // 0000,0000
sfr P1M1 = 0x91; //
sfr P3M0 = 0xB2; //0000,0000 端口3模式寄存器0
sfr P3M1 = 0xB1; //0000,0000 端口3模式寄存器1
sfr P5M0 = 0xCA; //0000,0000 端口5模式寄存器0
sfr P5M1 = 0xC9; //0000,0000 端口5模式寄存器1
//sfr WDT_CONTR = 0xC1; //0000,0000 看门狗控制寄存器
sfr ISP_CONTR=0xe7;
///////////////////管脚定义////////////////////////
//sbit btnOut=P3^3;//中断0 唤醒休眠用 /外部按钮和红外接收公用一脚
sbit btnIn=P3^2; //中断1 唤醒休眠用 内部按钮
sbit btnSet=P1^5; //设置指纹按下接地为0
sbit LedR=P3^7; //门外灯
sbit LedG=P3^6; //门内指示灯
sbit buzzer = P5^5; //控制三极管 推动蜂鸣器
sbit power = P1^2; //控制三极管 给除单片机外部件供电
sbit close=P1^1; //控制电机正反转
sbit open=P1^0; // 这四个脚需要强推挽
// 1.3 ADC 电池电压 1.4ADC 电机电流
//////////////// 变量声明////////////////
bit set1=0,set2=0,set3=0,set4=0 ,set5=0; //按钮动作功能位 set1 指纹开锁 set2 录入指纹 set3 上锁 set4 清所有指纹 set5 直接开锁
bit master=0; //管理员标志
bit locked=0; //已锁标志
uchar current; //电机电流 堵转 值0x0e
uint count=0; //计数 10次 扫描按键动作
uchar j=0,i=0;
uint Num;
uint btnPressSum=0; //按钮长按计数
long int t=0; //time0 计时
uint mcuV ,batV; //1s电池电压 2s电池电压
//////////////函数声明//////////////////
void fengming(uint x,uint y); //蜂鸣器发声
void buzz(uint No); //蜂鸣器奏乐 参数 123 321 1 2 3 4(低音do)
void btnScan(); //按钮扫描
void fingerOpenLock(); //指纹开锁
void openLock(); //直接开锁
void closeLock(); //上锁反锁
void getFinger(); //录入新指纹
void clearFinger(); //清空指纹
void chkMaster(); //检查管理员
void chkBat(); //检查电池电压
void IRopenLock(); //红外密码开锁
void main()
{
InitADC();
power=0; //打开降压供电模块
Timer0Init();
serial_init();
Delay(500);
P5M0|= 0x20;
P5M1= 0x00; //P5.5 强推挽
P3M0=0xC0; //P3.6 3.7 强推挽 1100 0000
P3M1= 0x00;
P1M0=0x07; // // P1.0 1.1 1.2 强推挽 0000 0111
P1M1= 0x00;
open=0;close=0; LedR=0; LedG=0;buzzer=0;
chkBat(); //检查电池电压
while(1)
{
btnScan();
if(set1)
{
buzz(3);
set1=0;
fingerOpenLock();
}
if(set2)
{
buzz(3);
set2=0;
getFinger();
}
if(set3)
{
set3=0;
closeLock();
}
if(set4)
{
set4=0;
clearFinger();//删除所有指纹
}
if(set5)
{
set5= 0;
chkBat();
openLock();//直接开锁
}
IRopenLock();
}
}
/////////按钮扫描////////////
void btnScan()
{
count++;
if(count==10)
{
count=0;
if(btnOut==0)Delay(50); //消抖
while(btnOut==0&&B_IR_Press==0) //是外部按键 并且不是红外按键
{
btnPressSum++;
Delay(10);
if(btnPressSum>200)
{
break;
}
}
if(btnPressSum>200)
{
set3=1;
}
elseif(btnPressSum>10)
{
set1=1;
}
btnPressSum=0;
if(btnIn==0)Delay(50);
while(btnIn==0)
{
btnPressSum++;
Delay(10);
if(btnPressSum>200)
{
break;
}
}
if(btnPressSum>200)
{
set3=1;
}
elseif(btnPressSum>10)
{
set5=1;
}
btnPressSum=0;
if(btnSet==0)Delay(50);
while(btnSet==0)
{
btnPressSum++;
Delay(10);
if(btnPressSum>200)
{
break;
}
}
if(btnPressSum>200)
{
set4=1;
}
elseif(btnPressSum>50)
{
set2=1;
}
btnPressSum=0;
}
}
void openLock()
{
buzz(123);t=0;
open= 1;close=0 ; LedG = 1;
Delay(500); //避开启动电流
do
{
if(t>48000)break; //如果6秒还未检测到电机堵转 停电机
current= FliterADC(CurrPin);
// putbyte(current); ADC 电机电流
}while (current<MAX);
open= 0; LedG = 0; locked = 0;
buzz(123);
Delay(2000);
close= 1;
Delay(300);//回锁舌
close= 0;
}
void fingerOpenLock()
{
//current=0;
LedR=1; t=0;
if(指纹验证通过()==1) //
{
openLock();
}
else
{
buzz(4);
}
LedR=0;
}
void closeLock()
{
t=0;
if(!locked)
{
locked=1;
close=1;open=0;LedG=1;
buzz(321);
Delay(500);
do
{
if(t>48000)break;
current= FliterADC(CurrPin);
// putbyte(current); //ADC 电机电流
}while (current<MAX);
close=0;LedG=0;
}
buzz(321);
}
void getFinger() //录入指纹
{
LedR=1;
j=0;t=0; //耗时长的操作,定时器清零,避免1分钟后休眠
if(Num==0) //如果指纹库为空,直接录入指纹
{
master=1;
}
else
{
chkMaster();
}
if(master) //管理员
{
LedG=1;
master=0;
j=0;
while(j<5)
{
if(写入指纹==1)
{
j++;
Num++;
buzz(3);
}
}
if(写入指纹==1);
{
buzz(321);
}
}
LedG=0;LedR=0;
}
void clearFinger() //清除所有指纹
{
LedR=1;j=0;
buzz(1);buzz(1);buzz(1);buzz(1);buzz(1);buzz(1); //清指纹提醒
chkMaster();
if(master)
{
LedG=1;
master=0;
if((清空指纹)) // 清空指纹
{
buzz(3);
}
else
{
buzz(1);
}
}
LedG=0;LedR=0;
}
void chkMaster() //验证管理员
{
while(!master)
{
if(j==5)
{
//LedG=1;LedR=1;
buzz(4);
break;
}
if(管理员验证成功) //管理员验证成功
{
master=1;
buzz(123);
}
else
{
buzz(4);
}
j++;
}
}
void chkBat() //检查电池电压
{
P1ASF= 0x00;
// //带隙电压 5V 为0x40(64) 3.3V 为0x 5F 3.0v为0x68
mcuV=FliterADC(0);
// putbyte(mcuV);
if( mcuV>0x5f ) //mcu工作电压=5*64/带隙电压测量值
{
buzz(4);buzz(4);buzz(4);buzz(4);buzz(4);buzz(4);
}
else
{
buzz(1);
}
P1ASF= 0x18;
//电池电压经20K 10K分压 ,测量点电压为电池电压1/3 2s锂电放电下限为6.6v ,分压后为2.2v
//电池电压通道ADC的结果与mcu工作电压的关系 电池电压= mcu电压*adc测量值/256
//2.2v 时 adc/mcuv应>1.76
batV= FliterADC(batVPin);
batV=batV*100/mcuV;
// putbyte(batV);
if(batV<BatLow)
{
buzz(4);buzz(1); buzz(4); buzz(1);buzz(4); buzz(1);
}
else
{
buzz(1);
}
}
voidIRopenLock() //红外密码验证
{
if(B_IR_Press) //有IR键按下
{
LedR=1;Delay(10);LedR=0;buzz(1);
B_IR_Press= 0;
if(B_IrUserErr==0)
{
if(IR_code==ClocsKey) //如果是锁门按键 锁门
{
set3=1;
}
else
{
buf[k++]=IR_code;
}
}
if(k==passLen)
{
for(k=0;k<passLen;k++)
{
if(buf[k]!=passChar[password[k]])
break;
}
if(k==passLen)
{
set5=1;
// putbytes("OK ");
}
else
{
buzz(4);buzz(4);
}
k=0;
}
}
}
////////////////////////////////////
/*蜂鸣器函数 */
////////////////////////////////////
void fengming(uint x,uint y) //x时长,y音调
{
uinti;
for(i=0;i<x;i++)
{
buzzer=~buzzer;
Delayus(y);
}
}
void buzz(uint No)
{
uinti=0;
uintshengdiao[]={478,0451,0426,0402,0372}; //中1DO 523Hz0956us 中2RE 578 0842 中3M 659 0759
//高1DO 10460478 #DO# 1109 0451 高2RE 1175 0426 #2RE#1245 0402 高3M 1318 0372
switch(No)
{
case1: for(i=0;i<3;i++)
{
fengming(62,478);
}
break;
case2: for(i=0;i<3;i++)
{
fengming(70,426);
}
break;
case3: for(i=0;i<3;i++) //高5SO 15680319
{
fengming(94,319);
}
break;
case4: for(i=0;i<3;i++)
{
fengming(31,956);//低音do 错误用
Delayus(1000);
}
break;
case123: for(i=0;i<5;i++)
{
fengming(30000/shengdiao,shengdiao);
Delayus(500);
}
break;
case321:for(i=5;i>0;i--)
{
fengming(30000/shengdiao,shengdiao);
Delayus(500);
}
}
buzzer=0; //关蜂鸣器,省电
}
void Timer0() interrupt 1 using 1 //调用定时器0,自动重装载模式
{
IR_RX_HT6121(); //红外接收函数//125um
t++;
if(t>480000) //一分钟休眠 脚位清零 灭灯 关供电模块
{
t=0;power=1;LedR=0;LedG=0;open=0;close=0 ; buzzer =0;
PCON|= 0x02;
}
// TL0= 0x00; //设置定时初值
// TH0= 0x28; //设置定时初值
}
void int0(void) interrupt 0
{
PCON&= 0xEF;
power=0; //供电模块上电
}
void int1(void) interrupt 2
{
PCON &= 0xEF; //按钮2唤醒
power=0; //指纹模块上电
}
/* 这个函数无效果
void soft_reset(void)
{
((void (code *) (void)) 0x0000) ();
} */,
***************************************/
由于版权问题,不公开指纹模块驱动,和调用函数,如果购买模块厂家会提供。
如果要降低造价,可以不使用指纹模块,只使用红外密码开锁。
下面是红外接收子程序,STC官网提供,稍做修改,即可使用
随便找个遥控器,先通过以下程序读取设备码各按键码,然后挑两个放入password数组,就可以用这个遥控器开锁了。