指纹锁V2.0 超低待机功耗(仅0.5uA)

理论上两节2000mah入门级18650能让这个指纹锁待机456年…

剩下的0.5uA就是锂电池充电板的待机电流了。

使用方法

先看PCB的正面和背面

注意背面有一排短接引脚,用于选择旋转角度(对于360度舵机来说)

一共5个短接点 0 1 2 3 4
这五个点按照从低到高的二进制来设定角度,下列表格中,数字代表短接,下划线代表不短接,则:

短接引脚组合 角度
0 _ _ _ _ 45
_ 1 _ _ _ 90
0 1 _ _ _ 135
_ _ 2 _ _ 180
0 _ 2 _ _ 225
_ 1 2 _ _ 270
0 1 2 _ _ 315

那么最大可旋转角度为 (2^5-1)*45 = 1395度。

PCB中 需要注意以下几点:

其中 指纹传感器排线P1的引脚定义:

排线引脚 目标引脚 备注
1 指纹3.3V
2 指纹Tx
3 指纹Rx
4 指纹GND
5 指纹WAK
6 指纹触摸3.3
7 指纹USB D+
8 指纹USB D-
9 触发按钮P1 非自锁按钮, 建议藏到指纹传感器下方
10 触发按钮P2 这样每次触碰到指纹的时候都会触发

舵机排线P3就是正常的舵机引脚顺序 GND已标出

如果要录入指纹,就先按下P2^0的按钮(也就是正面的S1),再按下指纹传感器,触发按钮,就能进入录指纹模式。
退出此模式,再长按P2^0按钮就行了。

还有就是:

注意:其中的继电器是3.3V低压继电器!!!

注意:其中的继电器是3.3V低压继电器!!!

注意:其中的继电器是3.3V低压继电器!!!

如果采用上图中的PCB,那么所有元件选型尽量(或者必须)按照下列表格来选择。
元件表

为了降低焊接难度,让更多人都能使用上这个V2.0的设计,我就把所有元件都放到正面了,所以也导致了PCB面积超过了嘉立创的5元打样限制,5张PCB下来可能得30元。
如果想要自己缩小的话,那就自己画PCB。
原理图:

当然了, 上面只是一个截图 原理图源文件在下面
原理图&PCB文件

大致说一下工作原理吧:

  1. 指纹按下时,微动开关触发,给单片机和NPN三极管上电,继电器导通。
  2. 单片机上电 第一件事就是P1^0输出高电平接管NPN三极管,此时按钮是否导通无所谓了。
  3. 然后指纹识别和解锁。
  4. 全部工作流程完毕后,P1^0输出低电平,关闭继电器,关闭全部电源。

这样,整个系统在没有指纹按下的时候,所有元件都处在关机状态。

一些细节就是这样设计,如果你指纹一直按着,开关一直导通,那他就永远不会断电,但是这个时候继电器是归单片机管的,可以用来操作继电器进行声音提示。

其实这个用场效应管+STM32来做 会更稳定。

代码部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
#include <reg52.h>
#include <stdio.h>
#include <string.h>

#define LEN 128 //可以减少 只要数据包长度低于这个值即可

sbit pwm = P1^1; //PWM信号输出,连舵机黄线
sbit Relay = P1^0; //继电器引脚
sbit sw = P2^0; //模式开关引脚

//角度选定引脚
sbit angle0 = P2^1;
sbit angle1 = P2^2;
sbit angle2 = P2^3;
sbit angle3 = P2^4;
sbit angle4 = P2^5;

unsigned char count; //0.5ms次数标识
unsigned char jd; //角度标识

unsigned char xdata Data_buff[LEN]; //初始化缓存


void delayms(unsigned int i) //延时
{
unsigned int j,k;
for(j=i; j>0; j--)
for(k=110; k>0; k--);
}

void Time0_Init() //定时器0初始化
{
TH0 = (65536-440)/256; //1.0851us一个计数周期
TL0 = (65536-440)%256; //初始化中断器
TMOD = 0x01; //定时器0工作在方式1
IE = 0x82; //IE=0x82=1000 0010 等价于 EA=1 开总中断 ET0=1 开定时器0中断
TR0 = 1; //开定时器0
}

