www.tuhoclaptrinhaz.com
Kênh Youtube

Hướng dẫn kết nối cảm biến vân tay và ESP8266 lưu trên Google Sheet

28/01/2024

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.3VDClư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).

Cm biến sinh trc hc đin dung R557 vi ESP8266:

Dây VCC ca cm biến Vân tay được kết ni vi Chân Nodemcu ESP8266 3.3V. Dây IRQ không được kết ni. Dây TXD và RXD được kết ni vi chân D3 và D4. Và dây GND được kết ni vi chân GND ca mô-đun WiFi Nodemcu ESP8266.

Các chân GND và VDD ca mô-đun màn hình OLED SSD1306 được kết ni vi các chân 3,3V và GND ca mô-đun WiFi Nodemcu ESP8266. Trong khi đó, các chân SCK hoc SCL và SDA ca mô-đun màn hình Oled được kết ni vi các chân D1 và D2 ​​ca Mô-đun Nodemcu. D1 là SCL và D2 ​​là SDA.

Phía bên trái là ngun đin 5V được điu chnh da trên b điu chnh đin áp 7805. Đây là tùy chn. Nếu bn mun cp ngun cho d án ca mình bng máy tính xách tay hoc PC thì không cn ngun đin quy đnh 5V này. Nhưng nếu bn mun cp ngun bên ngoài cho d án ca mình bng pin 12 v hoc B chuyn đi thì bn s cn ngun đin 5 volt được điu chnh này.

Cài đt thư vin vân tay:

Bây gi, bước tiếp theo là cài đt Thư vin Arduino cho Cm biến vân tay.

Đ làm điu này, hãy m Arduino IDE. Bm 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.

Bn có th thy Thư vin cm biến vân tay Adafruit ca tôi hin đã được cài đt.

Tiếp theo, đ đăng ký Vân tay, hãy kết ni mô-đun WiFi Nodemcu ESP8266 ca bn vi Máy tính xách tay/PC và Ti lên bn 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 lp Bng tính Google:

Bn s cn phi thiết lp cn thn Bng tính Google hoc trang tính Google ca mình đ ghi li d liu cn thiết. Nếu b l bt c điu gì, bn s không th kết ni nó vi Mô-đun WiFi Nodemcu ESP8266 ca mình. Tôi không s dng Bng tính Google ln đu tiên, tôi cũng đã s dng nó trong mt s d án khác. Vì vy, đ biết thêm thông tin v bng tính Google, hãy xem các bài viết trước ca tôi. Ngay bây gi bn có th làm theo các bước chính xác tương t.

Nhp vào ng dng Google và nhp vào Trang tính




Sau đó bm vào dấu cộng để tạo bảng trắng mới


Sau đó đt tên cho trang tính và nhp ngày, gi, id và trng thái.


Nhp vào tin ích m rng và nhp vào Tp lnh ng dng


Dán đon 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

Đâ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.

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.

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