How to Detect a Fingerprint with Optical Sensor (JM-101)

jm101

In this tutorial, I am going to show how you can use a JM-101 fingerprint optical sensor with ES8266 NodeMCU.

Parts Required

JM-101 Fingerprint Module

JM-101 fingerprint module is an integrated fingerprint processing module that integrates optical path and fingerprint processing. It has the characteristics of small size, low power consumption and simple interface. You can find more details about this module here.
JM-101 module supports USB and UART communication interfaces. In this tutorial, we will be using UART communication.

Building the Circuit and Schematic

Step 1: Start by connecting all together following the schematic below. And then connect your NodeMCU to your PC through an USB cable.

Adding a fingerprint to the system

Step 2: Open your Arduino IDE and create a new project. If you are using Arduino IDE to program ESP8266 modules for the first time, please complete Step 1, Step 2, Step 3 and Step 4 from my previous tutorial “ESP8266 NodeMCU – Blinking a LED“.

Step 3: We will be using the adafruit library about their fingerprint sensors. You can download the library .zip file from here. And then add this library to your project.

Step 4: Since NodeMCU only has one serial port that will be in use to debug with Arduino terminal we need to use “SoftwareSerial” that will be using interrupts in order to react like a real serial port. To do this we will be using the “espsoftwareserial” library that you can download from here and install like in Step 3.

Step 5: Once we have added these two libraries to our Arduino IDE we will paste the code below in our project and upload it to your NodeMCU. The code below is based on “enrol” example from adafruit library.

#include <Adafruit_Fingerprint.h>
#include <SoftwareSerial.h>

SoftwareSerial mySerial(13, 15, false, 256);

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

uint8_t id;

void setup()  
{
  Serial.begin(9600);
  while (!Serial);
  delay(100);
  Serial.println("\n\nAdafruit Fingerprint sensor enrollment");
  finger.begin(57600);
  
  if (finger.verifyPassword()) {
    Serial.println("Found fingerprint sensor!");
  } else {
    Serial.println("Did not find fingerprint sensor :(");
    while (1) { delay(1); }
  }
}

uint8_t readnumber(void) {
  uint8_t num = 0;
  
  while (num == 0) {
    while (! Serial.available());
    num = Serial.parseInt();
  }
  return num;
}

void loop()                     
{
  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;
  }   
}

Step 6: After uploading the code open the serial monitor. You will be asked to enter a number between 1 and 127 (this number will be the identifier of your fingerprint). Write the number “1” and click “Enter”. Now the system will be waiting to you to put your finger in the sensor…

Step 7: Put the finger you want to save the fingerprint in the sensor. Then you will be asked to put the same finger in the sensor again (to check if it matches). If the prints match your fingerprint will be stored with the respective ID 1 that you enter previously.

Step 8: Repeat the Step 6 and Step 7 to store a different fingerprint with the ID “2”.

Using the added fingerprints to switch ON/OFF a LED

Step 9: Create a new Arduino project, paste the code below and upload it to your NodeMCU. The code below is based on the “fingerprint” example from adafruit library.

#include <Adafruit_Fingerprint.h>
#include <SoftwareSerial.h>

SoftwareSerial mySerial(13, 15, false, 256);

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

uint8_t id;

const int led = 16; //GPIO5

void setup()  
{
  pinMode(led, OUTPUT);
  Serial.begin(9600);
  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);
  
  if (finger.verifyPassword()) {
    Serial.println("Found fingerprint sensor!");
  } else {
    Serial.println("Did not find fingerprint sensor :(");
    while (1) { delay(1); }
  }

  finger.getTemplateCount();
  Serial.print("Sensor contains "); Serial.print(finger.templateCount); Serial.println(" templates");
  Serial.println("Waiting for valid finger...");
}

void loop()                     // run over and over again
{
  getFingerprintIDez();
  delay(50);            //don't ned to run this at full speed.
}

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.fingerFastSearch();
  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;
}

// 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);

  if(finger.fingerID==1 && finger.confidence>100){
    digitalWrite(led, HIGH);
  }
  if(finger.fingerID==2 && finger.confidence>100){
    digitalWrite(led, LOW);
  }
  
  return finger.fingerID; 
}

Step 10: After uploading the code open the serial monitor. The system should inform you that the sensor contains 2 templates (the 2 fingerprints saved previously) and will be waiting for you to put one of the saved fingerprints on the sensor.

Step 11: If you use the finger saved with ID 1 and the sensor recognize it with confidence above 100, the built-in LED of the NodeMCU will turn ON. If you use the finger saved with ID 2 and the sensor recognize it with confidence above 100 the built-in LED will turn OFF. For example, you can replace the switch of the LED with an electrical door lock, using a relay as we used in the previous tutorial.

27 thoughts on “How to Detect a Fingerprint with Optical Sensor (JM-101)

  1. Howdy! This post couldn’t be written any better!
    Reading this post reminds me of my old room mate! He always kept chatting about this.

    I will forward this post to him. Fairly certain he will have a good
    read. Thank you for sharing!

  2. Compiler Error:

    Arduino: 1.8.1 (Windows 10), Board: “NodeMCU 1.0 (ESP-12E Module), 80 MHz, Flash, Disabled, 4M (no SPIFFS), v2 Lower Memory, Disabled, None, Only Sketch, 115200”

    sketch_may14b:6: error: ‘amp’ was not declared in this scope

    Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

    ^

    sketch_may14b:6: error: ‘mySerial’ does not name a type

    Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

    ^

    Multiple libraries were found for “SoftwareSerial.h”
    Used: C:\Users\ASUS\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\libraries\SoftwareSerial
    Not used: C:\Users\ASUS\Downloads\arduino-1.8.1\libraries\espsoftwareserial-master
    exit status 1
    ‘amp’ was not declared in this scope

    This report would have more information with
    “Show verbose output during compilation”
    option enabled in File -> Preferences.

  3. I am getting an error, the finger.verifyPassword() always fails hence we get “Did not find fingerprint sensor” , if I comment this section we are getting Communication error in the looping statement. Can anyone help me ?

  4. Hi, question! does anyone have an idea what’s wrong if jm-101 needs to reconect vcc after reading 1 finger.

  5. Im getting this “Unknown error”:
    Place same finger again
    ………………Image taken
    Image converted
    Creating model for #1
    Unknown error

    Can someone please help me?

    Anyway thank you for the tutorial!

  6. Oi boa tarde como faço para usar biometria com sensor de presença para acionar uma bomba d´água e uma válvula solenoide passando num sensor de fluxo no tempo de 5 minuto no máximo por cada digital? consegue ajudar nesse projeto?

  7. Hello
    I made it with wemos r1 mini on D5 (gpio14) and D6 (gpio12) pins and 5V
    I had the same issue with communication error and unknown error.
    Just add delay(100); after each Serial.Println in Loop part of the sketch.
    good luck

  8. Good web site! I truly love how it is simple on my eyes and the data are well written. I am wondering how I could be notified whenever a new post has been made. I’ve subscribed to your feed which must do the trick! Have a great day!

  9. para los interesados en el codigo publicado aparece un &mySerial lo que provoca un error
    en el compilador y esto se debe a que en html & es el & osea hay que cambiar & por &

  10. I simply could not depart your website before suggesting that I actually enjoyed the usual information an individual provide on your visitors? Is going to be again ceaselessly in order to check out new posts.

Leave a Reply to pene tamano Cancel reply

Your email address will not be published. Required fields are marked *

Ads Blocker Image Powered by Code Help Pro

Ads Blocker Detected!!!

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.