1

I have the following fingerprint sensor: Rugged Panel Mount Fingerprint Sensor with Bi-Color LED Ring [R503] : ID 4651 : $39.95 : Adafruit Industries, Unique & fun DIY electronics and kits Also during the enrollment process, it keeps waiting till the user places the finger and completes the enrollment. Due to this piece of code : while (! getFingerprintEnroll() ) is there a way that I could put a timer for 60 seconds and if there is no enrollment within that time exit that function?

Can someone please help me with that. Thanks!

Below is the code

#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>
#include <Bounce2.h> // https://github.com/thomasfredericks/Bounce2
#include <EEPROM.h>

//#define WHITE_LED 43

//D v16 debounce algorithm
Bounce2::Button button = Bounce2::Button(); // INSTANTIATE A Button OBJECT
#define BUTTON_PIN 7 // WE WILL attach() THE BUTTON TO THE FOLLOWING PIN IN setup()


//D v15 for audrino to connect to fingerprint sensor
//D v2
#if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__)
// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino  (WHITE wire)
// Set up the serial port to use softwareserial..
SoftwareSerial mySerial(2, 4);

#else
// On Leonardo/M0/etc, others with hardware serial, use hardware serial!
// #0 is green wire, #1 is white
#define mySerial Serial1

#endif

//D v15 for audrino to connect to display
#if defined(ARDUINO_FEATHER_ESP32) // Feather Huzzah32
#define TFT_CS         14
#define TFT_RST        15
#define TFT_DC         32

#elif defined(ESP8266)
#define TFT_CS         4
#define TFT_RST        16
#define TFT_DC         5

#else
// For the breakout board, you can use any 2 or 3 pins.
// These pins will also work for the 1.8" TFT shield.
#define TFT_CS        10
#define TFT_RST        9 // Or set to -1 and connect to Arduino RESET pin
#define TFT_DC         8
#endif


Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);


// OPTION 1 (recommended) is to use the HARDWARE SPI pins, which are unique
// to each board and not reassignable. For Arduino Uno: MOSI = pin 11 and
// SCLK = pin 13. This is the fastest mode of operation and is required if
// using the breakout board's microSD card.

// For 1.44" and 1.8" TFT with ST7735 use:
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

// For 1.14", 1.3", 1.54", and 2.0" TFT with ST7789:
//Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);


// OPTION 2 lets you interface the display using ANY TWO or THREE PINS,
// tradeoff being that performance is not as fast as hardware SPI above.
//#define TFT_MOSI 11  // Data out
//#define TFT_SCLK 13  // Clock out

// For ST7735-based displays, we will use this call
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

// OR for the ST7789-based displays, we will use this call
//Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);


// D v15 need to add the following section back to determine the steps and the adc value
//DONT DELETE THE FOLLOWING SECTION
/*
  //D v1
  int readPin=A4;
  int V2=0; //D v5, v2-> analog voltage read by the pin
  int V1=0; //D v5, v1-> v2 converted into feet/hr
  int delayTime=500;

  //D v6
  int batt_ref_pin=A6; // D v6-> pin A6 connected to the vesc temp pin
  int battery_ref=80; // D v6-> comparing it to less than 0.3V
  int low_batt;
*/

//D v16 this to detect it the switch is on or off state.. if high then searching(default) and if low then enrolling
const int DIN_PIN = 7;

//D v8.. initialize sum with 1 and ID with 1
int sum1 = 0; //D v8 initilally put that as 1, so when it went into the sum(), it started as print 2 and not print 1, so modifying that to 0
int sum();
int id = 1;

//D v19 storing data in eeprom, so need extra variables to stores those data
int addr1 = 0; // D v19 storing the value of sum1 in this addr. initally started with 0 value
int var1 = 0; //D v19 storing the value which is retrieved from sum1 and then comparing to see if it is 0 (when the code runs for the first time) and nth number when running it for n-1 time
int var2 = 0; //D v19 storing the value which is retrieved from addr1 and then comparing to see if it is 0 (when the code runs for the first time) and nth number when running it for n-1 time
int addr2 = 205; //D v19 constant address where I can store and read data from.. this is used to write the data to sum and read it back
int addr3 = 206; //D v19 constant address where I can store and read data from.. this is used to write the data to addr1 and read it back

