I have a school project that involves the Arduino Uno and a fingerprint scanner. What I would like for it to do is every time a finger is scanned, it sends to the counter + 1. When the same finger is scanned for a second time it sends to the counter -1.
Example:
1st person scans counter starts = 1
2nd person scans finger display = 2
3rd person scans finger display = 3 etc, etc, etc, Now the tricky part.
When any person scans finger again it subtracts a number. The numbers do not have to match the fingerprint of each person, just count up and back down when same finger scanned a second time.
I have grabbed the code for the fingerprint scanner from adafruit, since it is their fingerprint scanner, and have it working collecting fingerprints. I also have an LCD connected that works and lights up with the words I want to use in it. Right now as soon as you click the serial monitor it asks to capture the fingerprint but also starts counting right away even without a finger scanned. I just need it to work showing on the serial monitor. Once I get to that step I will transfer it to the LCD.
This is my first code aside from blinking lights and making servos turn. Please be gentle. lol I am sure the problem is my boolean and me, I just cant figure it out. Thanks for your help in advance!!!
#include <LiquidCrystal.h>
#include <Adafruit_Fingerprint.h>
#if ARDUINO >= 100
#include <SoftwareSerial.h>
#else
#include <NewSoftSerial.h>
#endif
int getFingerprintIDez();
int hits = 0;
// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino (WHITE wire)
#if ARDUINO >= 100
SoftwareSerial mySerial(2, 3);
#else
NewSoftSerial mySerial(2, 3);
#endif
int ThisChild =(1,2,3,4,5);
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
void setup()
{
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("Children on Board");
Serial.begin(9600);
Serial.println("fingertest");
// set the data rate for the sensor serial port
finger.begin(57600);
if (finger.verifyPassword()) {
Serial.println("Found fingerprint sensor!");
} else {
Serial.println("Did not find fingerprint sensor :(");
while (1);
}
Serial.println("Waiting for valid finger...");
}
void loop() // run over and over again
{
getFingerprintIDez();
boolean a_b_Children[5];
if (a_b_Children[ThisChild] == false) a_b_Children[ThisChild] = true;
else (a_b_Children[ThisChild] = false);
if (a_b_Children[ThisChild] = true) {
Serial.println(hits++);
}
}
uint8_t getFingerprintID() {
uint8_t p = finger.getImage();
switch (p) {
case FINGERPRINT_OK:
Serial.println("Image taken");
break;
case FINGERPRINT_NOFINGER:
Serial.println("No finger detected");
return p;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.println("Communication error");
return p;
case FINGERPRINT_IMAGEFAIL:
Serial.println("Imaging error");
return p;
default:
Serial.println("Unknown error");
return p;
}
// OK success!
p = finger.image2Tz();
switch (p) {
case FINGERPRINT_OK:
Serial.println("Image converted");
break;
case FINGERPRINT_IMAGEMESS:
Serial.println("Image too messy");
return p;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.println("Communication error");
return p;
case FINGERPRINT_FEATUREFAIL:
Serial.println("Could not find fingerprint features");
return p;
case FINGERPRINT_INVALIDIMAGE:
Serial.println("Could not find fingerprint features");
return p;
default:
Serial.println("Unknown error");
return p;
}
// OK converted!
p = finger.fingerFastSearch();
if (p == FINGERPRINT_OK) {
Serial.println("Found a print match!");
} else if (p == FINGERPRINT_PACKETRECIEVEERR) {
Serial.println("Communication error");
return p;
} else if (p == FINGERPRINT_NOTFOUND) {
Serial.println("Did not find a match");
return p;
} else {
Serial.println("Unknown error");
return p;
}
// found a match!
Serial.print("Found ID #"); Serial.print(finger.fingerID);
Serial.print(" with confidence of "); Serial.println(finger.confidence);
}
// returns -1 if failed, otherwise returns ID #
int getFingerprintIDez() {
uint8_t p = finger.getImage();
if (p != FINGERPRINT_OK) return -1;
p = finger.image2Tz();
if (p != FINGERPRINT_OK) return -1;
p = finger.fingerFastSearch();
if (p != FINGERPRINT_OK) return -1;
// found a match!
Serial.print("Found ID #"); Serial.print(finger.fingerID);
Serial.print(" with confidence of "); Serial.println(finger.confidence);
return finger.fingerID;
}
I tried that before I posted for help. It did stop initiating the counter as soon as I started the serial monitor but did not start the counter as soon as a fingerprint was scanned.
PaulS:
I was under the impression that by using [5] it would recognize that it was 5 different fingerprints being captured and counted for.
Are you saying that it should be in a global setting? I am really not following your response to well.
What I do know is that the fingerprint scanner acknowledges the capture by the id# that is is enrolled with. Right now I have one finger enrolled just to get it to count.
I was under the impression that by using [5] it would recognize that it was 5 different fingerprints being captured and counted for.
You are reserving space for 5 values. You are NOT providing initial values. When loop() ends, those 5 values that you have will be discarded. Next time loop() runs, you get new space to store 5 values.
Are you saying that it should be in a global setting?
I was under the impression that by using [5] it would recognize that it was 5 different fingerprints being captured and counted for.
You are reserving space for 5 values. You are NOT providing initial values. When loop() ends, those 5 values that you have will be discarded. Next time loop() runs, you get new space to store 5 values.
Are you saying that it should be in a global setting?
Either that or static.
I will work on this tonight. I kinda understand what your saying just need someone to visually elaborate it for me.
I tried what I think you are saying, but when I did, verifying gave me error on the way I inputted the initial values.
You need to get a grasp on the concept of scope. Scope refers to the lifetime and visibility of a data item. As a starter, consider:
Global scope -- data items define outside of any function. These are visible to any part of the program and live as long as the program is running.
Function scope -- data items defined within the starting ({) and end (}) braces of a function. They come to life when program execution enters the function and they "die" (i.e., go out of scope) when control leaves the function.
Block scope -- data items defined within a statement block. The come to life (i.e., are in scope) at the start of the statement block and die when the block ends. For example:
for (int i = 0; i < MAXNUM; i++) {
sum += val[i];
}
average = sum / i; // ERROR: i is no longer in scope
Variable i comes alive (into scope) when its definition is read as expression1 of the for loop. It dies when the closing brace of the for loop is reached. Therefore, the statement outside the braces draws a compiler error because i no longer exists.
4) static -- Using the keyword static allows you define a data item, and have it retain its value even when program control goes outside its scope level. For example, if you have
void myFunction() {
static int myVariable = 10;
// more code...
} // end of function
the next time you enter myFunction(), myVariable will still have the same value it did after the previous call to the function ended. Data items defined locally with the static type specifier are allocated on the heap, which means 1) only one of them is defined for the program, and 2) the data item persists regardless of its scope level.
econjack: You Rock Dude!!!!!! This is awesome! I can actually understand what you are saying. I have the book "Getting Started with Arduino" I sorta understand what is says but they way you explain things, way better!
I also just bought " Arduino for Dummies" I know I know, laugh at will. But, I also want to learn Arduino not just for my school project , so that I can also create projects in the future with my son.
econjack:
Data items defined with the static type specifier are allocated on the heap
I don't think that's strictly accurate - they will usually be defined in the global initialised data section, not the heap. Your description of the behaviour is right, though, assuming we're talking about local static variables. (The static keyword has a different meaning in the context of global data.)
I worked a little on the project tonight. I changed a few things around. I just added an if statement in the loop and got the fingerprint to count. great. Now I have to work it in reverse. Any thoughts? The reason I went with am if statement is because when the reader sends anything other that -1 to the Arduino, it acknowledges the fingerprint capture.
Here is the updated code. Any advice is more than appreciated!
#include <LiquidCrystal.h>
#include <Adafruit_Fingerprint.h>
#if ARDUINO >= 100
#include <SoftwareSerial.h>
#else
#include <NewSoftSerial.h>
#endif
int getFingerprintIDez();
int hits = 0;
// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino (WHITE wire)
#if ARDUINO >= 100
SoftwareSerial mySerial(2, 3);
#else
NewSoftSerial mySerial(2, 3);
#endif
int Childcount = (1,2,3,4,5);
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
void setup()
{
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("Children on Board");
Serial.begin(9600);
Serial.println("fingertest");
// set the data rate for the sensor serial port
finger.begin(57600);
if (finger.verifyPassword()) {
Serial.println("Found fingerprint sensor!");
} else {
Serial.println("Did not find fingerprint sensor :(");
while (1);
}
Serial.println("Waiting for valid finger...");
}
void loop() // run over and over again
{
if (getFingerprintIDez() >= 0){ //changed here from previous
Serial.println(hits++); //changed here from previous
}
}
uint8_t getFingerprintID() {
uint8_t p = finger.getImage();
switch (p) {
case FINGERPRINT_OK:
Serial.println("Image taken");
break;
case FINGERPRINT_NOFINGER:
Serial.println("No finger detected");
return p;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.println("Communication error");
return p;
case FINGERPRINT_IMAGEFAIL:
Serial.println("Imaging error");
return p;
default:
Serial.println("Unknown error");
return p;
}
// OK success!
p = finger.image2Tz();
switch (p) {
case FINGERPRINT_OK:
Serial.println("Image converted");
break;
case FINGERPRINT_IMAGEMESS:
Serial.println("Image too messy");
return p;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.println("Communication error");
return p;
case FINGERPRINT_FEATUREFAIL:
Serial.println("Could not find fingerprint features");
return p;
case FINGERPRINT_INVALIDIMAGE:
Serial.println("Could not find fingerprint features");
return p;
default:
Serial.println("Unknown error");
return p;
}
// OK converted!
p = finger.fingerFastSearch();
if (p == FINGERPRINT_OK) {
Serial.println("Found a print match!");
} else if (p == FINGERPRINT_PACKETRECIEVEERR) {
Serial.println("Communication error");
return p;
} else if (p == FINGERPRINT_NOTFOUND) {
Serial.println("Did not find a match");
return p;
} else {
Serial.println("Unknown error");
return p;
}
// found a match!
Serial.print("Found ID #"); Serial.print(finger.fingerID);
Serial.print(" with confidence of "); Serial.println(finger.confidence);
}
// returns -1 if failed, otherwise returns ID #
int getFingerprintIDez() {
uint8_t p = finger.getImage();
if (p != FINGERPRINT_OK) return -1;
p = finger.image2Tz();
if (p != FINGERPRINT_OK) return -1;
p = finger.fingerFastSearch();
if (p != FINGERPRINT_OK) return -1;
// found a match!
Serial.print("Found ID #"); Serial.print(finger.fingerID);
Serial.print(" with confidence of "); Serial.println(finger.confidence);
return finger.fingerID;
}
Both. I actually got it to work somewhat after I posted this! I am ecstatic right now!
fingers are pre logged with another software.
When finger is scanned first time = 1
same finger scanned a second time = 0
Example:
when finger 1 is scanned = 1
finger 2 scanned = 2
finger 3 scanned = 3
any of three fingers scanned again = subract 1 from total.
I got it to work for only one finger. Now the scanner stores the image by the id number enroll them by. I am guessing I need to find a way to call these id #s back into my if statement so that it can recognize when a different finger is scanned?
You need to keep a list of which IDs are currently 'in'. You also need to know the number that are currently in, which you could either work out by counting the number of entries in the list, or record separately and increment and decrement as IDs are added to and removed from the list.
One approach to this which avoids you needing to get your head around C++ collection classes is to store the IDs that are 'in' in an array. Since they can enter and leave in any order the array will be sparse (it will have holes in) so you need to define an ID value representing 'not used' and then to add an entry to the list you would iterate through the array looking for an unused entry - put your new ID in the first unused entry and increment the count. If you reach the end of the array without finding an unused entry, you have overflowed the array. To remove an entry from the list you would iterate through the array to find the entry for this ID, and if you find it decrement the count and set the entry to unused. You will probably need a third function which tells you whether a given ID is in the list, without changing it.
I tried this code and enrolled three different fingers into the scanner. I worked the first time and then it didn't.
When I enrolled the fingerprints I used these three numbers.
What did I do wrong?
void loop() // run over and over again
{
if (getFingerprintIDez() >= 0){
Serial.println(hits++);
}
else if (getFingerprintIDez() >= 1){
Serial.println(hits--);
}
else if (getFingerprintIDez() >= 2){
Serial.println(hits--);
}
else if (getFingerprintIDez() >= 3){
Serial.println(hits--);
}
}
I tried this code and enrolled three different fingers into the scanner. I worked the first time and then it didn't.
You should save the value returned by getFingerprintIDez() into a variable, and print, and test, that variable. Calling the function over and over doesn't seem reasonable.