void Time0_Int() interrupt 1 //中断程序
{
TH0 = (65536-440)/256; //1.0851us一个计数周期
TL0 = (65536-440)%256; //重新初始化中断器
if(count< jd)
{
pwm = 0; //高电平次数小于目标角度,PWM输出高电平(一次高电平输出0.5ms)
count=(count+1); //总次数加1
count=count%40; //确保总次数始终保持低于40 即保持周期为20ms
} else {
pwm = 1; //高电平次数大于等于目标角度,PWM输出低电平
count=(count+1); //总次数加1
count=count%40; //确保总次数始终保持低于40 即保持周期为20ms
}
}

void UART_Init(void) //波特率已最高为57600,12T 晶振11.0592MHz
{
SCON = 0x50;
TMOD &= 0x0f;
TMOD = 0x20;
PCON = 0x80;
TH1 = 0xFF;
TL1 = 0xFF;
ET1 = 0;
TR1 = 1;
}

//*******************************************
//函数名:Send_Bytes
//功能:发送多个字节
//参数:*c:首地址 len:长度
//指令代码:无
//返回值: 无
//*******************************************
void Send_Bytes(unsigned char *c,unsigned char len)
{
unsigned char i=0;
for(i=0; i<len; i++)
{
SBUF = *(c+i);
while(!TI);
TI = 0;
}
}

//*******************************************
//函数名:Receive_Bytes
//功能:接收多个字节
//参数:*c:首地址 len:长度
//指令代码:无
//返回值: 无
//*******************************************
char Receive_Bytes(unsigned char *c,unsigned char len)
{
unsigned char i=0;
unsigned long time=33000;
for(i=0; i<len; i++)
{
while(!RI && time--)
{
if(time==0)
return -2;
}
*(c+i)=SBUF;
RI=0;
}
return 0;
}

//*******************************************
//函数名:PS_GetImage
//功能:从传感器上读入图像存于图像缓冲区
//参数:无
//指令代码:01H
//返回值:有
//*******************************************
char PS_GetImage()
{

unsigned char *ps2= "\xef\x01\xff\xff\xff\xff\x01\x00\x03\x01\x00\x05"; //指令码

Send_Bytes(ps2,12); //发送指令码

if(Receive_Bytes(Data_buff,12)) //接收应答包
{
return -1;
}

if(Data_buff[9]==0x00&&Data_buff[11]==0x0a) //判断确认码是否成功 后面为校验和判断
{
return 0;
}

return -1;
}

//*******************************************
//函数名:PS_GenChar
//功能:将 ImageBuffer(图像缓冲区) 中的原始图像生成指纹特征文件存于 CharBuffer1 或 CharBuffer2
//参数:BufferID(特征缓冲区号)
//指令代码:02H
//返回值:有
//*******************************************
char PS_GenChar(unsigned char BufferID)
{

unsigned char *ps1= "\xef\x01\xff\xff\xff\xff\x01\x00\x04\x02\x01\x00\x08"; //存放CharBuffer1的指令码
unsigned char *ps2= "\xef\x01\xff\xff\xff\xff\x01\x00\x04\x02\x02\x00\x09"; //存放CharBuffer1的指令码
if(BufferID==0x01)
{
Send_Bytes(ps1,13); //发送指令码
}
else
{
Send_Bytes(ps2,13); //发送指令码
}

if(Receive_Bytes(Data_buff,12)) //接收应答包
{
return -1;
}

if(Data_buff[9]==0x00&&Data_buff[11]==0x0a) //判断确认码是否成功 后面为校验和判断
{
return 0;
}

return -1;
}

//*******************************************
//函数名:PS_Search
//功能:以 CharBuffer1 或 CharBuffer2 中的特征文件搜索整个或部分指纹库。若搜索到,则返回页码
//参数:BufferID, (StartPage(起始页),PageNum(页数))(默认从0到300全局搜索)
//指令代码:04H
//返回值:确认码、页码(ID)
//*******************************************
char PS_Search(unsigned char BufferID)
{

unsigned char *ps1= "\xef\x01\xff\xff\xff\xff\x01\x00\x08\x04\x01\x00\x00\x01\x2b\x00\x3a"; //存放CharBuffer1的指令码
unsigned char *ps2= "\xef\x01\xff\xff\xff\xff\x01\x00\x08\x04\x02\x00\x00\x01\x2b\x00\x3b";

if(BufferID==0x01)
{
Send_Bytes(ps1,17); //发送指令码
}
else
{
Send_Bytes(ps2,17); //发送指令码
}

if(Receive_Bytes(Data_buff,16)) //接收应答包
{
return -1;
}

if(Data_buff[9]==0x00) //判断确认码是否成功
{
return 0;
}

return -1;
}