//D v20 stop the fingerprint enrolling after 60 seconds
unsigned long myTime;
unsigned long myTime60 = 60001;

void setup() {

  //D v16 debounce algo
  button.attach( BUTTON_PIN, INPUT ); // USE EXTERNAL PULL-UP
  button.interval(5);// DEBOUNCE INTERVAL IN MILLISECONDS
  button.setPressedState(HIGH); // INDICATE THAT THE LOW STATE CORRESPONDS TO PHYSICALLY PRESSING THE BUTTON // code modifed from Low to high in order to make the fingerprint sensor work

  pinMode( DIN_PIN, INPUT_PULLUP );
  tft.initR(INITR_144GREENTAB); // Init ST7735R chip, green tab

  // OR use this initializer (uncomment) if using a 1.3" or 1.54" 240x240 TFT:
  //tft.init(240, 240);           // Init ST7789 240x240

  // tft print function!
  tftPrintTest();


  //D v2
  Serial.begin(9600);
  /*while (!Serial);  // For Yun/Leo/Micro/Zero/...
    delay(100);*/ // Adding these 2 lines breaks the clue and does not display half of the code below it
  /*Serial.println("\n\nAdafruit finger detect test nAdafruit Fingerprint sensor enrollment");*/


  // set the data rate for the sensor serial port
  finger.begin(57600);
  delay(5);
  if (finger.verifyPassword()) {
    // tft.println("Found fingerprint sensor!");
  } else {
    tft.println("Did not find fingerprint sensor :(");
    while (1) {
      delay(1);
    }
  }

  //arcada.display->println(F("sensor parameters"));
  finger.getParameters();
  finger.getTemplateCount();

  if (finger.templateCount == 0) {
    // arcada.display->print("Sensor doesn't contain any fingerprint data. Please run the 'enroll' example.");
  }
  else {
    //arcada.display->println("Waiting for valid finger...");
  }
}

void loop() {
  button.update();// D v16 debounce algo
  int value;
  value = digitalRead( DIN_PIN );
  tft.setTextColor(ST77XX_GREEN);
  tft.setCursor(0, 10);

  //D v16 make a pin work as a button press


  getFingerprintID();
  delay(50);
  //D v6 button A pressed
  if ( value == HIGH && button.pressed()) {
    /*  tft.setTextWrap(false);
      tft.fillScreen(ST77XX_BLACK);*/

    //D v18 added this scetion to avoid overwrite of data when the fringer print sensor is searching for data and user presses a button
    delay(100);
    tft.setCursor(0, 0);
    tft.fillScreen(ST77XX_BLACK);
    getFingerprintID();
    delay(50);

    //D v16 need to remove the comment from  line below
    //tft.println("Ready to enroll!");

    //D v6 removing this section. So it will always enroll as ID 1
    //Serial.println("Please type in the ID # (from 1 to 127) you want to save this finger as...");

    id = sum(); //D v8 calling this function to mention the ID number
    tft.println("Enrolling ID # ");
    tft.println(id);

    //D v20
    myTime = millis();
    if ((unsigned long)(myTime60 - myTime) >= 1)
    {
      //while (!  getFingerprintEnroll() );
      getFingerprintEnroll();
    }
    else {}
  }
  //D v6 button B pressed
  else {
    /*     tft.setTextWrap(false);
      tft.fillScreen(ST77XX_BLACK);*/
    Serial.begin(9600);
    /* while (!Serial);  // For Yun/Leo/Micro/Zero/...
      delay(100);*/ // Adding these 2 lines breaks the clue and does not display half of the code below it
    /*  delay(500);
      tft.setCursor(0, 0);
      tft.fillScreen(ST77XX_BLACK);*/
    tft.println("fingerprnt detect tst");

    // set the data rate for the sensor serial port
    finger.begin(57600);
    delay(5);
    if (finger.verifyPassword()) {
      /*  delay(500);
        tft.setCursor(0, 0);
        tft.fillScreen(ST77XX_BLACK);*/
      tft.println("Found fingerSensor");
    } else {
      tft.println("Did not find fingerprint sensor :(");
      while (1) {
        delay(1);
      }
    }

    //arcada.display->println(F("sensor parameters"));
    finger.getParameters();
    finger.getTemplateCount();

    if (finger.templateCount == 0) {
      // arcada.display->print("Sensor doesn't contain any fingerprint data. Please run the 'enroll' example.");
    }
    else {
      tft.println("Waiting for valid finger...");
      /*    delay(50);
        tft.setCursor(0, 0);
        tft.fillScreen(ST77XX_BLACK);*/

      // arcada.display->print("Sensor contains "); arcada.display->print(finger.templateCount); arcada.display->println(" templates");
    }
  }
}

