Help with using menu widget

Hello all! Although I have been browsing the forum for the last couple months I have been working on a project and ran into a dead end. What I am creating is an admin portal for a fingerprint scanning program. When finished I would like the menu to control all functionalities of my program for a scan, enroll, and delete mode. I had it partially working with a switch widget using a virtual pin with 0 min 1 max. If the switch was passing 0, the program would be in enroll mode, 1 was scan mode(so I had the switch controlling the loops). I added a button image widget as another virtual pin to delete the database with 0 min and 1 max. I wanted the button to start a loop that asked the user to put in a keypad password from a 4x4 keypad matrix and delete if correct or exit the loop if it was wrong. The program wasn’t waiting for keypad input as it would sync the switch and go straight back to that loop without performing the rest of the deletion loop. So, I decided that being that I had purchased the membership I should just use the menu widget instead. I created a virtual pin for the menu, V0, with 0 min and 2 max for the 3 options I wanted. Currently case 2 has nothing because I wanted to get my scanning modules working first before messing with the database deletion again. I am stuck because now when I run the code nothing happens. It initializes the fingerprint scanner and stops there without using any of the cases from the menu. Any suggestions?

Equipment:
Adafruit rugged fingerprint scanner
Arduino Mega 2560 R3
ESP 8266 wifi shield
Arduino 4x4 matrix keypad

Code:

// BLYNK template setup code
#define BLYNK_TEMPLATE_ID "TMPL07nDhxvy"
#define BLYNK_TEMPLATE_NAME "Arduino Uno Fingerprint Scanner"
#define BLYNK_AUTH_TOKEN "k6bccbIipGLrb-AZBJ4lBSuKG8gBqaJi"


/* Comment this out to disable prints and save space */
//#define BLYNK_PRINT Serial

// Initialize the libraries needed for the code
#include <Adafruit_Fingerprint.h>
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
#include <Keypad.h>

//Keypad code
const int ROW_NUM = 4;     // Four rows
const int COLUMN_NUM = 4;  // Four columns
char keys[ROW_NUM][COLUMN_NUM] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};
byte pin_rows[ROW_NUM] = { 28, 26, 24, 22 };       // Connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = { 29, 27, 25, 23 };  // Connect to the column pinouts of the keypad

Keypad keypad = Keypad(makeKeymap(keys), pin_rows, pin_column, ROW_NUM,
                       COLUMN_NUM);

// Length of password + 1 for null character
#define Password_Length 6
// Character to hold password input
char Data[Password_Length];
//Password
char Master[Password_Length] = "C001*";
// Counter for character entries
byte data_count = 0;
// Character to hold key input
char Key;

// WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "xxxxxxx";
char pass[] = "xxxxxx";

// Define the serials for communication
#define EspSerial Serial2          // Serial for ESP8266
#define FingerprintSerial Serial1  // Serial for Fingerprint Sensor

WidgetTerminal terminal(V1);

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&FingerprintSerial);

uint8_t static fid = 1;
bool clearterm = true;
bool enrollMode = false;
bool enrollStep1 = true;
bool enrollStep2 = true;
bool enrollStep3 = true;
bool enrollStep4 = true;
bool noFing = true;
bool scanningMode = false;
bool scanningSuccess = true;
bool scanningFailed = true;
bool eoi = true;
bool idleMode = false;

uint8_t readnumber(void) {
  uint8_t num = 0;

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

// ESP8266 baud rate:
#define ESP8266_BAUD 38400
ESP8266 wifi(&EspSerial);

// Enroll mode for fingerprint scanner
uint8_t getFingerprintEnroll() {

  int p = -1;
  Serial.print("Waiting for valid finger to enroll as #");
  Serial.println(fid);

  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println("Image taken");
        break;
      case FINGERPRINT_NOFINGER:
        Serial.println(".");
        return p;
      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;
  }
  enrollStep1 = false;
  while (!removeFingerPrompt()) { ; }

  Serial.println("Remove finger");
  delay(2000);
  p = 0;
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  Serial.print("ID ");
  Serial.println(fid);
  p = -1;
  enrollStep2 = false;
  while (!placeFingerPrompt()) { ; }
  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;
    }
  }
  enrollStep3 = false;
  while (!removeFingerPrompt2()) { ; }
  delay(1000);
  // 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(fid);

  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(fid);
  p = finger.storeModel(fid);
  if (p == FINGERPRINT_OK) {
    Serial.println("Stored!");
    enrollMode = false;
    delay(1000);
  } 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;
  }
  enrollStep4 = false;
  while (!enrollSuccess()) { ; }
  fid++;

  return true;
}

// Scanning mode for fingerprint scanner
uint8_t getFingerprintID() {
  finger.getTemplateCount();

  if (finger.templateCount == 0) {
    noFing = false;
    while (!noFinger()) { ; }
    Serial.print("Sensor doesn't contain any fingerprint data. Please run the 'enroll' example.");
  }
  uint8_t p = finger.getImage();
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.println("No finger detected");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("Imaging error");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  // OK success!

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

  // OK converted!
  p = finger.fingerSearch();
  if (p == FINGERPRINT_OK) {
    Serial.println("Found a print match!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_NOTFOUND) {
    scanningFailed = false;
    while (!scanFailed()) { ; }
    Serial.println("Did not find a match");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }

  // found a match!
  scanningSuccess = false;
  while (!scanSuccess()) { ; }
  Serial.print("Found ID #");
  Serial.print(finger.fingerID);
  Serial.print(" with confidence of ");
  Serial.println(finger.confidence);

  return finger.fingerID;
}

boolean CLEARTERMINAL() {
  if (!clearterm) {
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    clearterm = true;
  }
  return true;
}

boolean noFinger() {
  if (!noFing) {
    Blynk.virtualWrite(V1, "Sensor doesn't contain any fingerprint data. Please run the 'enroll' example.");
    finger.LEDcontrol(FINGERPRINT_LED_FLASHING, 25, FINGERPRINT_LED_RED, 10);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_RED);
    noFing = true;
  }
  return true;
}

boolean removeFingerPrompt() {
  if (!enrollStep1) {
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
    Blynk.virtualWrite(V1, "Remove finger");
    Blynk.virtualWrite(V1, "Prepare to place same finger again when prompted");
    enrollStep1 = true;
  }
  return true;
}

boolean placeFingerPrompt() {
  if (!enrollStep2) {
    finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_PURPLE);
    Blynk.virtualWrite(V1, "Place the same finger again");
    enrollStep2 = true;
  }
  return true;
}

boolean removeFingerPrompt2() {
  if (!enrollStep3) {
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
    Blynk.virtualWrite(V1, "Remove finger");
    enrollStep3 = true;
  }
  return true;
}

boolean enrollSuccess() {
  if (!enrollStep4) {
    String fing = String(fid);
    finger.LEDcontrol(FINGERPRINT_LED_FLASHING, 25, FINGERPRINT_LED_PURPLE, 10);
    Blynk.virtualWrite(V1, "Successfully enrolled fingerprint id #" + fing);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
    enrollStep4 = true;
  }
  return true;
}

boolean scanSuccess() {
  if (!scanningSuccess) {
    Blynk.virtualWrite(V1, "Print found, success!");
    scanningSuccess = true;
    finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_BLUE);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_BLUE);
  }
  return true;
}

boolean scanFailed() {
  if (!scanningFailed) {
    Blynk.virtualWrite(V1, "Print not found, Failed");
    finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_RED);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_RED);
  }
  return true;
}

boolean Exit() {
  if (!eoi) {
    Key = keypad.getKey();
    if (Key) {
      Data[data_count] = Key;
      Blynk.virtualWrite(V1, Data[data_count]);
      data_count++;
    }
    if (data_count == Password_Length - 1) {
      if (!strcmp(Data, Master)) {
        // Password is correct
        Blynk.virtualWrite(V1, "Correct");
        Blynk.virtualWrite(V1, "Deleting fingerprint database");
        finger.LEDcontrol(FINGERPRINT_LED_BREATHING, 100, FINGERPRINT_LED_RED);
        delay(2000);
        finger.emptyDatabase();
        Blynk.virtualWrite(V1, "Database deleted");
        Blynk.virtualWrite(V1, "To return to desired mode, switch mode button on admin dashboard/application. If needed switch again.");
        finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_RED);
        fid = 1;
      } else {
        // Password is incorrect
        Blynk.virtualWrite(V1, "Incorrect Password");
        delay(1000);
      }
    }
    clearData();
    eoi = true;
  }
  return true;
}

void clearData() {
  // Go through array and clear data
  while (data_count != 0) {
    Data[data_count--] = 0;
  }
  return;
}

BLYNK_WRITE(V0)  // Virual pin to switch enroll and scanning loop
{
  Blynk.syncVirtual(V0);
  switch (param.asInt()) {  // Get status of V0.
    String fing = String(fid);
    case 0:  //Enroll Mode
      {
        Serial.println(" test");
        if (!enrollMode) {
          clearterm = false;
          while (!CLEARTERMINAL()) { ; }
          scanningMode = false;
          idleMode = false;
          finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
          Blynk.virtualWrite(V1, "To switch modes please use switch on admin dashboard/application.");
          Blynk.virtualWrite(V1, "If switching modes, please be patient as this process could take up to 30 seconds.");
          Blynk.virtualWrite(V1, "If you would like to wipe the database, press the delete button.");
          Blynk.virtualWrite(V1, "Ready to enroll a fingerprint!");
          Serial.print("Enrolling ID #");
          Blynk.virtualWrite(V1, "Enrolling ID #" + fing);
          Serial.println(fid);
          Blynk.virtualWrite(V1, "Waiting for valid finger to enroll as #" + fing);
          finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_PURPLE);
          enrollMode = true;
        }
        while (!getFingerprintEnroll())
          ;
        delay(300);
        break;
      }
    case 1:
      {
        if (!scanningMode) {
          clearterm = false;
          while (!CLEARTERMINAL()) { ; }
          enrollMode = false;
          idleMode = false;
          finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
          Blynk.virtualWrite(V1, "To switch modes please use switch on admin dashboard/application.");
          Blynk.virtualWrite(V1, "If switching modes, please be patient as this process could take up to 30 seconds.");
          Blynk.virtualWrite(V1, "If you would like to wipe the database, press the delete button.");
          Blynk.virtualWrite(V1, "Scanning, waiting for fingerprint.");
          scanningMode = true;
        }
        getFingerprintID();
        delay(300);
        break;
      }
    case 2:
      {

        break;
      }
    default:
      Blynk.virtualWrite(V1, "Please make a selection.");
  }
}

void setup() {
  // Debug console
  Serial.begin(115200);

  // Set ESP8266 baud rate
  Serial2.begin(ESP8266_BAUD);
  delay(10);

  Blynk.begin(BLYNK_AUTH_TOKEN, wifi, ssid, pass, "blynk.cloud", 80);

  // set the data rate for the sensor serial port
  finger.begin(57600);

  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.print("Sensor contains ");
    Serial.print(finger.templateCount);
    Serial.println(" templates");
  }
}

void loop() {
  Blynk.run();
  // You can inject your own code or combine it with other sketches.
  // Check other examples on how to communicate with Blynk. Remember
  // to avoid delay() function!
}

Thank you!

The very first thing you MUST do is to remove these from your void loop.

Then, it would really help if you explained what widget types you are using at the moment (as opposed to in the previous version), what the functionality of these widgets are, which datastreams they are attached to, and how those datastreams are configured (data types, min/max values etc).

Pete.

1 Like

Hey Pete,

Just removed them, thank you. I added them in trying to fix the code earlier. Sorry for not being clear enough. Instead of using a button and a switch I am now using ONLY a menu. I have the terminal there just to update the user throughout the process as virtual pin V1. The menu is datastream virtual pin V0 with a minimum value of 0 and a maximum value of 2. Basically I want the menu to handle which loop is running besides using the switch and button as that was giving me issues. Case 0 is meant to be the enrollment mode of the fingerprint scanner. Case 1 is meant to be the scanning mode (just waiting to see if the finger placed was enrolled and in the database. Finally, case 2 is meant to be to delete the database which I have the code for its just empty right now. I was just interested in getting the menu working all together before I add that and probably break it even more lol.

Appreciate the fast response.

I’m guessing that your problem is this line of code in your BLYNK_WRITE(V0) callback function…

Your BLYNK_WRITE(V0) callback is triggered when the value of the menu widget attached to datastram V0 changes - i.e when you dirty the V0 value by selecting a different menu option.
It can also be triggered by calling Blynk.syncAll() (provided your V0 datastream has the “Sync with latest server value every time device connects to the cloud” option enabled) or by calling Blynk.syncVirtual(V0)

So, when you change the menu widget value BLYNK_WRITE(V0) is triggered, which then immediately calls Blynk.syncVirtual(V0) which triggers BLYNK_WRITE(V0) again, so the first two lines of code in BLYNK_WRITE(V0) are creating an endless loop.
Except, Blynk.syncVirtual(V0) isn’t processed until the next Blynk.run() is encountered, so who know what sort of messed-up program flow this is creating.

Clearly, you are trying to loop the BLYNK_WRITE(V0) function, and this isn’t how its meant to be used.

Instead, you need to use BLYNK_WRITE(V0) to set a global variable and nothing else.
Then, use a BlynkTimer to call a function which checks this global variable and takes the appropriate action. The timer is then causing the loop, rather than you trying to artificially loop the BLYNK_WRITE(V0) callback.

You need to add a BLYNK_CONNECTED() callback that contains Blynk.syncVirtual(V0) to get the value of your V0 datastream when your devices first connects to Blynk, to save you having to manually dirty the menu value.

You have lots of other dodgy things going off, like your CLEARTERMINAL() function. Why dont you simply use terminal.clear() ?

Also, you need to avoid the use of blocking while and delay commands with Blynk, asd these prevent Blynk.run() being executed on a regular basis, which will cause disconnections from the Blynk server.

I also have no idea what this…

is doing at the top of your BLYNK_WRITE(V0) callback, but I doubt if it’s doing what you intend it to.

Pete.

Hey Peter,

Thanks again.

String fing = String(fid);

I am using this pass the “fid” through the terminal. The “fid” is the finger id number which is an integer. I was having issues trying to pass the integer through the terminal so the user would see what number the fingerprint was associated with. To get around that I was changing the int to a string with this line.

I used the CLEARTERMINAL() function because when I used terminal.clear() or Blynk.virtualWrite(V1, “clr”) which were two things I saw people around the forum, they would just write “clr” into the terminal and not actually clear it. So I made that funky function just to empty the text from the terminal.

I will look into including a timer and callback function and let you know how that goes.

But at tie point when you are doing this, you don’t yet have a valid fingerprint scanned.

So are you saying that terminal.clear() is not working correctly?

Pete.

I initialize the fingerprint id “fid” using:

String fing = String(fid);

Once the finger is successfully scanned it will add 1 and continue to enroll finger 2. I am not too concerned with overwriting existing ones upon restart.

Yes, terminal.clear() was just outputting “clr” as text into the terminal for me, not actually clearing the terminal. If I get the menu working with I can show you.

uint8_t static fid = 1;
I meant to quote this, not the one I quoted above.

Still doesn’t make any sense to me.

Pete.

It’s a variable for the adafruit sensor, just an integer. In the example sketch for enrolling fingerprints, it just initializes that variable without a value and the user chooses a number by typing into the serial monitor. I was having trouble getting user input from the terminal instead of the serial monitor so I decided to set the variable to 1 and add 1 to it each time a finger was successfully enrolled.

[Unformatted code removed by moderator]

Sorry if I am unclear. I am pretty new to this stuff, especially working with this many libraries and different pieces of equipment. Can you point me to an example of a good timer and callback function to use?

When you post code to the forum it needs to have triple backticks at the beginning and end, not blockquotes.

and that’s my point. at the point when the code I quoted is called, this has not happened.

I can see that. All of the stuff you’re doing with workarounds on top of workarounds inst helping you, its just making your code more complex. The lack of in-code documentation and the use of obscure variable names doesn’t help either.

Not specifically about what you’re trying to do, but a good primer nonetheless…

Reading this may also help…

Pete.

Pete,

Thanks to you I have finally made some progress with this menu widget. I tried to clean my code up some by adding additional comments and removing some functions that I am not using at the moment. Currently, here’s what I have:

// BLYNK template setup code
#define BLYNK_TEMPLATE_ID "TMPL07nDhxvy"
#define BLYNK_TEMPLATE_NAME "Arduino Uno Fingerprint Scanner"
#define BLYNK_AUTH_TOKEN "k6bccbIipGLrb-AZBJ4lBSuKG8gBqaJi"


/* Comment this out to disable prints and save space */
//#define BLYNK_PRINT Serial

// Initialize the libraries needed for the code
#include <Adafruit_Fingerprint.h>      // Fingerprint scanner
#include <ESP8266_Lib.h>               // Wifi shield
#include <BlynkSimpleShieldEsp8266.h>  //Blynk wifi
#include <Keypad.h>                    // 4x4 Keypad

// 4x4 Keypad matrix
const int ROW_NUM = 4;     // Four rows
const int COLUMN_NUM = 4;  // Four columns
char keys[ROW_NUM][COLUMN_NUM] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};
byte pin_rows[ROW_NUM] = { 28, 26, 24, 22 };       // Connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = { 29, 27, 25, 23 };  // Connect to the column pinouts of the keypad

Keypad keypad = Keypad(makeKeymap(keys), pin_rows, pin_column, ROW_NUM,
                       COLUMN_NUM);

// Length of password + 1 for null character
#define Password_Length 6
// Character to hold password input
char Data[Password_Length];
//Password
char Master[Password_Length] = "C001*";
// Counter for character entries
byte data_count = 0;
// Character to hold key input
char Key;

// WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "xxxxxx";
char pass[] = "xxxxx";

// Define the serials for communication
#define EspSerial Serial2          // Serial for ESP8266
#define FingerprintSerial Serial1  // Serial for Fingerprint Sensor

WidgetTerminal terminal(V1);  // Blynk terminal widget datastream V1
BlynkTimer timer;             // Blynk timer

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&FingerprintSerial);  //Define fingerprint Scanner

uint8_t static fid = 1;       // Variable for finger ID *STARTS WITH 1 NO MATTER WHAT*
bool isFirstConnect = true;   // Flag to check if blynk was connected
bool clearterm = true;        // Flag to clear terminal
bool enrollMode = false;      // Flag for enrollment mode
bool enrollStep1 = true;      // Flag for step 1 of enrollment
bool enrollStep2 = true;      // Flag for step 2 of enrollment
bool enrollStep3 = true;      // Flag for step 3 of enrollment
bool enrollStep4 = true;      // Flag for step 4 of enrollment
bool noFing = true;           //Flag for no fingerprints in database
bool scanningMode = false;    //Flag for scanning mode
bool scanningSuccess = true;  //Flag for successful scan
bool scanningFailed = true;   //Flag for failed scan

uint8_t readnumber(void) {
  uint8_t num = 0;

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

// ESP8266 baud rate:
#define ESP8266_BAUD 38400
ESP8266 wifi(&EspSerial);

// Enroll mode for fingerprint scanner
uint8_t getFingerprintEnroll() {

  int p = -1;
  Serial.print("Waiting for valid finger to enroll as #");
  Serial.println(fid);

  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println("Image taken");
        break;
      case FINGERPRINT_NOFINGER:
        Serial.println(".");
        return p;
      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;
  }
  enrollStep1 = false;                 // Set enrollment step 1 flag
  while (!removeFingerPrompt()) { ; }  // Finger was successfully scanned for step 1, call removeFingerPrompt

  Serial.println("Remove finger");
  delay(2000);
  p = 0;
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  Serial.print("ID ");
  Serial.println(fid);
  p = -1;
  enrollStep2 = false;                // Set enrollment step 2 flag
  while (!placeFingerPrompt()) { ; }  //  Image was successfully converted, call placeFingerPrompt
  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;
    }
  }
  enrollStep3 = false;                  // Set enrollment step 3 flag
  while (!removeFingerPrompt2()) { ; }  // Finger was successfully processed, call removeFingerPrompt2
  delay(1000);
  // 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(fid);

  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(fid);
  p = finger.storeModel(fid);
  if (p == FINGERPRINT_OK) {
    Serial.println("Stored!");
    enrollMode = false;
    delay(1000);
  } 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;
  }
  enrollStep4 = false;            // Set enrollment step 4 flag
  while (!enrollSuccess()) { ; }  // Enrollment was successful, call enrollSuccess
  fid++;                          // Increase finger ID #

  return true;
}

// Scanning mode for fingerprint scanner
uint8_t getFingerprintID() {
  finger.getTemplateCount();

  if (finger.templateCount == 0) {
    noFing = false;            // Set no finger flag
    while (!noFinger()) { ; }  // No fingerprints enrolled, call noFinger
    Serial.print("Sensor doesn't contain any fingerprint data. Please run the 'enroll' example.");
  }
  uint8_t p = finger.getImage();
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.println("No finger detected");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("Imaging error");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  // OK success!

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

  // OK converted!
  p = finger.fingerSearch();
  if (p == FINGERPRINT_OK) {
    Serial.println("Found a print match!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_NOTFOUND) {
    scanningFailed = false;
    while (!scanFailed()) { ; }
    Serial.println("Did not find a match");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }

  // Found a match!
  scanningSuccess = false;      // Set flag for successful scan
  while (!scanSuccess()) { ; }  //  Successful scan, call scanSuccess
  Serial.print("Found ID #");
  Serial.print(finger.fingerID);
  Serial.print(" with confidence of ");
  Serial.println(finger.confidence);

  return finger.fingerID;
}

// Clear Blynk Terminal
boolean CLEARTERMINAL() {
  if (!clearterm) {
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    clearterm = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when scanning mode is initialized without any fingerprints enrolled.
boolean noFinger() {
  if (!noFing) {
    Blynk.virtualWrite(V1, "Sensor doesn't contain any fingerprint data. Please run the 'enroll' example.");
    finger.LEDcontrol(FINGERPRINT_LED_FLASHING, 25, FINGERPRINT_LED_RED, 10);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_RED);
    noFing = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when the user needs to remove their finger to continue the enrollment process.
boolean removeFingerPrompt() {
  if (!enrollStep1) {
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
    Blynk.virtualWrite(V1, "Remove finger");
    Blynk.virtualWrite(V1, "Prepare to place same finger again when prompted");
    enrollStep1 = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when the user needs to place their finger again to continue the enrollment process.
boolean placeFingerPrompt() {
  if (!enrollStep2) {
    finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_PURPLE);
    Blynk.virtualWrite(V1, "Place the same finger again");
    enrollStep2 = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when the user needs to remove their finger to finish the enrollment process.
boolean removeFingerPrompt2() {
  if (!enrollStep3) {
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
    Blynk.virtualWrite(V1, "Remove finger");
    enrollStep3 = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when the enrollment process was a success.
boolean enrollSuccess() {
  if (!enrollStep4) {
    String fing = String(fid);
    finger.LEDcontrol(FINGERPRINT_LED_FLASHING, 25, FINGERPRINT_LED_PURPLE, 10);
    Blynk.virtualWrite(V1, "Successfully enrolled fingerprint id #" + fing);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
    enrollStep4 = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when there was a successful scan in the scanning mode.
boolean scanSuccess() {
  if (!scanningSuccess) {
    Blynk.virtualWrite(V1, "Print found, success!");
    scanningSuccess = true;
    finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_BLUE);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_BLUE);
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when there was a failed scan in the scanning mode.
boolean scanFailed() {
  if (!scanningFailed) {
    Blynk.virtualWrite(V1, "Print not found, Failed");
    finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_RED);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_RED);
  }
  return true;
}

// Callback function to check V0 status
void V0check() {
  Blynk.syncVirtual(V0);
}

// Callback function to check if the blynk was connected
// BLYNK_CONNECTED() {
//   if (isFirstConnect) {
//     Blynk.syncVirtual(V0);
//     isFirstConnect = false;
//   }
// }

BLYNK_WRITE(V0)  // Menu widget
{
  int index = param.asInt();  // Get status of V0.
  String fing = String(fid);  // Create fing to set fid to a string in order to pass through terminal.
  switch (index) {            // Switch selections
    case 1:                   // Enroll mode
      {
        if (!enrollMode) {
          clearterm = false;
          while (!CLEARTERMINAL()) { ; }
          scanningMode = false;
          finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
          Blynk.virtualWrite(V1, "To switch modes please use switch on admin dashboard/application.");
          Blynk.virtualWrite(V1, "If switching modes, please be patient as this process could take up to 30 seconds.");
          Blynk.virtualWrite(V1, "If you would like to wipe the database, press the delete button.");
          Blynk.virtualWrite(V1, "Ready to enroll a fingerprint!");
          Serial.print("Enrolling ID #");
          Blynk.virtualWrite(V1, "Enrolling ID #" + fing);
          Serial.println(fid);
          Blynk.virtualWrite(V1, "Waiting for valid finger to enroll as #" + fing);
          finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_PURPLE);
          enrollMode = true;
        }
        while (!getFingerprintEnroll())
          ;
        delay(300);
        break;
      }
    case 2:  // Scanning mode
      {
        if (!scanningMode) {
          clearterm = false;
          while (!CLEARTERMINAL()) { ; }
          enrollMode = false;
          finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
          Blynk.virtualWrite(V1, "To switch modes please use switch on admin dashboard/application.");
          Blynk.virtualWrite(V1, "If switching modes, please be patient as this process could take up to 30 seconds.");
          Blynk.virtualWrite(V1, "If you would like to wipe the database, press the delete button.");
          Blynk.virtualWrite(V1, "Scanning, waiting for fingerprint.");
          scanningMode = true;
        }
        getFingerprintID();
        delay(300);
        break;
      }
    case 3:
      {
        break;
      }
    default:  // If there is no selection
      Blynk.virtualWrite(V1, "Please make a selection.");
  }
}

void setup() {
  // Debug console
  Serial.begin(115200);

  // Set ESP8266 baud rate
  Serial2.begin(ESP8266_BAUD);
  delay(10);

  // Blnk auth tokens
  Blynk.begin(BLYNK_AUTH_TOKEN, wifi, ssid, pass, "blynk.cloud", 80);

  // Set the data rate for the sensor serial port
  finger.begin(57600);

  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.print("Sensor contains ");
    Serial.print(finger.templateCount);
    Serial.println(" templates");
  }
  timer.setInterval(5000L, V0check);  // Timer interval, every 5 seconds
}

void loop() {
  Blynk.run();
  timer.run();
  // You can inject your own code or combine it with other sketches.
  // Check other examples on how to communicate with Blynk. Remember
  // to avoid delay() function!
}

I had to comment out the BLYNK_CONNECTED() because when I had that in there it would skip the initialization of the fingerprint scanner and it would not work. With that commented out, it works… but very patchy I guess is the word. It takes a couple seconds for the fingerprint scanner to detect a finger now. Additionally, if there isn’t a finger on the scanner for either case 1 or 2, after about 3 seconds of waiting it will begin to return “communication error” in the serial monitor which is one of the error escapes from getFingerprintEnroll(). This will happen at any step of the enrollment process or scanning proccess. It WILL work if I leave my finger on the scanner for a few seconds, but I’m not sure whats triggering the error. It does switch modes very quickly though.

Many Thanks

Correction, it only outputs the communication error once you enter the getFingerprintEnroll() while statement. Basically once it detects a finger and passes the enrollStep1 while waiting for a finger it will output the error.

I dont think youve taken onboard anything I’ve said so far.

You have to stop calling Blynk.suncVirtual(V0) from within your main code.
This command should be called once only, at startup.

And your BLYNK_WRITE(V0) should contain around two lines of code:

  1. get the incoming value from the menu widget and assign it to a GLOBAL variable
  2. call a new function which contains all of the code currently in BLYNK_WRITE(V0). This line of code is optional, as your new function will be called by a BlynkTimer, but saves you having to wait while the timer kicks-in.

Pete.

Sorry, now I believe I understand what you mean. Everything above this is the same, I just added a function called modeSelection() above the V0check().

void modeSelection() {
  String fing = String(fid);  // Create fing to set fid to a string in order to pass through terminal.
  switch (index) {            // Switch selections
    case 1:                   // Enroll mode
      {
        if (!enrollMode) {
          clearterm = false;
          while (!CLEARTERMINAL()) { ; }
          scanningMode = false;
          finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
          Blynk.virtualWrite(V1, "To switch modes please use switch on admin dashboard/application.");
          Blynk.virtualWrite(V1, "If switching modes, please be patient as this process could take up to 30 seconds.");
          Blynk.virtualWrite(V1, "If you would like to wipe the database, press the delete button.");
          Blynk.virtualWrite(V1, "Ready to enroll a fingerprint!");
          Serial.print("Enrolling ID #");
          Blynk.virtualWrite(V1, "Enrolling ID #" + fing);
          Serial.println(fid);
          Blynk.virtualWrite(V1, "Waiting for valid finger to enroll as #" + fing);
          finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_PURPLE);
          enrollMode = true;
        }
        while (!getFingerprintEnroll())
          ;
        delay(300);
        break;
      }
    case 2:  // Scanning mode
      {
        if (!scanningMode) {
          clearterm = false;
          while (!CLEARTERMINAL()) { ; }
          enrollMode = false;
          finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
          Blynk.virtualWrite(V1, "To switch modes please use switch on admin dashboard/application.");
          Blynk.virtualWrite(V1, "If switching modes, please be patient as this process could take up to 30 seconds.");
          Blynk.virtualWrite(V1, "If you would like to wipe the database, press the delete button.");
          Blynk.virtualWrite(V1, "Scanning, waiting for fingerprint.");
          scanningMode = true;
        }
        getFingerprintID();
        delay(300);
        break;
      }
    case 3:
      {
        break;
      }
    default:  // If there is no selection
      Blynk.virtualWrite(V1, "Please make a selection.");
  }
}

// Callback function to check V0 status
void V0check() {
  modeSelection();
}

// Callback function to check if the blynk was connected
BLYNK_CONNECTED() {
  if (isFirstConnect) {
    Blynk.syncVirtual(V0);
    isFirstConnect = false;
  }
}

BLYNK_WRITE(V0)  // Menu widget
{
  index = param.asInt();  // Get status of V0.
  modeSelection();  
}

void setup() {
  // Debug console
  Serial.begin(115200);

  // Set ESP8266 baud rate
  Serial2.begin(ESP8266_BAUD);
  delay(10);

  // Blnk auth tokens
  Blynk.begin(BLYNK_AUTH_TOKEN, wifi, ssid, pass, "blynk.cloud", 80);

  // Set the data rate for the sensor serial port
  finger.begin(57600);

  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.print("Sensor contains ");
    Serial.print(finger.templateCount);
    Serial.println(" templates");
  }
  timer.setInterval(5000L, V0check);  // Timer interval, every 5 seconds
}

void loop() {
  Blynk.run();
  timer.run();
  // You can inject your own code or combine it with other sketches.
  // Check other examples on how to communicate with Blynk. Remember
  // to avoid delay() function!
}

I tried to implement this and I am having the same issue as I did before when I had BLYNK_CONNECTED() uncommented. It seems to never initialize the fingerprint scanner and it gets stuck in a loop outputting “communication error”.

Please post the full sketch, not snippets.

Posting the actual seral output, formatted with triple backticks, would probably provide more insight into the issue than the information you’ve provided so far.

Pete.

Okay. Sorry for making this rough for you :man_facepalming:

// BLYNK template setup code
#define BLYNK_TEMPLATE_ID "TMPL07nDhxvy"
#define BLYNK_TEMPLATE_NAME "Arduino Uno Fingerprint Scanner"
#define BLYNK_AUTH_TOKEN "k6bccbIipGLrb-AZBJ4lBSuKG8gBqaJi"


/* Comment this out to disable prints and save space */
//#define BLYNK_PRINT Serial

// Initialize the libraries needed for the code
#include <Adafruit_Fingerprint.h>      // Fingerprint scanner
#include <ESP8266_Lib.h>               // Wifi shield
#include <BlynkSimpleShieldEsp8266.h>  //Blynk wifi
#include <Keypad.h>                    // 4x4 Keypad

// 4x4 Keypad matrix
const int ROW_NUM = 4;     // Four rows
const int COLUMN_NUM = 4;  // Four columns
char keys[ROW_NUM][COLUMN_NUM] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};
byte pin_rows[ROW_NUM] = { 28, 26, 24, 22 };       // Connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = { 29, 27, 25, 23 };  // Connect to the column pinouts of the keypad

Keypad keypad = Keypad(makeKeymap(keys), pin_rows, pin_column, ROW_NUM,
                       COLUMN_NUM);

// Length of password + 1 for null character
#define Password_Length 6
// Character to hold password input
char Data[Password_Length];
//Password
char Master[Password_Length] = "C001*";
// Counter for character entries
byte data_count = 0;
// Character to hold key input
char Key;

// WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "xxxxxx";
char pass[] = "xxxxxx";

// Define the serials for communication
#define EspSerial Serial2          // Serial for ESP8266
#define FingerprintSerial Serial1  // Serial for Fingerprint Sensor

WidgetTerminal terminal(V1);  // Blynk terminal widget datastream V1
BlynkTimer timer;             // Blynk timer

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&FingerprintSerial);  //Define fingerprint Scanner

uint8_t static fid = 1;       // Variable for finger ID *STARTS WITH 1 NO MATTER WHAT*
bool isFirstConnect = true;   // Flag to check if blynk was connected
bool clearterm = true;        // Flag to clear terminal
bool enrollMode = false;      // Flag for enrollment mode
bool enrollStep1 = true;      // Flag for step 1 of enrollment
bool enrollStep2 = true;      // Flag for step 2 of enrollment
bool enrollStep3 = true;      // Flag for step 3 of enrollment
bool enrollStep4 = true;      // Flag for step 4 of enrollment
bool noFing = true;           //Flag for no fingerprints in database
bool scanningMode = false;    //Flag for scanning mode
bool scanningSuccess = true;  //Flag for successful scan
bool scanningFailed = true;   //Flag for failed scan
int index;

uint8_t readnumber(void) {
  uint8_t num = 0;

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

// ESP8266 baud rate:
#define ESP8266_BAUD 38400
ESP8266 wifi(&EspSerial);

// Enroll mode for fingerprint scanner
uint8_t getFingerprintEnroll() {

  int p = -1;
  Serial.print("Waiting for valid finger to enroll as #");
  Serial.println(fid);

  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println("Image taken");
        break;
      case FINGERPRINT_NOFINGER:
        Serial.println(".");
        return p;
      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;
  }
  enrollStep1 = false;                 // Set enrollment step 1 flag
  while (!removeFingerPrompt()) { ; }  // Finger was successfully scanned for step 1, call removeFingerPrompt

  Serial.println("Remove finger");
  delay(2000);
  p = 0;
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  Serial.print("ID ");
  Serial.println(fid);
  p = -1;
  enrollStep2 = false;                // Set enrollment step 2 flag
  while (!placeFingerPrompt()) { ; }  //  Image was successfully converted, call placeFingerPrompt
  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;
    }
  }
  enrollStep3 = false;                  // Set enrollment step 3 flag
  while (!removeFingerPrompt2()) { ; }  // Finger was successfully processed, call removeFingerPrompt2
  delay(1000);
  // 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(fid);

  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(fid);
  p = finger.storeModel(fid);
  if (p == FINGERPRINT_OK) {
    Serial.println("Stored!");
    enrollMode = false;
    delay(1000);
  } 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;
  }
  enrollStep4 = false;            // Set enrollment step 4 flag
  while (!enrollSuccess()) { ; }  // Enrollment was successful, call enrollSuccess
  fid++;                          // Increase finger ID #

  return true;
}

// Scanning mode for fingerprint scanner
uint8_t getFingerprintID() {
  finger.getTemplateCount();

  if (finger.templateCount == 0) {
    noFing = false;            // Set no finger flag
    while (!noFinger()) { ; }  // No fingerprints enrolled, call noFinger
    Serial.print("Sensor doesn't contain any fingerprint data. Please run the 'enroll' example.");
  }
  uint8_t p = finger.getImage();
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.println("No finger detected");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("Imaging error");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  // OK success!

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

  // OK converted!
  p = finger.fingerSearch();
  if (p == FINGERPRINT_OK) {
    Serial.println("Found a print match!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_NOTFOUND) {
    scanningFailed = false;
    while (!scanFailed()) { ; }
    Serial.println("Did not find a match");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }

  // Found a match!
  scanningSuccess = false;      // Set flag for successful scan
  while (!scanSuccess()) { ; }  //  Successful scan, call scanSuccess
  Serial.print("Found ID #");
  Serial.print(finger.fingerID);
  Serial.print(" with confidence of ");
  Serial.println(finger.confidence);

  return finger.fingerID;
}

// Clear Blynk Terminal
boolean CLEARTERMINAL() {
  if (!clearterm) {
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    clearterm = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when scanning mode is initialized without any fingerprints enrolled.
boolean noFinger() {
  if (!noFing) {
    Blynk.virtualWrite(V1, "Sensor doesn't contain any fingerprint data. Please run the 'enroll' example.");
    finger.LEDcontrol(FINGERPRINT_LED_FLASHING, 25, FINGERPRINT_LED_RED, 10);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_RED);
    noFing = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when the user needs to remove their finger to continue the enrollment process.
boolean removeFingerPrompt() {
  if (!enrollStep1) {
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
    Blynk.virtualWrite(V1, "Remove finger");
    Blynk.virtualWrite(V1, "Prepare to place same finger again when prompted");
    enrollStep1 = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when the user needs to place their finger again to continue the enrollment process.
boolean placeFingerPrompt() {
  if (!enrollStep2) {
    finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_PURPLE);
    Blynk.virtualWrite(V1, "Place the same finger again");
    enrollStep2 = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when the user needs to remove their finger to finish the enrollment process.
boolean removeFingerPrompt2() {
  if (!enrollStep3) {
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
    Blynk.virtualWrite(V1, "Remove finger");
    enrollStep3 = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when the enrollment process was a success.
boolean enrollSuccess() {
  if (!enrollStep4) {
    String fing = String(fid);
    finger.LEDcontrol(FINGERPRINT_LED_FLASHING, 25, FINGERPRINT_LED_PURPLE, 10);
    Blynk.virtualWrite(V1, "Successfully enrolled fingerprint id #" + fing);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
    enrollStep4 = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when there was a successful scan in the scanning mode.
boolean scanSuccess() {
  if (!scanningSuccess) {
    Blynk.virtualWrite(V1, "Print found, success!");
    scanningSuccess = true;
    finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_BLUE);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_BLUE);
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when there was a failed scan in the scanning mode.
boolean scanFailed() {
  if (!scanningFailed) {
    Blynk.virtualWrite(V1, "Print not found, Failed");
    finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_RED);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_RED);
  }
  return true;
}

void modeSelection() {
  String fing = String(fid);  // Create fing to set fid to a string in order to pass through terminal.
  switch (index) {            // Switch selections
    case 1:                   // Enroll mode
      {
        if (!enrollMode) {
          clearterm = false;
          while (!CLEARTERMINAL()) { ; }
          scanningMode = false;
          finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
          Blynk.virtualWrite(V1, "To switch modes please use switch on admin dashboard/application.");
          Blynk.virtualWrite(V1, "If switching modes, please be patient as this process could take up to 30 seconds.");
          Blynk.virtualWrite(V1, "If you would like to wipe the database, press the delete button.");
          Blynk.virtualWrite(V1, "Ready to enroll a fingerprint!");
          Serial.print("Enrolling ID #");
          Blynk.virtualWrite(V1, "Enrolling ID #" + fing);
          Serial.println(fid);
          Blynk.virtualWrite(V1, "Waiting for valid finger to enroll as #" + fing);
          finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_PURPLE);
          enrollMode = true;
        }
        while (!getFingerprintEnroll())
          ;
        delay(300);
        break;
      }
    case 2:  // Scanning mode
      {
        if (!scanningMode) {
          clearterm = false;
          while (!CLEARTERMINAL()) { ; }
          enrollMode = false;
          finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
          Blynk.virtualWrite(V1, "To switch modes please use switch on admin dashboard/application.");
          Blynk.virtualWrite(V1, "If switching modes, please be patient as this process could take up to 30 seconds.");
          Blynk.virtualWrite(V1, "If you would like to wipe the database, press the delete button.");
          Blynk.virtualWrite(V1, "Scanning, waiting for fingerprint.");
          scanningMode = true;
        }
        getFingerprintID();
        delay(300);
        break;
      }
    case 3:
      {
        break;
      }
    default:  // If there is no selection
      Blynk.virtualWrite(V1, "Please make a selection.");
  }
}

// Callback function to check V0 status
void V0check() {
  modeSelection();
}

// Callback function to check if the blynk was connected
BLYNK_CONNECTED() {
  if (isFirstConnect) {
    Blynk.syncVirtual(V0);
    isFirstConnect = false;
  }
}

BLYNK_WRITE(V0)  // Menu widget
{
  index = param.asInt();  // Get status of V0.
  modeSelection();  
}

void setup() {
  // Debug console
  Serial.begin(115200);

  // Set ESP8266 baud rate
  Serial2.begin(ESP8266_BAUD);
  delay(10);

  // Blnk auth tokens
  Blynk.begin(BLYNK_AUTH_TOKEN, wifi, ssid, pass, "blynk.cloud", 80);

  // Set the data rate for the sensor serial port
  finger.begin(57600);

  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.print("Sensor contains ");
    Serial.print(finger.templateCount);
    Serial.println(" templates");
  }
  timer.setInterval(5000L, V0check);  // Timer interval, every 5 seconds
}

void loop() {
  Blynk.run();
  timer.run();
  // You can inject your own code or combine it with other sketches.
  // Check other examples on how to communicate with Blynk. Remember
  // to avoid delay() function!
}

When the code uploads to the arduino, the serial output is:

Enrolling ID #1
Waiting for valid finger to enroll as #1
Communication error
Communication error
Communication error

The “Communication error” will continue to infinitely.

I’d expected to see rather more of yor serial output.

I hadn’t expected to see you using a BlynkTimer to call a function to call a function. This is the stuff that makes the code very difficult to follow and adds totally unnecessary complexity.

Try using this code…

// BLYNK template setup code
#define BLYNK_TEMPLATE_ID "TMPL07nDhxvy"
#define BLYNK_TEMPLATE_NAME "Arduino Uno Fingerprint Scanner"
#define BLYNK_AUTH_TOKEN "k6bccbIipGLrb-AZBJ4lBSuKG8gBqaJi"


/* Comment this out to disable prints and save space */
//#define BLYNK_PRINT Serial

// Initialize the libraries needed for the code
#include <Adafruit_Fingerprint.h>      // Fingerprint scanner
#include <ESP8266_Lib.h>               // Wifi shield
#include <BlynkSimpleShieldEsp8266.h>  //Blynk wifi
#include <Keypad.h>                    // 4x4 Keypad

// 4x4 Keypad matrix
const int ROW_NUM = 4;     // Four rows
const int COLUMN_NUM = 4;  // Four columns
char keys[ROW_NUM][COLUMN_NUM] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};
byte pin_rows[ROW_NUM] = { 28, 26, 24, 22 };       // Connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = { 29, 27, 25, 23 };  // Connect to the column pinouts of the keypad

Keypad keypad = Keypad(makeKeymap(keys), pin_rows, pin_column, ROW_NUM,
                       COLUMN_NUM);

// Length of password + 1 for null character
#define Password_Length 6
// Character to hold password input
char Data[Password_Length];
//Password
char Master[Password_Length] = "C001*";
// Counter for character entries
byte data_count = 0;
// Character to hold key input
char Key;

// WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "xxxxxx";
char pass[] = "xxxxxx";

// Define the serials for communication
#define EspSerial Serial2          // Serial for ESP8266
#define FingerprintSerial Serial1  // Serial for Fingerprint Sensor

WidgetTerminal terminal(V1);  // Blynk terminal widget datastream V1
BlynkTimer timer;             // Blynk timer

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&FingerprintSerial);  //Define fingerprint Scanner

uint8_t static fid = 1;       // Variable for finger ID *STARTS WITH 1 NO MATTER WHAT*
bool isFirstConnect = true;   // Flag to check if blynk was connected
bool clearterm = true;        // Flag to clear terminal
bool enrollMode = false;      // Flag for enrollment mode
bool enrollStep1 = true;      // Flag for step 1 of enrollment
bool enrollStep2 = true;      // Flag for step 2 of enrollment
bool enrollStep3 = true;      // Flag for step 3 of enrollment
bool enrollStep4 = true;      // Flag for step 4 of enrollment
bool noFing = true;           //Flag for no fingerprints in database
bool scanningMode = false;    //Flag for scanning mode
bool scanningSuccess = true;  //Flag for successful scan
bool scanningFailed = true;   //Flag for failed scan
int index;

uint8_t readnumber(void) {
  uint8_t num = 0;

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

// ESP8266 baud rate:
#define ESP8266_BAUD 38400
ESP8266 wifi(&EspSerial);

// Enroll mode for fingerprint scanner
uint8_t getFingerprintEnroll() {

  int p = -1;
  Serial.print("Waiting for valid finger to enroll as #");
  Serial.println(fid);

  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println("Image taken");
        break;
      case FINGERPRINT_NOFINGER:
        Serial.println(".");
        return p;
      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;
  }
  enrollStep1 = false;                 // Set enrollment step 1 flag
  while (!removeFingerPrompt()) { ; }  // Finger was successfully scanned for step 1, call removeFingerPrompt

  Serial.println("Remove finger");
  delay(2000);
  p = 0;
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  Serial.print("ID ");
  Serial.println(fid);
  p = -1;
  enrollStep2 = false;                // Set enrollment step 2 flag
  while (!placeFingerPrompt()) { ; }  //  Image was successfully converted, call placeFingerPrompt
  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;
    }
  }
  enrollStep3 = false;                  // Set enrollment step 3 flag
  while (!removeFingerPrompt2()) { ; }  // Finger was successfully processed, call removeFingerPrompt2
  delay(1000);
  // 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(fid);

  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(fid);
  p = finger.storeModel(fid);
  if (p == FINGERPRINT_OK) {
    Serial.println("Stored!");
    enrollMode = false;
    delay(1000);
  } 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;
  }
  enrollStep4 = false;            // Set enrollment step 4 flag
  while (!enrollSuccess()) { ; }  // Enrollment was successful, call enrollSuccess
  fid++;                          // Increase finger ID #

  return true;
}

// Scanning mode for fingerprint scanner
uint8_t getFingerprintID() {
  finger.getTemplateCount();

  if (finger.templateCount == 0) {
    noFing = false;            // Set no finger flag
    while (!noFinger()) { ; }  // No fingerprints enrolled, call noFinger
    Serial.print("Sensor doesn't contain any fingerprint data. Please run the 'enroll' example.");
  }
  uint8_t p = finger.getImage();
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.println("No finger detected");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("Imaging error");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  // OK success!

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

  // OK converted!
  p = finger.fingerSearch();
  if (p == FINGERPRINT_OK) {
    Serial.println("Found a print match!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_NOTFOUND) {
    scanningFailed = false;
    while (!scanFailed()) { ; }
    Serial.println("Did not find a match");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }

  // Found a match!
  scanningSuccess = false;      // Set flag for successful scan
  while (!scanSuccess()) { ; }  //  Successful scan, call scanSuccess
  Serial.print("Found ID #");
  Serial.print(finger.fingerID);
  Serial.print(" with confidence of ");
  Serial.println(finger.confidence);

  return finger.fingerID;
}

// Clear Blynk Terminal
boolean CLEARTERMINAL() {
  if (!clearterm) {
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    Blynk.virtualWrite(V1, " ");
    clearterm = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when scanning mode is initialized without any fingerprints enrolled.
boolean noFinger() {
  if (!noFing) {
    Blynk.virtualWrite(V1, "Sensor doesn't contain any fingerprint data. Please run the 'enroll' example.");
    finger.LEDcontrol(FINGERPRINT_LED_FLASHING, 25, FINGERPRINT_LED_RED, 10);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_RED);
    noFing = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when the user needs to remove their finger to continue the enrollment process.
boolean removeFingerPrompt() {
  if (!enrollStep1) {
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
    Blynk.virtualWrite(V1, "Remove finger");
    Blynk.virtualWrite(V1, "Prepare to place same finger again when prompted");
    enrollStep1 = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when the user needs to place their finger again to continue the enrollment process.
boolean placeFingerPrompt() {
  if (!enrollStep2) {
    finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_PURPLE);
    Blynk.virtualWrite(V1, "Place the same finger again");
    enrollStep2 = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when the user needs to remove their finger to finish the enrollment process.
boolean removeFingerPrompt2() {
  if (!enrollStep3) {
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
    Blynk.virtualWrite(V1, "Remove finger");
    enrollStep3 = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when the enrollment process was a success.
boolean enrollSuccess() {
  if (!enrollStep4) {
    String fing = String(fid);
    finger.LEDcontrol(FINGERPRINT_LED_FLASHING, 25, FINGERPRINT_LED_PURPLE, 10);
    Blynk.virtualWrite(V1, "Successfully enrolled fingerprint id #" + fing);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
    enrollStep4 = true;
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when there was a successful scan in the scanning mode.
boolean scanSuccess() {
  if (!scanningSuccess) {
    Blynk.virtualWrite(V1, "Print found, success!");
    scanningSuccess = true;
    finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_BLUE);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_BLUE);
  }
  return true;
}

// Send text to terminal, control scanner LED. Called when there was a failed scan in the scanning mode.
boolean scanFailed() {
  if (!scanningFailed) {
    Blynk.virtualWrite(V1, "Print not found, Failed");
    finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_RED);
    delay(2000);
    finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_RED);
  }
  return true;
}

void modeSelection()
{
  String fing = String(fid);  // Create fing to set fid to a string in order to pass through terminal.
  switch (index) {            // Switch selections
    case 1:                   // Enroll mode
      {
        Serial.println("case option 1 was selected");
        if (!enrollMode) {
          Serial.println("Not in enrol mode");          
          //clearterm = false;
          //while (!CLEARTERMINAL()) { ; }
          terminal.clear();
          
          scanningMode = false;
          finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
          Blynk.virtualWrite(V1, "To switch modes please use switch on admin dashboard/application.");
          Blynk.virtualWrite(V1, "If switching modes, please be patient as this process could take up to 30 seconds.");
          Blynk.virtualWrite(V1, "If you would like to wipe the database, press the delete button.");
          Blynk.virtualWrite(V1, "Ready to enroll a fingerprint!");
          Serial.print("Enrolling ID #");
          Blynk.virtualWrite(V1, "Enrolling ID #" + fing);
          Serial.println(fid);
          Blynk.virtualWrite(V1, "Waiting for valid finger to enroll as #" + fing);
          finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_PURPLE);
          enrollMode = true;
        }
        while (!getFingerprintEnroll())
          ;
        delay(300);
        break;
      }
    case 2:  // Scanning mode
      {
        Serial.println("case option 2 was selected");
        if (!scanningMode) {
          Serial.println("Not in scanning mode");
          
          //clearterm = false;
          //while (!CLEARTERMINAL()) { ; }
          terminal.clear();
          
          enrollMode = false;
          finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_PURPLE);
          Blynk.virtualWrite(V1, "To switch modes please use switch on admin dashboard/application.");
          Blynk.virtualWrite(V1, "If switching modes, please be patient as this process could take up to 30 seconds.");
          Blynk.virtualWrite(V1, "If you would like to wipe the database, press the delete button.");
          Blynk.virtualWrite(V1, "Scanning, waiting for fingerprint.");
          
          Serial.println("To switch modes please use switch on admin dashboard/application.");
          Serial.println("If switching modes, please be patient as this process could take up to 30 seconds.");
          Serial.println("If you would like to wipe the database, press the delete button.");
          Serial.println("Scanning, waiting for fingerprint.");         
                           
          scanningMode = true;
        }
        getFingerprintID();
        delay(300);
        break;
      }
    case 3:
      {
        Serial.println("case option 3 was selected");
        break;
      }
    default:  // If there is no selection
      Blynk.virtualWrite(V1, "Please make a selection.");
  }
}

// Callback function that triggers when the device connects or re-connects to the Blynk server
BLYNK_CONNECTED()
{
  Serial.println("BLYNK_CONNECTED triggered");
  Blynk.syncVirtual(V0);
}


BLYNK_WRITE(V0)  // Triggerd when Menu widget value changes or Blynk.syncVirtual(V0) is called
{
  Serial.println("BLYNK_WRITE(V0) triggered");
  index = param.asInt();  // Get status of V0.
  Serial.print("index = ");
  Serial.println(index); 
  modeSelection();  
}

void setup() {
  // Debug console
  Serial.begin(115200);

  // Set ESP8266 baud rate
  Serial2.begin(ESP8266_BAUD);
  delay(10);

  // Set the data rate for the sensor serial port
  finger.begin(57600);

  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.print("Sensor contains ");
    Serial.print(finger.templateCount);
    Serial.println(" templates");
  }

  // Connect to Blynk
  Blynk.begin(BLYNK_AUTH_TOKEN, wifi, ssid, pass, "blynk.cloud", 80);
  
  timer.setInterval(5000L, modeSelection);  // Timer interval, every 5 seconds
}


void loop()
{
  Blynk.run();
  timer.run();
}

and post your ENTIRE serial output from boot-up to whatever error message you encounter when you run the code.

Pete.

1 Like

Wow Pete. Thank you so much I appreciate it. Working good and no errors at all. What I sent you before was the only serial output I was getting. Now everything is smooth. Just to let you know though, this is what I was talking about before when I said that the clear terminal wasn’t working for me. I attached a picture to show you the terminal output. terminal.clear just outputs “clr”.

Sounds like a bug, as the documentation says that should work…

I’ll do some tests later, and I’m sure that there is a better way to do it than the one you’ve used.

Pete.

1 Like