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!