jueves, 11 de junio de 2020

Sensor de huella dactilar

Este curso debido a la pandemia no hemos podido desarrollar nuestros proyectos con Arduino. Algunas prácticas con sensores, ya las habíamos realizado en cursos pasados, pero uno de los proyectos que teníamos previstos para este curso, consistía en aprender a utilizar un sensor de huella dactilar o módulo de reconocimiento de huella dactilar. 
La aparición de nuestras huellas dactilares comienza en las primeras semanas de vida dentro del útero materno y es un rasgo que nos define de manera única toda nuestra vida. De ahí que sea una buena manera de identificarnos ya que es un rasgo biométrico propio de cada individuo.


Las características de los rasgos biométricos son las siguientes:
- Universalidad: Todo individuo debe tenerlo.
- Unicidad: Personas distintas tienen rasgos distintos.
- Permanencia: El rasgo debe ser invariable en el tiempo.
- Perennidad: El rasgo debe ser permanente a largo plazo.
- Mensurabilidad: El rasgo debe poder ser cuantificado de alguna manera.

Los sensores de huellas dactilares para Arduino son unos dispositivos capaces de leer, guardar e identificar posteriormente las huellas de nuestros dedos.
En los últimos tiempos los sensores de huellas se han hecho muy populares gracias a los smartphones pues intentamos sustituir las contraseñas por algún tipo de sensor biométrico, que son casi imposibles de falsificar. 
El módulo de reconocimiento de huella dactilar que tenemos es el siguiente:


Este módulo, almacena las huellas en una memoria interna y posteriormente las reconoce. El módulo se comunica con Arduino a través de un puerto serie. Este sensor escanea las huellas en menos de 1 segundo y puede almacenar en su memoria hasta 162. Es fácil de conectar, sólo usaremos 4 de los 6 cables que vienen con el sensor: 2 para alimentación y 2 para comunicación serie.
Cable rojo --> 5 V 
Cable negro --> GND
Verde/Amarillo --> Rx (pin D2) 
Blanco/Azul -->Tx (pin D3) 

En cuanto a la programación, es muy sencilla gracias a la librería que pone a nuestra disposición Adafruit, llamada Adafruit-Fingerprint-Sensor-Library y disponible en el siguiente enlace: https://github.com/adafruit/Adafruit-Fingerprint-Sensor-Library. 
Como siempre, descargaremos y lo añadiremos a IDE Arduino a través de Programa/Incluir librería

Para probar el funcionamiento del sensor lo primero que hacemos es cargar el ejemplo de la propia librería, llamado “enroll”.

Este ejemplo sirve para escanear y guardar las huellas que queramos que reconozca. Aquí dejamos el código de este ejemplo:

#include <Adafruit_Fingerprint.h>
// On Leonardo/Micro or others with hardware serial, use those! #0 is green wire, #1 is white
// uncomment this line:
// #define mySerial Serial1
// 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)
// comment these two lines if using hardware serial
SoftwareSerial mySerial(2, 3);
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
uint8_t id;
void setup()
{
Serial.begin(9600);
while (!Serial); // For Yun/Leo/Micro/Zero/...
delay(100);
Serial.println("\n\nAdafruit Fingerprint sensor enrollment");
// 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) { delay(1); }
}
}
uint8_t readnumber(void) {
uint8_t num = 0;
while (num == 0) {
while (! Serial.available());
num = Serial.parseInt();
}
return num;
}
void loop() // run over and over again
{
Serial.println("Ready to enroll a fingerprint!");
Serial.println("Please type in the ID # (from 1 to 127) you want to save this finger as...");
id = readnumber();
if (id == 0) {// ID #0 not allowed, try again!
return;
}
Serial.print("Enrolling ID #");
Serial.println(id);

while (! getFingerprintEnroll() );
} uint8_t getFingerprintEnroll() { int p = -1;
Serial.print("Waiting for valid finger to enroll as #"); Serial.println(id);
while (p != FINGERPRINT_OK) {
p = finger.getImage();
switch (p) {
case FINGERPRINT_OK:
Serial.println("Image taken");
break;
case FINGERPRINT_NOFINGER:
Serial.println(".");
break;
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;
}
Serial.println("Remove finger");
delay(2000);
p = 0;
while (p != FINGERPRINT_NOFINGER) {
p = finger.getImage();
}
Serial.print("ID "); Serial.println(id);
p = -1;
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;
}
} // 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(id);

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(id);
p = finger.storeModel(id);
if (p == FINGERPRINT_OK) {
Serial.println("Stored!");
} 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;
}
}

Con este programa, guardaremos las huellas que después queramos que reconozca el sensor. Simplemente cargaremos el programa en nuestro Arduino y al ejecutarlo nos va a pedir un nº identificador para la huella que vayamos a guardar. Empezamos con el 0, y al dar Intro, nos pedirá que pongamos la huella en el sensor, nos pedirá quitarla y volverla a poner.
Estos mismos pasos los tenemos que hacer para cada una de las huellas que queramos guardar, cambiando, por supuesto, el nº identificador de cada una de ellas.

Una vez hecho esto, tendremos que cargar otro programa que trae también la librería, con el que se comparará la huella que pongamos con las que tiene en su base de datos(las que hemos guardado antes). Este programa también lo tendremos disponible al cargar la librería, está disponible en Ejemplos/Fingerprint. Su código es:

#include <Adafruit_Fingerprint.h>

// On Leonardo/Micro or others with hardware serial, use those! #0 is green wire, #1 is white
// uncomment this line:
// #define mySerial Serial1 // 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)
// comment these two lines if using hardware serial
SoftwareSerial mySerial(2, 3); Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); void setup()
{
Serial.begin(9600);
while (!Serial); // For Yun/Leo/Micro/Zero/...
delay(100);
Serial.println("\n\nAdafruit finger detect test"); // 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); }
} 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");
}
} void loop() // run over and over again
{
getFingerprintIDez();
delay(50); //don't ned to run this at full speed.
} 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); return finger.fingerID;
} // returns -1 if failed, otherwise returns ID #
int getFingerprintIDez() {
uint8_t p = finger.getImage();
if (p != FINGERPRINT_OK) return -1; p = finger.image2Tz();
if (p != FINGERPRINT_OK) return -1; p = finger.fingerFastSearch();
if (p != FINGERPRINT_OK) return -1;

// found a match!
Serial.print("Found ID #"); Serial.print(finger.fingerID);
Serial.print(" with confidence of "); Serial.println(finger.confidence);
return finger.fingerID;
}



Con este programa cargado, vemos que si le ponemos cualquiera de las huellas que hemos guardado previamente, la reconoce y aparece en pantalla un mensaje “Found Id #0”. Si ponemos cualquier otra huella no nos aparece mensaje.
Esto, por supuesto, tiene muchas utilidades, pero eso ya lo veremos en próximos cursos.

No hay comentarios: