Some additional searching led to a youtube video that was in a foreign language. I managed to find something that translated subtitles to English, then from there found a library to download. It was not a complete library in that there I did not recognize anything to put into the Arduino libraries.
But, I tried their code to enroll and to check a fingerprint. It worked. To the best of my knowledge, it is using the Adafruit library, but with someone else’s example code. Unfortunately, I cannot find it again. Just be aware of this situation. After installing the library, try different libraries, or more correctly, different example code until one works better than the Adafruit example code.
The Adafruit code to validate a fingerprint did not work at all. Their code to enroll kept asking for the same finger over and over. To enroll another finger I had to press the reset button and start over.
I cannot find it again, but will provide the working code, after changes.
Some significant changes were needed. For example, in the loop() it just called a function and used the serial monitor to show if the fingerprint was valid. The code was ignoring the return value. But on adding that in, I found that some error codes were in the range of a valid return. So each error code was hunted down and replaced with a new specific error code. That worked out okay.
I have also added in the code to control a set of actuators, three controllers of type L298N, each of which drives two actuators.
So the key here is: The Adafruit library seems to be good, but, their example code is not.
Edit: and just nice to know, this is a panel mount sensor, round, with no clear top or bottom. It does recognize fingerprints even when rotated.
/***************************************************
This is an example sketch for our optical Fingerprint sensor
Designed specifically to work with the Adafruit BMP085 Breakout
----> http://www.adafruit.com/products/751
These displays use TTL Serial to communicate, 2 pins are required to
interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
// Nerf Gun Desk Project
// This device will control five actuators that open and close doors and lift tables
// of a desk. When open those doors/lifts provide access to Nerf gun resources.
// Due to the pin count limitations, actuators 0 and 1 are driven together,
// 2 and 3 are drive together, and 4 is driven separately.
// At this writing, the grouping represents the types of actuators.
// From the perspective of this code, there are 3 actuators.
// #define DEBUG
// #define SHOW_LOOP_ERRORS
// #define SHOW_NO_FINGER
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// This section is from the Adafruit example code
#include <Adafruit_Fingerprint.h>
// The sensor can store 127 fingerprints identified as 1 ... 127.
// The code I started with returned errors codes withint that range.
// So, I found all the possible places to return an error code and
// started numbering them from 255 down. Because, the return value
// is an unsigned 8 bit number.
// Now, when a valid finger is detected, the returned value is
// from 1 ... 127. All other values are errors.
const uint8_t E_NO_FINGER = 255;
const uint8_t E_PACKET_RECEIVE_ERROR = 254;
const uint8_t E_IMAGE_FAIL = 253;
const uint8_t E_UNKNOWN_ERROR_1 = 252;
const uint8_t E_IMAGE_MESSY = 251;
const uint8_t E_PACKET_RECEIVE_ERR = 250;
const uint8_t E_FEATURE_FAIL = 249;
const uint8_t E_INVALID_IMAGE = 248;
const uint8_t E_UNKNOWN_ERROR_2 = 247;
const uint8_t E_PACKET_RECEIVE_ERROR_2 = 246;
const uint8_t E_FINGER_NOT_FOUND = 245;
const uint8_t E_UNKNOWN_ERROR_3 = 244;
#if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__)
// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino (WHITE wire)
// Set up the serial port to use softwareserial..
SoftwareSerial mySerial(2, 3);
#else
// On Leonardo/M0/etc, others with hardware serial, use hardware serial!
// #0 is green wire, #1 is white
#define mySerial Serial1
#endif
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
// End of Adafruit section
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// Begin stuff for actuators
// Nerf Gun Desk Project
// This device will control five actuators that open and close doors and lift tables
// of a desk. When open those doors/lifts provide access to Nerf gun resources.
// Due to the pin count limitations, actuators 0 and 1 are driven together,
// 2 and 3 are drive together, and 4 is driven separately.
// At this writing, the grouping represents the types of actuators.
// From the perspective of this code, there are 3 actuators.
// List of input/output pins and their use
// A0 analog 0 not used
// A1 analog 1 not used
// A2 analog 2 not used
// A3 analog 3 not used
// A4 analog 4 not used
// A5 analog 5 not used
// D0 serial data receive
// D1 serial data transmit
// D2 Finger print sensor transmit
// D3 Finger print sensor receive
// There are five actuators, but not enough pins. Therefore:
// Actuators 1 and 2 are driven from one pair of pins.
// Actuators 3 and 4 are driven from the next pair of pins
// D4 actuators 1 and 2 control A Two control lines for each actuator
// D5 actuators 1 and 2 control B drive 2 actuators with one pair of control lines
// D6 actuators 3 and 4 control A
// D7 actuators 3 and 4 control B
// D8 actuator 5 line A
// D9 actuator 5 line B
// D10 not used
// D11 not used
// D12 input switch, close doors without fingerprint, but not open them.
// D13 input, development. set to low to inhibit debug prints
void act_state_closing();
void act_state_closed();
void act_state_opening();
void act_state_open();
const bool OPEN = false;
const bool CLOSE = true;
const bool BUTTON_RELEASED = true;
const bool BUTTON_PRESSED = false;
const int ACT_COUNT = 3;
// Actuator control pins are two at a time.
// The second pin is always the first plus 1.
const int ACTUATOR_PINS[] = { 4, 6, 8 };
// Actuator are moved together, but are staggered by this many
// milliseconds to reduce current draw.
const unsigned long ACTUATOR_DELAY[] = { 0, 1000, 1000 };
// The expected run time for each actuator. After power has been
// applied for this many milliseconds it is turned off.
const unsigned long ACTUATOR_RUN[] = { 2000, 2000, 2000 };
// Declare a digital input for a user push button.
const int PUSH_BUTTON = 12;
const int DEBUG_CONTROL = 13;
// The actuators are controled by an FSM, Finite State Machine.
// ACT is short for actuator
// Here are its states.
enum ACT_STATE_ENUM
{ ACT_CLOSING,
ACT_CLOSED,
ACT_OPENING,
ACT_OPENED,
ACT_STATE_COUNT
};
// The state of the FSM
ACT_STATE_ENUM ACT_STATE;
// Names of each state for development printing
const char state_names[ 4 ][ 13 ] = { "ACT_CLOSING ",
"ACT_CLOSED ",
"ACT_OPENING ",
"ACT_OPENED " };
// End stuff for actuators
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
void setup()
{
Serial.begin(9600);
while (!Serial); // For Yun/Leo/Micro/Zero/...
delay(100);
Serial.println("\n\nAdafruit finger detect test");
Serial.print( "Compile date " );
Serial.print( __DATE__ );
Serial.print( " : " );
Serial.println( __TIME__ );
// set the data rate for the sensor serial port
finger.begin(57600);
delay(5);
if (finger.verifyPassword()) {
Serial.println("Found fingerprint sensor!");
} else {
Serial.println("Did not find fingerprint sensor :(");
while (1) { delay(1); }
}
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.println("Waiting for valid finger...");
Serial.print("Sensor contains "); Serial.print(finger.templateCount); Serial.println(" templates");
}
// .........................................
// Begin actuator setup
// Power may have been lost with the doors open so
// first they should be closed.
ACT_STATE = ACT_CLOSING;
// set the actuator pins to output mode and turn off power
for( int actuator = 0; actuator < ACT_COUNT; actuator ++ )
{
pinMode( ACTUATOR_PINS[ actuator ], OUTPUT);
pinMode( ACTUATOR_PINS[ actuator ] + 1, OUTPUT);
digitalWrite( ACTUATOR_PINS[ actuator ], LOW );
digitalWrite( ACTUATOR_PINS[ actuator ] + 1, LOW );
}
// Set one digital pin for a push button for development and
// maybe for use. The other may be used to enable some print lines for debug.
pinMode( PUSH_BUTTON, INPUT );
pinMode( DEBUG_CONTROL, INPUT );
Serial.print( __LINE__ );
Serial.println( " Exit setup" );
// end actuator setup
} // end of setup()
void loop() // run over and over again
{
uint8_t finger = getFingerprintID();
if( finger > 0 && finger < 128 )
{
Serial.print( __LINE__ );
Serial.print ( " YYYYYYYYYYY " );
Serial.print( " in loop(), valid finger ID is " );
Serial.println( finger );
}
// ......................................................
// begin actuator stuff
// Valid fingerprints are stored in 1 .. 127.
// All return values outside that range indicate not a valid fingerprint.
if( finger > 0 && finger < 128 )
{
if( ACT_STATE == ACT_CLOSED )
{
ACT_STATE = ACT_OPENING;
}
else if( ACT_STATE = ACT_OPENED )
{
ACT_STATE = ACT_CLOSING;
}
}
switch( ACT_STATE )
{
case ACT_CLOSING: act_state_closing(); break;
case ACT_CLOSED: act_state_closed(); break;
case ACT_OPENING: act_state_opening(); break;
case ACT_OPENED: act_state_open(); break;
default:
{
Serial.print( __LINE__ );
Serial.println( " default taken" );
Serial.print( " state found to be " );
Serial.println( state_names[ ACT_STATE ] );
ACT_STATE = ACT_CLOSING;
Serial.print( " state reset to " );
Serial.println( state_names[ ACT_STATE ] );
}
}
// end actuator stuff
// ......................................................
delay(50); //don't ned to run this at full speed.
}
// end of loop()
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
uint8_t getFingerprintID()
{
uint8_t p = finger.getImage();
switch (p)
{
case FINGERPRINT_OK:
Serial.print( __LINE__ );
Serial.print(" Image taken, p = ");
Serial.print( p );
Serial.println( " break" );
break;
case FINGERPRINT_NOFINGER:
#ifdef SHOW_NO_FINGER
Serial.print( __LINE__ );
Serial.print(" No finger detected, p = ");
Serial.print( p );
Serial.println( " immediate return" );
#endif
return E_NO_FINGER;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.print( __LINE__ );
Serial.print(" Communication error, p = ");
Serial.println( p );
return E_PACKET_RECEIVE_ERROR;
case FINGERPRINT_IMAGEFAIL:
Serial.print( __LINE__ );
Serial.print(" Imaging error, p = ");
Serial.println( p );
return E_IMAGE_FAIL;
default:
Serial.print( __LINE__ );
Serial.println(" Unknown error, p = ");
Serial.print( p );
Serial.println( " return p" );
return E_UNKNOWN_ERROR_1;
} // end of switch
// OK success!
p = finger.image2Tz();
switch (p) {
case FINGERPRINT_OK:
Serial.print( __LINE__ );
Serial.print(" Image converted, p = ");
Serial.print( p );
Serial.println( " switch break" );
break;
case FINGERPRINT_IMAGEMESS:
Serial.print( __LINE__ );
Serial.print(" Image too messy, p = ");
Serial.print( p );
Serial.println( " return p " );
return E_IMAGE_MESSY;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.print( __LINE__ );
Serial.print(" Communication error p = ");
Serial.print( p );
Serial.println( " return p" );
return E_PACKET_RECEIVE_ERR;
case FINGERPRINT_FEATUREFAIL:
Serial.print( __LINE__ );
Serial.print(" Could not find fingerprint features, p = ");
Serial.println( p );
return E_FEATURE_FAIL;
case FINGERPRINT_INVALIDIMAGE:
Serial.print( __LINE__ );
Serial.print(" Could not find fingerprint features, p = ");
Serial.print( p );
Serial.println( " return p" );
return E_INVALID_IMAGE;
default:
Serial.print( __LINE__ );
Serial.print(" Unknown error, p = ");
Serial.print( p );
Serial.println( " return p" );
return E_UNKNOWN_ERROR_2;
}
// OK converted!
p = finger.fingerSearch();
if (p == FINGERPRINT_OK)
{
Serial.print( __LINE__ );
Serial.print(" Found a print match! p =");
Serial.print( p );
Serial.println( " fall through" );
}
else if (p == FINGERPRINT_PACKETRECIEVEERR)
{
Serial.print( __LINE__ );
Serial.print(" Communication error, p = ");
Serial.print( p );
Serial.println( " return p" );
return E_PACKET_RECEIVE_ERROR_2;
}
else if (p == FINGERPRINT_NOTFOUND)
{
Serial.print( __LINE__ );
Serial.print(" Did not find a match, p = ");
Serial.print( p );
Serial.println( " return p " );
return E_FINGER_NOT_FOUND;
}
else
{
Serial.print( __LINE__ );
Serial.print(" Unknown error, p = ");
Serial.print( p );
Serial.println( " return p" );
return E_UNKNOWN_ERROR_3;
}
// found a match!
Serial.print( __LINE__ );
Serial.print(" Found ID #"); Serial.print(finger.fingerID);
Serial.print(" with confidence of ");
Serial.println(finger.confidence);
Serial.print( __LINE__ );
Serial.print( " p = " );
Serial.println( p );
Serial.print( "finger.fingerID = " );
Serial.print( finger.fingerID );
Serial.println( " return the finger ID" );
return finger.fingerID;
} // end of function: getFingerprintID()
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// WARNING: The example code included this function, but
// never calls it. Left it here just to show any reader
// that you need to check for stuff like this.
// I put the xyz on the end just to prove that it really
// does compile without this code and will remove it
// for my project.
// returns -1 if failed, otherwise returns ID #
int getFingerprintIDez_xyz()
{
Serial.print( __LINE__ );
Serial.println( " Entered getFingerprintIDez()" );
uint8_t p = finger.getImage();
if (p != FINGERPRINT_OK)
{
Serial.print( __LINE__ );
Serial.print( " p != FINGERPRINT_OK, p = " );
Serial.print( p );
Serial.println( " return -1" );
return -1;
}
p = finger.image2Tz();
if (p != FINGERPRINT_OK)
{
Serial.print( __LINE__ );
Serial.print( " p != FINGERPRINT_OK, p = " );
Serial.print( p );
Serial.println( " return -1" );
return -1;
}
p = finger.fingerFastSearch();
if (p != FINGERPRINT_OK)
{
Serial.print( __LINE__ );
Serial.print( " p != FINGERPRINT_OK, p = " );
Serial.print( p );
Serial.println( " return -1" ); return -1;
}
// found a match!
Serial.print( __LINE__ );
Serial.print(" Found ID #");
Serial.print(finger.fingerID);
Serial.print(" with confidence of ");
Serial.println(finger.confidence);
Serial.print( __LINE__ );
Serial.println( " exit function getFingerprintIDez()" );
return finger.fingerID;
}
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// Actuator functions begin here
// This function is called when the actuator state is
// in state ACT_CLOSING
// The actuators are to be closed or are closing.
void act_state_closing( )
{
Serial.print( __LINE__ );
Serial.print( " in state " );
Serial.println( state_names[ ACT_STATE ] );
move_actuators( CLOSE );
ACT_STATE = ACT_CLOSED;
Serial.print( __LINE__ );
Serial.print( " function done, change state to " );
Serial.println( state_names[ ACT_STATE ] );
} // end of function act_state_closing()
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// use this function when the actuators are closed.
// Wait here until there is a finger print scan or a button press.
// First version is button only.
void act_state_closed()
{
int button_state = digitalRead( PUSH_BUTTON );
// The pushbutton closes only when open or when
// debugging and testing.
#ifdef DEBUG
if( button_state == BUTTON_PRESSED )
{
ACT_STATE = ACT_OPENING;
Serial.print( __LINE__ );
Serial.println( " Button pressed, go to closing state" );
Serial.println( state_names[ ACT_STATE ] );
}
#endif
} // end of function act_state_closed()
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// This function is called when the actuator state is
// in state ACT_OPENING
// All inputs are ignored until the opening is complete
void act_state_opening( )
{
move_actuators( OPEN );
ACT_STATE = ACT_OPENED;
Serial.print( __LINE__ );
Serial.print( " Actuators opened, go to state " );
Serial.println( state_names[ ACT_STATE ] );
} // end of function act_state_opening()
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// The system rests in this state,
// Exit criteria:
// A fingerprint scan
// A button press to close
// A timer expires to close
// Action: Change to state
void act_state_open()
{
// Digital input pins float high. Must use LOW or a pull down resistor.
int button_pressed = digitalRead( PUSH_BUTTON );
if( button_pressed == BUTTON_PRESSED )
{
ACT_STATE = ACT_CLOSING;
Serial.print( __LINE__ );
Serial.println( " Button pressed, go to closing state" );
Serial.println( state_names[ ACT_STATE ] );
}
} // end of function act_state_open()
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
void move_actuators( bool move_direction )
{
bool first_pin;
bool second_pin;
if( move_direction == OPEN )
{
first_pin = true;
second_pin = false;
Serial.print( __LINE__ );
Serial.println( " Opening" );
}
else
{
first_pin = false;
second_pin = true;
Serial.print( __LINE__ );
Serial.println( " Closing" );
}
// Turn on the motors after specified delay before each activation
for( int actuator = 0; actuator < ACT_COUNT; actuator ++ )
{
delay( ACTUATOR_DELAY[ actuator ] );
digitalWrite( ACTUATOR_PINS[ actuator ], first_pin );
digitalWrite( ACTUATOR_PINS[ actuator ] + 1, second_pin );
Serial.print( __LINE__ );
Serial.print( " Power on group " );
Serial.print( actuator );
Serial.print( " pins " );
Serial.print( ACTUATOR_PINS[ actuator ] );
Serial.print( " and " );
Serial.println( ACTUATOR_PINS[ actuator ] + 1 );
}
// Turn off the motors after the specified run time
// When both pins have the same value power is off.
for( int actuator = 0; actuator < ACT_COUNT; actuator ++ )
{
delay( ACTUATOR_RUN[ actuator ] );
digitalWrite( ACTUATOR_PINS[ actuator ], LOW );
digitalWrite( ACTUATOR_PINS[ actuator ] + 1, LOW );
Serial.print( __LINE__ );
Serial.print( " Power off group " );
Serial.print( actuator );
Serial.print( " pins " );
Serial.print( ACTUATOR_PINS[ actuator ] );
Serial.print( " and " );
Serial.println( ACTUATOR_PINS[ actuator ] + 1 );
}
Serial.print( __LINE__ );
Serial.println( " Movement complete" );
}
// End of actuator functions
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&