1 简介
Hi,大家好,这里是丹成学长,今天向大家介绍一个学长做的单片机项目
基于树莓派的指纹打卡器
大家可用于 课程设计 或 毕业设计
🧿 毕设项目分享:见文末!
2 主要器件
- 树莓派一台
- 指纹模块(AS608光学指纹识别模块)
- OLED液晶屏
- usb转TTL
- 杜邦线
3 实现效果
5 部分实现代码
树莓派驱动gpio接收指纹模块数据:
1 # -*-coding=utf8-*-
2
3 import serial
4 import serial.tools.list_ports
5
6 import os, sys
7 PATH=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
8 sys.path.append(PATH)
9
10 SureCore = {
11 0x00: True, # 表示指令执行完毕或OK;
12 0x01: 101, # 表示数据包接收错误;
13 0x02: 102, # 表示传感器上没有手指;
14 0x03: 103, # 表示录入指纹图像失败;
15 0x06: 202, # 表示指纹图像太乱而生不成特征;
16 0x07: 203, # 表示指纹图像正常,但特征点太少而生不成特征;
17 0x15: 204, # 表示图像缓冲区内没有有效原始图而生不成图像;
18 0x08: 302, # 表示指纹不匹配;
19 0x09: 402, # 表示没搜索到;此时页码与得分为 0
20 0x0a: 502, # 表示合并失败(两枚指纹不属于同一手指);
21 0x0d: 802, # 表示指令执行失败;
22 0x0f: 1002, # 表示不能发送后续数据包;
23 }
24 '''返回= 999 校验和错误'''
25
26
27 class DealBuff:
28 """切割收到的数据"""
29 HEAD = [0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF]
30
31 def __init__(self, buff):
32 self.buff = buff
33 """处理读出的指纹数据用到"""
34 self.tag = list() # 包标识
35 self.data = list()
36 self.check = list()
37 pass
38
39 def read(self):
40 buff = [x for x in bytes(self.buff)]
41 check = self.slit(buff)
42 return self.tag, self.data, check
43
44 def listCut(self, buff, num):
45 """切割数组"""
46 rec = list()
47 for i in range(num):
48 bytes_buf = (buff.pop(0))
49 # rec.append(buff.pop(0))
50 rec.append(bytes_buf)
51 return rec, buff
52 pass
53
54 def slit(self, buff):
55 """"选择数据"""
56 # 初始化中间变量
57 popList = list()
58 check_Num = 0
59 check = list()
60 head = list()
61
62 if len(buff) < 6: # 判断是否有效数据
63 return True
64
65 head, buff = self.listCut(buff, 6) # 选择出头及判断
66 for i in range(6):
67 if head[i] != self.HEAD[i]:
68 return False
69
70 popList, buff = self.listCut(buff, 1) # 取出包标识
71 self.tag.append(popList)
72 check_Num += popList[0] # 计算校验和
73
74 popList, buff = self.listCut(buff, 2) # 取出包长度
75 check_Num += popList[0] + popList[1] # 计算校验和
76
77 popList, buff = self.listCut(buff, popList[0] * 16 + popList[1]) # 取出包数据
78 check.append(popList.pop()) # 取出校验数据
79 check.append(popList.pop())
80 for i in popList: # 计算校验和
81 check_Num += i
82
83 self.data.extend(popList) # 导入有用数据
84 if check_Num % 65535 != check[0] + check[1]*256: # 检验校验和
85 return False
86
87 rec = self.slit(buff) # 得到是否正确分析完数据
88 return rec
89 pass
90
91 def write(self):
92 """要写的数据打包"""
93 pack = self.dataSeparate(self.buff, 128) # 将数据分成每组128个元素
94 return pack
95 pass
96
97 def dataSeparate(self, buff, numPart):
98 """把数据分组打包"""
99 num = int(len(buff) / numPart)
100 newData = list()
101 for i in range(num):
102 newData.append(buff[i * numPart:(i+1) * numPart])
103
104 packData = list()
105 for i in range(num-1):
106 data = self.packData(newData[i], 0x02) # 数据包没结束
107 packData.extend(data)
108
109 packData.extend(self.packData(newData[num-1], 0x08)) # 数据包结束
110 return packData
111 pass
112
113 def packData(self, buff, flage):
114 num = len(buff) + 2
115 senddata = [flage, int(num / 256), int(num % 256)] + buff
116 sum = 0
117 for i in senddata:
118 sum += i
119 senddata = self.HEAD + senddata
120 senddata.append(int(sum / 256))
121 senddata.append(int(sum % 256))
122 return senddata
123 pass
124
125 pass
126
127
128 class DealFingeer:
129 """和指纹模块交互"""
130 HEAD = [0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF]
131 tag = list() # 包标识
132 cmd = list() #
133 data = list()
134 ser = serial.Serial()
135 def __init__(self, cmd, data=None, server=None):
136 """初始化函数"""
137 self.cmd = cmd
138 self.data = data
139 self.server = server
140 pass
141
142 def run(self):
143 if hasattr(self, self.cmd):
144 func = getattr(self, self.cmd)
145 return func(self.data)
146 pass
147
148 def link(self):
149 """连接串口"""
150 self.ser.port = "COM5"
151 self.ser.baudrate = 57600
152 self.ser.bytesize = 8
153 self.ser.parity = 'N'
154 self.ser.xonxoff = 0
155 self.ser.rtscts = 0
156 self.ser.close()
157 self.ser.open()
158 pass
159
160 def finger(self, data):
161 self.link()
162 check = self.getImage() # 检测获取图像
163 if check is not True:
164 return check, []
165
166 self.link()
167 check = self.genChar(data) # 检测生成特征值
168 if check is not True:
169 return check, []
170 # ================= 生成特征值时图像会清除,所以要重新采集 ========================== #
171 self.link()
172 check = self.getImage() # 检测获取图像
173 if check is not True:
174 return check, []
175
176 if self.server is not None:
177 self.server.send("True".encode("utf8")) # 发送数据说明准备好了
178
179 self.link()
180 check = self.upImage() # 上传图像
181 if check is not True: # 校验和错误
182 return check, []
183 self.tag, self.data = self.getUpImage()
184
185 if len(self.tag) is 0 and len(self.data) is 0: # 得到数据错误
186 return False, []
187 return True, []
188
189 def save(self, data=None):
190 self.link()
191 check = self.regModel()
192 if check is not True: # 校验和错误
193 return check, []
194
195 self.link()
196 check = self.upChar(data) # 上传特征值
197 if check is not True: # 校验和错误
198 return check, []
199 self.tag, self.data = self.getUpChar()
200
201 if len(self.tag) is 0 and len(self.data) is 0: # 得到数据错误
202 return False, []
203 return True, []
204 pass
205
206 def check(self, data=None):
207 """检验指纹, 生成特征值"""
208 self.link()
209 check = self.match() # 比较指纹特征
210 if check is not True:
211 return check, []
212 score = self.data[1]*255 + self.data[2] # 返回的分数值
213
214 self.link()
215 check = self.regModel() # 合成指纹特征值
216 if check is not True:
217 return check, []
218 return True, score
219 pass
220
221 def isFinger(self, data=None):
222 """判断现在的指纹和下载的指纹是否相同"""
223 self.link()
224 check = self.downCharCheck()
225 if check is not True: # 判断是否可以发送数据
226 return check, []
227 """下载指纹"""
228 self.link()
229 self.downCharData(data)
230 """检验指纹"""
231 self.link()
232 check = self.match()
233 if check is not True:
234 return check, []
235 score = self.data[1] * 255 + self.data[2] # 返回的分数值
236 return True, score
237 pass
238
239 def getImage(self, data=None):
240 """获取图像"""
241 cmd = self.HEAD + [0x01, 0x00, 0x03, 0x01, 0x00, 0x05] # 发送命令获取内容
242 return self.isOk(cmd, 12)
243 pass
244
245 def genChar(self, data=None):
246 """生成特征文件"""
247 if data == "1":
248 cmd = self.HEAD + [0x01, 0x00, 0x04, 0x02, 0x01, 0x00, 0x08] # 发送命令
249 return self.isOk(cmd, 12) # 图像接收数据 12 大小
250 elif data == "2":
251 cmd = self.HEAD + [0x01, 0x00, 0x04, 0x02, 0x02, 0x00, 0x09] # 发送命令
252 return self.isOk(cmd, 12) # 图像接收数据 12 大小
253 pass
254
255 def match(self, data=None):
256 """比较指纹特征"""
257 cmd = self.HEAD + [0x01, 0x00, 0x03, 0x03, 0x00, 0x07] # 发送命令获取内容
258 return self.isOk(cmd, 14)
259 pass
260
261 def regModel(self, data=None):
262 """合成指纹特征值"""
263 cmd = self.HEAD + [0x01, 0x00, 0x03, 0x05, 0x00, 0x09] # 发送命令获取内容
264 return self.isOk(cmd, 12)
265 pass
266
267 def upChar(self, data=None):
268 """上传特征模块检测"""
269 buff = bytes()
270 if data == "1":
271 cmd = self.HEAD + [0x01, 0x00, 0x04, 0x08, 0x01, 0x00, 0x0e] # 发送命令
272 return self.isOk(cmd, 12, False)
273 elif data == "2":
274 cmd = self.HEAD + [0x01, 0x00, 0x04, 0x08, 0x02, 0x00, 0x0F] # 发送命令
275 return self.isOk(cmd, 12, False)
276 pass
277
278 def getUpChar(self, data=None):
279 """上传特征模块数据"""
280 buff = self.ser.read(834)
281 self.ser.close()
282 subpackage = DealBuff(buff) # 分割内容
283 self.tag, self.data, check = subpackage.read()
284 if check is not True: # 校验和错误
285 return 999
286 return self.tag, self.data
287
288 def downCharCheck(self, data=None):
289 """
290 下载特征值检测
291 先要初始化,发送获取图像命令
292 """
293 self.getImage()
294 self.link()
295 cmd = self.HEAD + [0x01, 0x00, 0x04, 0x09, 0x02, 0x00, 0x10] # 发送命令 下载的数据放在buff2中
296 return self.isOk(cmd, 12)
297 pass
298
299 def downCharData(self, data):
300 """下载特征值的数据"""
301 self.writeRead(data, 0) # 发送数据 接收为0
302 pass
303
304
305 def upImage(self, data=None):
306 """上传图像检测"""
307 cmd = self.HEAD + [0x01, 0x00, 0x03, 0x0a, 0x00, 0x0e] # 发送命令
308 return self.isOk(cmd, 12, False)
309 pass
310
311 def getUpImage(self, data=None):
312 """获取后续的图像数据"""
313 buff = self.ser.read(40032)
314 self.ser.close()
315 subpackage = DealBuff(buff) # 分割内容
316 self.tag, self.data, check = subpackage.read()
317 if check is not True: # 校验和错误
318 return [], []
319 return self.tag, self.data
320
321 def writeRead(self, cmd, length, close=True):
322 """发送命令读取原始字节"""
323 cmd = bytes(cmd)
324 self.ser.write(cmd)
325 buff = self.ser.read(length) # 图像接收数据
326 if close:
327 self.ser.close() # 接受完数据断开com
328 return buff
329 pass
330
331 def isOk(self, cmd, length, close=True):
332 """判断数据是否合格"""
333 buff = self.writeRead(cmd, length, close) # 图像接收数据 12 大小
334 subpackage = DealBuff(buff) # 分割内容
335 self.tag, self.data, check = subpackage.read()
336 # 检验数据是否可靠
337 if check is not True: # 校验和错误
338 return 999
339 return self.check_code(self.data)
340 pass
341
342 def check_code(self, data):
343 """检验指令码"""
344 return SureCore[data[0]]
345 pass
346
347 pass
348
349
350 if __name__ == "__main__":
351 # HEAD = [0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF]
352 # data = [0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x03, 0x0A, 0x00, 0x0E]
353 # data = HEAD + [0x01, 0x00, 0x03, 0x01, 0x00, 0x05]
354 # data = HEAD + [0x01, 0x00, 0x03, 0x05, 0x00, 0x09]
355 # data = HEAD + [0x01, 0x00, 0x04, 0x08, 0x02, 0x00, 0x0f]
(篇幅有限,其他代码暂不更新,有需要联系学长)
🧿 毕设项目分享:见文末!