// D v6 enroll fingerprint
uint8_t getFingerprintEnroll() {

  int p = -1;
  // arcada.display->println("Waiting for valid finger to enroll as 1"); /*Serial.println(id); */ // D v6 commenting this line
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        tft.println("Image taken");
        break;
      case FINGERPRINT_NOFINGER:
        //tft.println(".");
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        tft.println("Communication error");
        break;
      case FINGERPRINT_IMAGEFAIL:
        tft.println("Imaging error");
        break;
      default:
        tft.println("Unknown error");
        break;
    }
  }

  // OK success!

  p = finger.image2Tz(1);
  switch (p) {
    case FINGERPRINT_OK:
      //tft.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      tft.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      tft.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      tft.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      tft.println("Could not find fingerprint features");
      return p;
    default:
      tft.println("Unknown error");
      return p;
  }

  tft.println("Remove finger");
  delay(2000);
  p = 0;
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  Serial.print("ID 1"); /*Serial.println(id); */// D v6 commenting this line
  p = -1;
  tft.println("Place finger again");
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        tft.println("Image taken");
        break;
      case FINGERPRINT_NOFINGER:
        // tft.println(".");
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        tft.println("Communication error");
        break;
      case FINGERPRINT_IMAGEFAIL:
        tft.println("Imaging error");
        break;
      default:
        tft.println("Unknown error");
        break;
    }
  }

  // OK success!

  p = finger.image2Tz(2);
  switch (p) {
    case FINGERPRINT_OK:
      //  tft.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      tft.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      tft.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      tft.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      tft.println("Could not find fingerprint features");
      return p;
    default:
      tft.println("Unknown error");
      return p;
  }

  // OK converted!
  p = finger.createModel();
  if (p == FINGERPRINT_OK) {
    tft.println("Prints matched!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    tft.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_ENROLLMISMATCH) {
    tft.println("Fingerprints did not match");
    delay(500);
    // delay(500);
    tft.setCursor(0, 0);
    tft.fillScreen(ST77XX_BLACK);
    return p;
  } else {
    tft.println("Unknown error");
    return p;
  }

  tft.print("ID # "); tft.print(id); // D v6 commenting this line
  p = finger.storeModel(id); // D v6 commenting this line
  if (p == FINGERPRINT_OK) {
    {
      int sum();
    }
    tft.println("Stored!");
    delay(1500);
    tft.setCursor(0, 0);
    tft.fillScreen(ST77XX_BLACK);
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    tft.println("Communication error");
    delay(500);
    tft.setCursor(0, 0);
    tft.fillScreen(ST77XX_BLACK);
    return p;
  } else if (p == FINGERPRINT_BADLOCATION) {
    tft.println("Could not store in that location");
    return p;
  } else if (p == FINGERPRINT_FLASHERR) {
    tft.println("Error writing to flash");
    return p;
  } else {
    tft.println("Unknown error");
    return p;
  }
  return true;
}



