PHẦN 1: GIAO TIẾP VỚI ARDUINO
Xin chào các bạn! Hôm nay mình sẽ đem tới cho các bạn một bài chia sẻ mới về module nhận dạng vân tay. Chắc có lẻ nhiều bạn khi nhắc tới nhận dạng vân tay có thể sẽ nghĩ đến phải biết xử lý ảnh, machine learning, AI,…mới có thể xử lý hình ảnh dấu vân tay đúng không. NHƯNG KHÔNG, mọi thứ xử lý đó đã được module cảm biến vân tay làm sẵn hết, chúng ta chỉ cần giao tiếp với module qua cổng UART hoặc USB là có thể thêm dấu vân tay vào bộ nhớ, nhận diện vân tay đó là vân tay nào,…để có thể ra lệnh điều khiển theo tùy ý mình.
Và để có thể cụ thể hơn công việc đó là như thế nào thì bạn hãy xem hết bài viết dưới đây của mình nhé
1. Giới thiệu module cảm biến vân tay AS608
Cảm biến nhận dạng vân tay AS608 Fingerprint Sensor sử dụng giao tiếp UART TTL hoặc USB để giao tiếp với Vi điều khiển hoặc kết nối trực tiếp với máy tính (thông qua mạch chuyển USB-UART hoặc giao tiếp USB).
- Nguồn cung cấp điện áp: DC 3.6 đến 6.0V
- Nguồn cung hiện tại: <120mA
- Màu đèn nền: màu xanh lục
- Baudrate: 9600, 19200, 28800, 38400, 57600 (default is 57600)
- Mức độ an toàn: từ thấp đến cao 1,2,3,4,5
- Tỷ lệ chấp nhận sai (FAR): <0,001% (mức độ bảo mật 3)
- Tỷ lệ từ chối giả (FRR): <1.0% (mức độ bảo mật 3)
- Có thể lưu trữ hơn 200 dấu vân tay khác nhau.
Cảm biến nhận dạng vân tay AS608 Fingerprint Sensor được tích hợp nhân xử lý nhận dạng vân tay phía trong, tự động gán vân tay với 1 chuỗi data và truyền qua giao tiếp UART ra ngoài nên hoàn toàn không cần các thao tác xử lý hình ảnh, đơn giản chỉ là phát lệnh đọc/ghi và so sánh chuỗi UART nên rất dễ sử dụng và lập trình.
2.1. Chuẩn bị
- Arduino Uno (mình sử dụng cái này, nếu bạn dùng Kit Arduino khác thì cứ dùng).
- Module cảm biến vân tay AS608.
- Các dây jack cắm để nối cảm biến với arduino.
Mình sử dụng thư viện Fingerprint của Adafruit:
Vào Arduino -> Sketch -> Include library -> Manage libraries -> Tìm thư viện adafruit fingerprint để cài đặt vào nhé
Sau khi cài đặt thư viện xong, bạn có thể tham khảo 1 số examples có sẵn trong
File -> Examples -> Adafruit Fingerprint Sensor Lib
2.2. Lập trình Arduino
Đây là code arduino của mình, bạn có thể tham khảo (mình sẽ giới thiệu sơ qua phần code này ở phía dưới)
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 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 |
#include <Adafruit_Fingerprint.h> // pin #2 is IN from sensor // pin #3 is OUT from arduino SoftwareSerial mySerial(2, 3); Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); String inputString = ""; bool stringComplete = false; // whether the string is complete uint8_t id; uint8_t checkTask = 0; //for check task void setup() { // put your setup code here, to run once: Serial.begin(9600); while (!Serial); // For Yun/Leo/Micro/Zero/... delay(100); Serial.println("\n\nAdafruit Fingerprint sensor enrollment"); // set the data rate for the sensor serial port finger.begin(57600); if (finger.verifyPassword()) { Serial.println("Found fingerprint sensor!"); } else { Serial.println("Did not find fingerprint sensor :("); while (1) { delay(1); } } Serial.println(F("Reading sensor parameters")); finger.getParameters(); Serial.print(F("Status: 0x")); Serial.println(finger.status_reg, HEX); Serial.print(F("Sys ID: 0x")); Serial.println(finger.system_id, HEX); Serial.print(F("Capacity: ")); Serial.println(finger.capacity); Serial.print(F("Security level: ")); Serial.println(finger.security_level); Serial.print(F("Device address: ")); Serial.println(finger.device_addr, HEX); Serial.print(F("Packet len: ")); Serial.println(finger.packet_len); Serial.print(F("Baud rate: ")); Serial.println(finger.baud_rate); finger.getTemplateCount(); Serial.print(F("Sensor contains: ")); Serial.print(finger.templateCount); Serial.println(" templates"); } void loop() // run over and over again { getFingerprintID(); delay(50); //don't ned to run this at full speed. if(checkTask == 1) //Add template fingerprint { Serial.println("Ready to enroll a fingerprint!"); Serial.println("Please type in the ID # (from 1 to 127) you want to save this finger as..."); id = readnumber(); if (id == 0) {// ID #0 not allowed, try again! return; } Serial.print("Enrolling ID #"); Serial.println(id); while (! getFingerprintEnroll() ) { } checkTask = 0; } else if(checkTask == 2) //check template { checkTask = 0; uint8_t p = finger.loadModel(id); if(p == FINGERPRINT_OK) { Serial.print("ID "); Serial.print(id); Serial.println(" is exist"); } else { Serial.print("ID "); Serial.print(id); Serial.println(" is NO exist"); } } else if(checkTask == 3) //delete template { checkTask = 0; if(id == 0) //delete all template { finger.emptyDatabase(); Serial.println("Now database is empty"); } else deleteFingerprint(id); } } void serialEvent() { while (Serial.available()) { // get the new byte: char inChar = (char)Serial.read(); // add it to the inputString: inputString += inChar; // if the incoming character is a 'X', set a flag so the main loop can // do something about it: if (inChar == 'X') { if(inputString[0] == 'C' && inputString[4] == 'X') //to check ID { id = (inputString[1] - 48)*100 + (inputString[2] - 48)*10 + (inputString[3] - 48); checkTask = 2; Serial.print("Check ID..."); Serial.println(id); } else if(inputString == "ADDX") //add new fingerprint { Serial.println("Add fingerprint..."); checkTask = 1; } else if(inputString[0] == 'D' && inputString[4] == 'X') //delete fingerprint in memmory { id = (inputString[1] - 48)*100 + (inputString[2] - 48)*10 + (inputString[3] - 48); Serial.print("Delete template ID..."); Serial.println(id); checkTask = 3; } } } inputString = ""; } uint8_t readnumber(void) { uint8_t num = 0; while (num == 0) { while (! Serial.available()); num = Serial.parseInt(); } return num; } uint8_t getFingerprintID() { uint8_t p = finger.getImage(); switch (p) { case FINGERPRINT_OK: Serial.println("Image taken"); break; case FINGERPRINT_NOFINGER: Serial.println("No finger detected"); return p; case FINGERPRINT_PACKETRECIEVEERR: Serial.println("Communication error"); return p; case FINGERPRINT_IMAGEFAIL: Serial.println("Imaging error"); return p; default: Serial.println("Unknown error"); return p; } // OK success! p = finger.image2Tz(); switch (p) { case FINGERPRINT_OK: Serial.println("Image converted"); break; case FINGERPRINT_IMAGEMESS: Serial.println("Image too messy"); return p; case FINGERPRINT_PACKETRECIEVEERR: Serial.println("Communication error"); return p; case FINGERPRINT_FEATUREFAIL: Serial.println("Could not find fingerprint features"); return p; case FINGERPRINT_INVALIDIMAGE: Serial.println("Could not find fingerprint features"); return p; default: Serial.println("Unknown error"); return p; } // OK converted! p = finger.fingerSearch(); if (p == FINGERPRINT_OK) { Serial.println("Found a print match!"); } else if (p == FINGERPRINT_PACKETRECIEVEERR) { Serial.println("Communication error"); return p; } else if (p == FINGERPRINT_NOTFOUND) { Serial.println("Did not find a match"); return p; } else { Serial.println("Unknown error"); return p; } // found a match! Serial.print("Found ID #"); Serial.print(finger.fingerID); Serial.print(" with confidence of "); Serial.println(finger.confidence); return finger.fingerID; } uint8_t getFingerprintEnroll() { int p = -1; Serial.print("Waiting for valid finger to enroll as #"); Serial.println(id); while (p != FINGERPRINT_OK) { p = finger.getImage(); switch (p) { case FINGERPRINT_OK: Serial.println("Image taken"); break; case FINGERPRINT_NOFINGER: Serial.println("."); break; case FINGERPRINT_PACKETRECIEVEERR: Serial.println("Communication error"); break; case FINGERPRINT_IMAGEFAIL: Serial.println("Imaging error"); break; default: Serial.println("Unknown error"); break; } } // OK success! p = finger.image2Tz(1); switch (p) { case FINGERPRINT_OK: Serial.println("Image converted"); break; case FINGERPRINT_IMAGEMESS: Serial.println("Image too messy"); return p; case FINGERPRINT_PACKETRECIEVEERR: Serial.println("Communication error"); return p; case FINGERPRINT_FEATUREFAIL: Serial.println("Could not find fingerprint features"); return p; case FINGERPRINT_INVALIDIMAGE: Serial.println("Could not find fingerprint features"); return p; default: Serial.println("Unknown error"); return p; } Serial.println("Remove finger"); delay(2000); p = 0; while (p != FINGERPRINT_NOFINGER) { p = finger.getImage(); } Serial.print("ID "); Serial.println(id); p = -1; Serial.println("Place same finger again"); while (p != FINGERPRINT_OK) { p = finger.getImage(); switch (p) { case FINGERPRINT_OK: Serial.println("Image taken"); break; case FINGERPRINT_NOFINGER: Serial.print("."); break; case FINGERPRINT_PACKETRECIEVEERR: Serial.println("Communication error"); break; case FINGERPRINT_IMAGEFAIL: Serial.println("Imaging error"); break; default: Serial.println("Unknown error"); break; } } // OK success! p = finger.image2Tz(2); switch (p) { case FINGERPRINT_OK: Serial.println("Image converted"); break; case FINGERPRINT_IMAGEMESS: Serial.println("Image too messy"); return p; case FINGERPRINT_PACKETRECIEVEERR: Serial.println("Communication error"); return p; case FINGERPRINT_FEATUREFAIL: Serial.println("Could not find fingerprint features"); return p; case FINGERPRINT_INVALIDIMAGE: Serial.println("Could not find fingerprint features"); return p; default: Serial.println("Unknown error"); return p; } // OK converted! Serial.print("Creating model for #"); Serial.println(id); p = finger.createModel(); if (p == FINGERPRINT_OK) { Serial.println("Prints matched!"); } else if (p == FINGERPRINT_PACKETRECIEVEERR) { Serial.println("Communication error"); return p; } else if (p == FINGERPRINT_ENROLLMISMATCH) { Serial.println("Fingerprints did not match"); return p; } else { Serial.println("Unknown error"); return p; } Serial.print("ID "); Serial.println(id); p = finger.storeModel(id); if (p == FINGERPRINT_OK) { Serial.println("Stored!"); } else if (p == FINGERPRINT_PACKETRECIEVEERR) { Serial.println("Communication error"); return p; } else if (p == FINGERPRINT_BADLOCATION) { Serial.println("Could not store in that location"); return p; } else if (p == FINGERPRINT_FLASHERR) { Serial.println("Error writing to flash"); return p; } else { Serial.println("Unknown error"); return p; } return true; } uint8_t deleteFingerprint(uint8_t id) { uint8_t p = -1 p = finger.deleteModel(id); if (p == FINGERPRINT_OK) { Serial.println("Deleted!"); } else if (p == FINGERPRINT_PACKETRECIEVEERR) { Serial.println("Communication error"); } else if (p == FINGERPRINT_BADLOCATION) { Serial.println("Could not delete in that location"); } else if (p == FINGERPRINT_FLASHERR) { Serial.println("Error writing to flash"); } else { Serial.print("Unknown error: 0x"); Serial.println(p, HEX); } return p; } |
Thư viện sử dụng Adafruit_Fingerprint.h
Mình cấu hình sử dụng SoftwareSerial ở chân 2 và 3 của arduino Uno.
SoftwareSerial mySerial(2, 3);
Trong hàm loop mình cho mặc định chương trình sẽ chạy vòng quét kiểm tra vân tay từ cảm biến getFingerprintID()
Nếu không có vân tay chạm vào thì sẽ báo No finger detected
Trường hợp có vân tay chạm vào thì sẽ hiển thị các thông tin xử lý như image taken, image converted,…Kèm dữ liệu vân tay đó đã có lưu trữ trong bộ nhớ module cảm biến chưa, hay vân tay lạ. Ở dưới do vân tay mình đã thêm vào bộ nhớ với ID là 2 nên khi quét sẽ hiển thị thông tin ID được tìm thấy.
Thông số confidence biểu thị cho mức độ tin cậy khi so khớp giữa vân tay được quét và vân tay đã được lưu trữ trong bộ nhớ cảm biến. Giá trị càng cao thì càng tin cậy.
Ở code của mình sẽ có thêm 1 số chức năng như: thêm vân tay mới, xóa vân tay, kiểm tra vân tay,…
Mình có sử dụng sự kiện serialEvent() để bắt gói tin gửi qua serial để thực hiện các chức năng trên.
Cụ thể thêm mới vân tay theo lệnh serial “ADDX”, Hàm xử lý thêm vân tay getFingerprintEnroll()
Khi dùng lệnh ADDX thì nó sẽ bắt mình nhập ID cần lưu vào, sau khi nhập ID thì quá trình xử lý vân tay và lưu trữ bắt đầu thực thi như ảnh phía trên. Nhớ là lúc khi nhập ID thì bạn phải để ngón tay bạn vào cảm biến trước để nó quét xử lý nhé.
Kiểm tra ID vân tay đã tồn tại trong bộ nhớ hay chưa theo lệnh “C001X”, trong đó 001 là mã 3 ký tự chữ số của ID mình muốn kiểm tra. Hàm xử lý kiểm tra là finger.loadModel(id)
Xóa vân tay theo lệnh “D001X”, với 001 là mã 3 ký tự chữ số của ID mình muốn xóa. Hàm xóa vân tay deleteFingerprint(id)
Ngoài ra để xóa toàn bộ dữ liệu vân tay lưu trong bộ nhớ, có thể dùng cú pháp “D000X” sẽ xóa sạch bộ nhớ bằng lệnh finger.emptyDatabase()
3. Kết luận
Vậy là cũng đã xong bài chia sẻ hôm nay. Phần code lập trình của mình các bạn có thể tham khảo hay tùy biến lại theo ý các bạn, mình làm sơ sơ để test chạy nên có thể nó chưa được tinh gọn hay tối ưu, hi vọng nó sẽ giúp các bạn tiếp cận cảm biến AS608 nhanh gọn hơn. Trong thời gian sắp tới, mình sẽ cho ra bài viết tiếp theo PHẦN 2 về giao tiếp cảm biến vân tay AS608 này nhưng với Rasp Pi và có kết hợp xử lý lưu trữ trên database, phần này có vẻ nâng cao hơn với bài viết hiện tại. Các bạn hãy chờ đón nhé!
Chúc thành công!
Xem phần 2: https://tapit.vn/giao-tiep-cam-bien-nhan-dang-van-tay-as608-phan-2/
Tấn Lĩnh – ATOMA Technology