Trong bài viết hôm nay, cùng tuhoclaptrinhaz.com tìm hiểu cách tạo theo dõi thời gian vào/ra của sinh viên hoặc Hệ thống theo dõi thời gian của nhân viên dựa trên IoT bằng Module WiFi Nodemcu ESP8266, Cảm biến sinh vân tay AS608 , I2C- Mô-đun hiển thị Oled SSD1306 và Google Sheet.Cảm Biến Nhận Dạng Vân Tay AS608 Fingerprint Sensor
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).
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.
Thông số
kỹ thuật:
·
Điện áp sử dụng: 3.0~3.6VDC (thường cấp 3.3VDC, lưu ý quan
trọng nếu cấp lớn hơn 3.3VDC cảm biến sẽ cháy ngay lập tức).
·
Dòng tiêu thụ: 30~60mA, trung bình 40mA
·
Communication Interface: USB /UART
·
Tốc độ Baudrate UART: 9600 x N (N từ 1~12), mặc định
N=6 baudrate = 57600,8,1.
·
USB communication: 2.0 full speed
·
Sensor image size (pixel): 256 x 288 pixels
·
Image processing time (s): <0.4s
·
Power-on delay (s): <0.1s (the module needs about 0.1S
to initialize after power on)
·
Job search time (s): <0.3s
·
FRR (rejection rate) <1%
·
FAR (recognition rate) <0.001%
·
Fingerprint storage capacity 300 (ID: 0 ~ 299)
Sơ đồ
chân: Nhìn trực diện từ trái qua phải
1.
V+: chân cấp nguồn chính VCC 3.3VDC cho cảm biến hoạt động.
2.
Tx: Chân giao tiếp UART TTL TX
3.
Rx: Chân giao tiếp UART TTL RX
4.
GND: Chân cấp nguồn GND (Mass / 0VDC)
5.
TCH: Chân Output của cảm biến chạm Touch, khi chạm tay vào
cảm biến chân này sẽ xuất ra mức cao High, để sử dụng tính năng này cần cấp
nguồn 3.3VDC cho chân Va
6.
VA: Chân cấp nguồn 3.3VDC cho Touch Sensor.
7.
U+: Chân tín hiệu USB D+
8.
U-: Chân tín hiệu USB D-
Để giao
tiếp UART cần sử dụng các chân:
1.
V+: Cấp nguồn 3.3VDC
2.
Tx: nối với RX của Vi điều kiển (mức TTL từ 3.3~5VDC)
3.
Rx: nối với TX của Vi điều kiển (mức TTL từ 3.3~5VDC)
4.
GND: Cấp nguồn GND (Mass chung)
Để giao tiếp USB cần sử dụng các chân:
1. V+: Cấp nguồn 3.3VDC
2. U+: Chân tín hiệu USB D+
3. U-: Chân tín hiệu USB D-
4. GND: Cấp nguồn GND (Mass chung).
Cảm biến sinh trắc học điện dung R557 với ESP8266:
Dây VCC của cảm biến Vân tay được kết nối với Chân Nodemcu ESP8266
3.3V. Dây IRQ không được kết nối. Dây TXD và RXD được kết nối với chân D3 và D4. Và
dây GND được kết nối với chân GND của mô-đun WiFi Nodemcu
ESP8266.
Các chân GND và VDD của mô-đun màn hình OLED SSD1306 được kết nối với các chân 3,3V và GND của mô-đun WiFi Nodemcu ESP8266. Trong khi đó, các chân SCK hoặc SCL và SDA của mô-đun màn hình Oled được kết nối với các chân D1 và D2 của Mô-đun Nodemcu. D1 là SCL và D2 là SDA.
Phía bên trái là nguồn điện 5V được điều chỉnh dựa trên bộ điều chỉnh điện áp 7805. Đây là tùy chọn. Nếu bạn muốn cấp nguồn cho dự án của mình bằng máy tính xách tay hoặc PC thì không cần nguồn điện quy định 5V này. Nhưng nếu bạn muốn cấp nguồn bên ngoài cho dự án của mình bằng pin 12 v hoặc Bộ chuyển đổi thì bạn sẽ cần nguồn điện 5 volt được điều chỉnh này.
Cài đặt thư viện vân tay:
Bây giờ, bước tiếp theo là cài đặt Thư viện Arduino cho Cảm biến vân tay.
Để làm điều này, hãy mở Arduino IDE. Bấm vào Menu Sketch/Include Library/Manage Libraries.
Nhập vào thanh tìm kiếm từ Adafruit Fingerprint
Click vào nút cài đặt.
Bạn có thể thấy Thư viện cảm biến vân tay Adafruit của tôi hiện đã được cài đặt.
Tiếp theo, để đăng ký Vân tay, hãy kết nối mô-đun WiFi Nodemcu ESP8266 của bạn với Máy tính xách tay/PC và Tải lên bản code sau.
Code đăng ký vân tay:
#include <Adafruit_Fingerprint.h>
#if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__)
SoftwareSerial mySerial(D3, D4);
#else
// On Leonardo/M0/etc, others with hardware serial, use hardware serial!
// #0 is green wire, #1 is white
#define mySerial Serial1
#endif
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
uint8_t id;
void setup()
{
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);
}
uint8_t readnumber(void) {
uint8_t num = 0;
while (num == 0) {
while (! Serial.available());
num = Serial.parseInt();
}
return num;
}
void loop() // run over and over again
{
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() );
}
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;
}
Sau khi tải lên mã này; tiếp
" style="background: 0px 50%; border: 0px; box-sizing: border-box; font-weight: inherit; height: inherit; line-height: inherit; list-style: none; margin: 0px; outline: none; padding: 0px 5px; text-align: center;">210
#include <Adafruit_Fingerprint.h>
#if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__)
SoftwareSerial mySerial(D3, D4);
#else
// On Leonardo/M0/etc, others with hardware serial, use hardware serial!
// #0 is green wire, #1 is white
#define mySerial Serial1
#endif
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
uint8_t id;
void setup()
{
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);
}
uint8_t readnumber(void) {
uint8_t num = 0;
while (num == 0) {
while (! Serial.available());
num = Serial.parseInt();
}
return num;
}
void loop() // run over and over again
{
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() );
}
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;
}
Sau khi tải lên mã này; tiếp
" style="background: 0px 50%; border: 0px; box-sizing: border-box; font-weight: inherit; height: inherit; line-height: inherit; list-style: none; margin: 0px; outline: none; padding: 0px 5px; text-align: center;">210
#include <Adafruit_Fingerprint.h>
#if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__)
SoftwareSerial mySerial(D3, D4);
#else
// On Leonardo/M0/etc, others with hardware serial, use hardware serial!
// #0 is green wire, #1 is white
#define mySerial Serial1
#endif
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
uint8_t id;
void setup()
{
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);
}
uint8_t readnumber(void) {
uint8_t num = 0;
while (num == 0) {
while (! Serial.available());
num = Serial.parseInt();
}
return num;
}
void loop() // run over and over again
{
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() );
}
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;
}
Sau khi tải lên mã này; tiếp
" style="background: 0px 50%; border: 0px; box-sizing: border-box; font-weight: inherit; height: inherit; line-height: inherit; list-style: none; margin: 0px; outline: none; padding: 0px 5px; text-align: center;">210
#include <Adafruit_Fingerprint.h>
#if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__)
SoftwareSerial mySerial(D3, D4);
#else
// On Leonardo/M0/etc, others with hardware serial, use hardware serial!
// #0 is green wire, #1 is white
#define mySerial Serial1
#endif
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
uint8_t id;
void setup()
{
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);
}
uint8_t readnumber(void) {
uint8_t num = 0;
while (num == 0) {
while (! Serial.available());
num = Serial.parseInt();
}
return num;
}
void loop() // run over and over again
{
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() );
}
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;
}
Sau khi tải lên mã này; tiếp
theo hãy mở màn hình nối tiếp và làm theo hướng dẫn. Nếu bạn cảm thấy khó
khăn khi đăng ký ngón tay của mình thì bạn có thể làm theo video hướng dẫn của
tôi ở cuối bài viết này. Dù sao, tôi đã đăng ký hai ngón tay “ngón trỏ và
ngón giữa”. Tôi gán 3 làm ID cho ngón trỏ và 4 làm ID cho ngón giữa của mình. Một
ngón tay sẽ đại diện cho Fahad và ngón tay khác sẽ đại
diện cho Fawad . Bây giờ, hãy tiếp
tục và bắt đầu với Google Sheet để theo dõi thời gian.
Thiết lập Bảng tính Google:
Bạn sẽ cần phải thiết lập cẩn thận Bảng tính Google hoặc trang tính Google của mình để ghi lại dữ liệu cần thiết. Nếu bỏ lỡ bất cứ điều gì, bạn sẽ không thể kết nối nó với Mô-đun WiFi Nodemcu ESP8266 của mình. Tôi không sử dụng Bảng tính Google lần đầu tiên, tôi cũng đã sử dụng nó trong một số dự án khác. Vì vậy, để biết thêm thông tin về bảng tính Google, hãy xem các bài viết trước của tôi. Ngay bây giờ bạn có thể làm theo các bước chính xác tương tự.
Nhấp vào ứng dụng Google và nhấp vào Trang tính
Sau đó bấm vào dấu cộng để tạo bảng
trắng mới
Sau đó đặt tên cho trang tính và nhập ngày, giờ,
id và trạng thái.
Nhấp vào tiện
ích mở rộng
và nhấp vào Tập
lệnh ứng
dụng
Dán đoạn code sau thay thế cho đoạn code có sẵn:
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 | // Enter Spreadsheet ID here var SS = SpreadsheetApp.openById('Thay ID của Google Sheet vào đây'); var str = ""; function doPost(e) { var parsedData; var result = {}; try { parsedData = JSON.parse(e.postData.contents); } catch(f){ return ContentService.createTextOutput("Error in parsing request body: " + f.message); } if (parsedData !== undefined){ var flag = parsedData.format; if (flag === undefined){ flag = 0; } var sheet = SS.getSheetByName(parsedData.sheet_name); // sheet name to publish data // to is specified in Arduino code var dataArr = parsedData.values.split(","); // creates an array of the values to publish var date_now = Utilities.formatDate(new Date(), "CST", "yyyy/MM/dd"); // gets the current date var time_now = Utilities.formatDate(new Date(), "CST", "hh:mm:ss a"); // gets the current time var value0 = dataArr [0]; // value0 from Arduino code var value1 = dataArr [1]; // value1 from Arduino code var value2 = dataArr [2]; // value2 from Arduino code // read and execute command from the "payload_base" string specified in Arduino code switch (parsedData.command) { case "insert_row": sheet.insertRows(2); // insert full row directly below header text //var range = sheet.getRange("A2:D2"); // use this to insert cells just above the existing // data instead of inserting an entire row //range.insertCells(SpreadsheetApp.Dimension.ROWS); // use this to insert cells just above // the existing data instead of inserting an entire row sheet.getRange('A2').setValue(date_now); // publish current date to cell A2 sheet.getRange('B2').setValue(time_now); // publish current time to cell B2 sheet.getRange('C2').setValue(value0); // publish value0 from Arduino code to cell C2 sheet.getRange('D2').setValue(value1); // publish value1 from Arduino code to cell D2 sheet.getRange('E2').setValue(value2); // publish value2 from Arduino code to cell E2 str = "Success"; // string to return back to Arduino serial console SpreadsheetApp.flush(); break; case "append_row": var publish_array = new Array(); // create a new array publish_array [0] = date_now; // add current date to position 0 in publish_array publish_array [1] = time_now; // add current time to position 1 in publish_array publish_array [2] = value0; // add value0 from Arduino code to position 2 in publish_array publish_array [3] = value1; // add value1 from Arduino code to position 3 in publish_array publish_array [4] = value2; // add value2 from Arduino code to position 4 in publish_array sheet.appendRow(publish_array); // publish data in publish_array after the last row of data //in the sheet str = "Success"; // string to return back to Arduino serial console SpreadsheetApp.flush(); break; } return ContentService.createTextOutput(str); } // endif (parsedData !== undefined) else { return ContentService.createTextOutput("Error! Request body empty or in incorrect format."); } } |
Sau đó nhấp vào Deploy và nhấp vào New Development
Sau đó bấm vào kích hoạt các loại triển khai.
Bây giờ chọn triển khai dưới dạng web
Bây giờ chọn bất kỳ ai và nhấp vào triển khai
Bây giờ hãy chọn tài khoản mà bạn đã tạo trang tính Google.Bây giờ hãy nhấp vào đi tới ESP8266 và RFID với bảng Google không an toàn
Bây giờ hãy nhấp vào nút cho phép để cấp quyền truy cập vào tài khoản
Sau đó sao chép id triển khai
Dán id triển khai vào mã trên Arduino
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 348 349 350 351 352 353 354 | #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include <Adafruit_Fingerprint.h> #include <Arduino.h> #include <ESP8266WiFi.h> #include "HTTPSRedirect.h" #include <Wire.h> int u=0; int v=0; #if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__) SoftwareSerial mySerial(D3, D4); #else // On Leonardo/M0/etc, others with hardware serial, use hardware serial! // #0 is green wire, #1 is white #define mySerial Serial1 #endif Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); // Enter network credentials: const char* ssid = "Tên Wifi của bạn"; const char* password = "Mật khẩu wifi"; // Enter Google Script Deployment ID: const char *GScriptId = "Dán mã bảng tính vào vị trí này"; // Enter command (insert_row or append_row) and your Google Sheets sheet name // (default is Sheet1): String payload_base = "{\"command\": \"insert_row\", \"sheet_name\": \"Sheet1\", \"values\": "; String payload = ""; // Google Sheets setup (do not edit) const char* host = "script.google.com"; const int httpsPort = 443; const char* fingerprint = ""; String url = String("/macros/s/") + GScriptId + "/exec"; HTTPSRedirect* client = nullptr; // Declare variables that will be published to Google Sheets String user = ""; String id = ""; String enter =""; #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); void setup() { Serial.begin(9600); Serial.println('\n'); Serial.println("System initialized"); // Connect to WiFi WiFi.begin(ssid, password); Serial.print("Connecting to "); Serial.print(ssid); Serial.println(" ..."); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } Serial.println('\n'); Serial.println("Connection established!"); Serial.print("IP address:\t"); Serial.println(WiFi.localIP()); // Use HTTPSRedirect class to create a new TLS connection client = new HTTPSRedirect(httpsPort); client->setInsecure(); client->setPrintResponseBody(true); client->setContentTypeHeader("application/json"); Serial.print("Connecting to "); Serial.println(host); // Try to connect for a maximum of 5 times bool flag = false; for (int i=0; i<5; i++){ int retval = client->connect(host, httpsPort); if (retval == 1){ flag = true; Serial.println("Connected"); break; } else Serial.println("Connection failed. Retrying..."); } if (!flag){ Serial.print("Could not connect to server: "); Serial.println(host); return; } delete client; // delete HTTPSRedirect object client = nullptr; // delete HTTPSRedirect object display.begin(SSD1306_SWITCHCAPVCC, 0x3C); delay(2000); display.clearDisplay(); display.setTextColor(WHITE); delay(10); while (!Serial); // For Yun/Leo/Micro/Zero/... delay(100); Serial.println("\n\nAdafruit finger detect test"); // set the data rate for the sensor serial port finger.begin(57600); delay(5); 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(); if (finger.templateCount == 0) { Serial.print("Sensor doesn't contain any fingerprint data. Please run the 'enroll' example."); } else { Serial.println("Waiting for valid finger..."); Serial.print("Sensor contains "); Serial.print(finger.templateCount); Serial.println(" templates"); } } void loop() { // create some fake data to publish display.clearDisplay(); display.setTextSize(2); display.setCursor(0, 10); display.print("Waiting..."); display.display(); getFingerprintID(); } void updatesheet(String user, String id, String enter) { static bool flag = false; if (!flag){ client = new HTTPSRedirect(httpsPort); client->setInsecure(); flag = true; client->setPrintResponseBody(true); client->setContentTypeHeader("application/json"); } if (client != nullptr){ if (!client->connected()){ client->connect(host, httpsPort); } } else{ Serial.println("Error creating client object!"); } // Create json object string to send to Google Sheets payload = payload_base + "\"" + user + "," + id + "," + enter + "\"}"; // Publish data to Google Sheets Serial.println("Publishing data..."); Serial.println(payload); if(client->POST(url, host, payload)){ // do stuff here if publish was successful } else{ // do stuff here if publish was not successful Serial.println("Error while connecting"); } // a delay of several seconds is required before publishing again delay(5000); } 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"); finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_BLUE); finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_RED); 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(); Serial.println("finger print id"); Serial.println(p); if (p == FINGERPRINT_OK) { Serial.println("Found a print match!"); finger.LEDcontrol(FINGERPRINT_LED_FLASHING, 25, FINGERPRINT_LED_PURPLE, 10); delay(1000); if(finger.fingerID==3) { if(u==0) { display.clearDisplay(); display.setTextSize(2); display.setCursor(0, 10); display.print("Success"); display.display(); user="Fahad"; id="123"; enter="in"; updatesheet(user,id, enter); u=1; } else if(u==1) { display.clearDisplay(); display.setTextSize(2); display.setCursor(0, 10); display.print("Success"); display.display(); enter=""; user="Fahad"; id="123"; enter="out"; updatesheet(user,id, enter); u=0; } } if(finger.fingerID==4) { if(v==0) { display.clearDisplay(); display.setTextSize(2); display.setCursor(0, 10); display.print("Success"); display.display(); enter=""; user="Fawad"; id="123"; enter="in"; updatesheet(user,id, enter); v=1; } else if(v==1) { display.clearDisplay(); display.setTextSize(2); display.setCursor(0, 10); display.print("Success"); display.display(); enter=""; user="Fawad"; id="123"; enter="out"; updatesheet(user,id, enter); v=0; } } } else if (p == FINGERPRINT_PACKETRECIEVEERR) { Serial.println("Communication error"); return p; } else if (p == FINGERPRINT_NOTFOUND) { finger.LEDcontrol(FINGERPRINT_LED_FLASHING, 25, FINGERPRINT_LED_RED, 10); delay(1000); 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; } // returns -1 if failed, otherwise returns ID # int getFingerprintIDez() { uint8_t p = finger.getImage(); if (p != FINGERPRINT_OK) return -1; p = finger.image2Tz(); if (p != FINGERPRINT_OK) return -1; p = finger.fingerFastSearch(); if (p != FINGERPRINT_OK) return -1; // found a match! Serial.print("Found ID #"); Serial.print(finger.fingerID); Serial.print(" with confidence of "); Serial.println(finger.confidence); return finger.fingerID; } |
Đây là mã cuối cùng và đây là những thư viện tương tự mà tôi đã sử dụng trước đây. Nếu bạn so sánh mã này với mã dự án dựa trên bảng tính RFID và Google ; thì bạn sẽ hiểu rõ hơn về cách thức và lý do tôi thực hiện những thay đổi nhất định. Và một điều nữa, hãy giữ tất cả tệp mã chính, các tệp DebugMaros.h, HTTPSRedirect.cpp và HTTPSRedirect.h trong cùng một thư mục.
Dù sao đi nữa, hãy để tôi chỉ cho bạn cách tôi sử dụng ID ngón tay và những giá trị tôi đang gửi tới Google Trang tính.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | if(finger.fingerID==3) { if(u==0) { user="Fahad"; id="123"; enter="in"; updatesheet(user,id, enter); u=1; } else if(u==1) { enter=""; user="Fahad"; id="123"; enter="out"; updatesheet(user,id, enter); u=0; } } |
Nếu ID ngón tay == 3 và nếu u == 0 nghĩa là nếu người đó quét ngón tay của mình lần đầu tiên thì hãy gửi các giá trị này tới trang tính Google.
| user="Fahad"; id="123"; enter="in"; updatesheet(user,id, enter); |
Vì vậy, bằng cách sử dụng kỹ thuật tương tự, chúng ta có thể làm điều đó cho các sinh viên hoặc nhân viên khác.
Tôi đã tải chương trình này lên và bây giờ chúng ta hãy xem hoạt động của Trình theo dõi điểm danh trên Google Trang tính.
Ghi chú:
Nếu bạn thực hiện tất cả những điều này lần đầu tiên và bạn không biết cách sử dụng mô-đun màn hình OLED SSD1306. Cách cài đặt bo mạch WiFi Nodemcu ESP8266 trong Arduino IDE. Sau đó tôi thực sự khuyên bạn nên đọc bài viết của tôi trên.
Hiện tại, Mô-đun WiFi và Máy tính xách tay Nodemcu ESP8266 của tôi đã được kết nối với WiFi. Tôi cũng xin nói với bạn rằng, không nhất thiết phải sử dụng cùng một mạng WiFi, bạn có thể sử dụng các mạng WiFi khác nhau. Đó là một dự án IoT, bạn có thể theo dõi thời gian ra/vào của nhân viên hoặc học sinh từ bất kỳ nơi nào trên thế giới. Bạn có thể thấy không có kết nối vật lý nào giữa Nodemcu ESP8266 và Máy tính xách tay của tôi.
Mô-đun hiển thị Oled là tùy chọn, nếu bạn loại bỏ mô-đun này, nó sẽ không ảnh hưởng gì đến dự án. Nhưng sử dụng màn hình cũng tốt, vì nếu không có màn hình bạn sẽ bối rối và không chắc liệu ngón tay có được quét thành công hay không. Hiện tại, trên mô-đun màn hình Oled, bạn có thể thấy thông báo đang chờ… điều này có nghĩa là bạn có thể quét ngón tay của mình. Khi quét thành công ngón tay, thông báo Thành công sẽ được in trên màn hình.
Nguồn sưu tầm tham khảo:
1. https://www.electroniclinic.com/esp8266-pn532-rfid-and-google-spreadsheet-based-in-out-time-tracking-system/
2. https://www.electroniclinic.com/google-sheet-attendance-tracker-using-esp8266-biometric-sensor-r557/#Google_Sheet_Attendance_Tracker
Đăng nhận xét