//*******************************************
//函数名:ReadAngle
//功能:读取硬件上选定的旋转角度
//参数:无
//返回值:unsigned char类型的数值,单位为45度
//备注: 暂时懒得移植到180度上, 修改自己N年前的代码太折磨人了。
// 也懒得用寄存器连续读取IO了...
//*******************************************
unsigned char ReadAngle()
{
unsigned char sum;
unsigned char temp;

//计算角度
angle0 = 1;
temp = angle0;
sum += (1 - temp);
angle0 = 0;

angle1 = 1;
temp = angle1;
sum += (1 - temp)*2;
angle1 = 0;

angle2 = 1;
temp = angle2;
sum += temp*4;
angle2 = 0;

angle3 = 1;
temp = angle3;
sum += (1 - temp)*8;
angle3 = 0;

angle4 = 1;
temp = angle4;
sum += (1 - temp)*16;
angle4 = 0;

return sum;
}

/********************************************/
//360度舵机
// 0.5ms高电平 -> 最高速度正转 -> jd = 1
// 2.5ms高电平 -> 最高速度反转 -> jd = 5
//
//最高速度时:
// 0.1秒 -> 45度 当然 只是理论上是这样 具体自己调
/********************************************/
void unlock()
{
unsigned char angle;
angle = ReadAngle();
delayms(100);
Time0_Init();
count = 0;
jd = 1;
delayms(angle*200);
jd = 3;
delayms(3000);
jd = 5;
delayms(angle*200);
Relay = 0;
}

/********************************************/
//180度舵机
// 1.0ms高电平 -> 0度
// 2.5ms高电平 -> 180度
/********************************************/
/*
void unlock()
{
delayms(100);
Time0_Init();
count=0;
jd = 5;
delayms(3000);
count=0;
jd = 2;
delayms(1000);
Relay = 0;
}
*/

int main()
{
char status;
Relay = 1;
sw = 1;
status = sw;
while (!status)
{
delayms(3000);
sw = 1;
if(sw == 0)
Relay = 0;
}

RI=0;
while(1) {
UART_Init();
if(PS_GetImage() == 0) {
if(PS_GenChar(0x01) == 0) {
if(PS_Search(0x01) == 0) {
unlock();
} else {
while(1)
{
Relay = 0;
delayms(300);
Relay = 1;
delayms(300);
}
}
} else
Relay = 0;
} else
Relay = 0;
}
}

外壳部分

这回改进了下指纹传感器,藏了一个小微动开关在指纹传感器下面,每次指纹识别都会触发按钮,也不用每次都特意的额外的按下按钮

然后又给指纹传感器设计了个外壳,方便安装和放置微动开关





侧边的小凹槽是用来安装自锁扎带的,就是这种↓

可以用来帮到门把手之类的地方,实在不行就直接把整个外壳用热熔胶粘到门上


更新日志

2020-02-15

解决了无法进入录指纹模式的bug 优化了1字节的Rom空间
指纹锁V2.0基本上就要进入过去式了 因为物联网的V3要出了

2020-07-31

好多网友自己手焊都翻车了 然后我就直接做一个PCB文件吧,需要的自己去打样。
不过这个PCB的新特性我还没写相关代码。
因为为了照顾绝大多数小白,我把PCB分为了两个版本,一个版本是单面焊接纯直插原件的,一个是双面全贴片的。
不过为了降低难度,单面全直插的PCB体积超过了嘉立创的10*10cm的优惠限制..可能会贵一点..
上面说的物联网的V3 程序写好了,一直懒得焊电路调试…

2020-08-17

还是好多人来问。。于是我就重写了一遍文档。
以后打死也不碰这个坑爹51了。

Video

emmm暂时还没上传 先别急蛤。

DownLoad

外壳设计图
PCB文件