// D v6 search fingerprint
uint8_t getFingerprintID() {
  uint8_t p = finger.getImage();
  switch (p) {
    case FINGERPRINT_OK:
      // tft.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      tft.println("No finger detected");

      //arcada.display->setTextColor(ARCADA_RED); // D v4
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      //tft.println("Communication error");
      return p;
    case FINGERPRINT_IMAGEFAIL:
      //tft.println("Imaging error");
      return p;
    default:
      // tft.println"Unknown error");
      return p;
  }

  // OK success!

  p = finger.image2Tz();
  switch (p) {
    case FINGERPRINT_OK:
      //tft.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      //tft.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      //tft.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      //tft.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      //tft.println("Could not find fingerprint features");
      return p;
    default:
      // tft.println("Unknown error");
      return p;
  }

  // OK converted!
  p = finger.fingerSearch();
  if (p == FINGERPRINT_OK) {
    tft.setCursor(0, 60);
    tft.println("Found print match!");
    /*    delay(5000);
      tft.setCursor(0, 0);
      tft.fillScreen(ST77XX_BLACK);*/
    //arcada.display->setTextColor(ARCADA_GREEN); // D v4
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    //tft.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_NOTFOUND) {
    tft.println("Unknown fingerprnt");
    //arcada.display->setTextColor(ARCADA_BLUE); // D v4
    return p;
  } else {
    //tft.println("Unknown error");
    return p;
  }

  // found a match!
  //tft.print("Found ID #"); tft.print(finger.fingerID);
  //tft.print(" with confidence of "); tft.print(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!
  //tft.print("Found ID #"); tft.print(finger.fingerID);
  //tft.print(" with confidence of "); tft.print(finger.confidence);
  return finger.fingerID;
}

void tftPrintTest() {
  tft.setTextWrap(true);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(1);
  // tft.println("Hello World!");
}

//D v8 function to start counting the ID number
/*int sum()
  {
  sum1=sum1+1;
  EEPROM.write(sum1, sum1);
  return sum1;
  }*/

//D v19 updating the above logic to store data in eeprom and retrieving the data after reset or poweroff.. Refer to page 27, 28 for code and flowchart
//EEPROM data from : https://roboticsbackend.com/arduino-store-int-into-eeprom/   , https://www.norwegiancreations.com/2017/02/using-eeprom-to-store-data-on-the-arduino/
//https://roboticsbackend.com/how-to-save-values-on-arduino-with-eeprom/     , audrino forum and adafruit forum,
// EEPROM get(): https://www.arduino.cc/en/Reference/EEPROMGet   ; EEPROM put(): https://www.arduino.cc/en/Reference/EEPROMPut ; EEPROM read and write: https://randomnerdtutorials.com/arduino-eeprom-explained-remember-last-led-state/
int sum()
{
  var1 = EEPROM.read(addr2); // D v19 read the value from addr 205 and see if it has any ID already stored in it
  var2 = EEPROM.read(addr3); // D v19 read the value from addr 205 and see if it has any ID already stored in it

  if (var1 != 0 && var2 != 0) // D v19 check if this code is running for the first time. If yes then the ID should be set to sum1 and addr1 would be 0, so that ID is 1. If not continue from where it was left
  {
    sum1 = var1;
    addr1 = var2;
  }
  else
  {
    sum1 = 0;
    addr1 = 0;
  }

  sum1 = sum1 + 1;
  addr1 = addr1 + 1;
  EEPROM.write(addr1, sum1); //D v19 store the ID value in the corresponding addr
  EEPROM.write(addr2, sum1); // D v19 store the sum1 value in address 205
  EEPROM.write(addr3, addr1); // D v19 store the addr1 value in address 205
  return sum1;
}
2
  • 1
    yes there is a way ... hint: monitor the value of millis()
    – jsotola
    Jun 24 at 22:18
  • Hi @jsotola: I have done that but that doesn't fix the issue. Below is the snippet of the code where I have written it myTime = millis(); if ((unsigned long)(myTime60 - myTime) >= 1) { //while (! getFingerprintEnroll() ); getFingerprintEnroll(); }
    – Dave
    Jun 25 at 13:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.