一日在淘宝闲逛,看到一个电动锁芯,价格比较便宜,做工精良,顺便买了回来,打算改造下大门,现在指纹锁比较流行,使用也最方便,车都无钥匙进入了,大门指纹开锁是必须的。淘宝搜一下,指纹锁真贵,好的要几千大洋,最便宜的要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(); }#p#分页标题#e# 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) {#p#分页标题#e# 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数组,就可以用这个遥控器开锁了。 (责任编辑:admin) |