KKM: SENZOR OTISKA PRSTA

Senzor otiska prsta

Početnik si s Dasduinom. Ili s elektronikom? Za oko ti je zapeo određeni modul, ali ne znaš kako ga koristiti? Bez brige, tu je KKM! Kako Koristiti Module (KKM) je serija blog tutorijala tvrtke soldered na kojoj ćeš pronaći sve što ti treba kako bi započeo rad sa svojim omiljenim modulom. Tutorijali obuhvaćaju: tehničke karakteristike, princip rada, upute kako povezati modul s Dasduinom te osnovni kod. Sve ostalo prepuštamo tebi na maštu.

UVOD

U ovom tutorijalu upoznat ćemo senzor otiska prsta koji se koristi u mnogim primjenama gdje je potrebno da se određeni korisnik prijavi. Kao što znamo većina pametnih telefona podržava otključavanje s otiskom prsta, mnoge prostorije su štićene na ovaj način od neovlaštenog ulaza. Ovaj senzor nalazi primjenu u raznim sustavima sigurnosti jer koristi baš otisak prsta koji je jedinstven za svakoga. Kako bi zaštitili nešto bitno od sada će te to moči napraviti s vrlo visokom razinom sigurnosti uz ovaj senzor, ali da bi saznali kako krenimo s upoznavanjem samog senzora.

KAKO RADI?

Da bi mogli napraviti nešto korisno sa senzorom otiska prsta prvo ćemo se upoznati s načinom rada senzora. Ovaj senzor je optički što znači da pomoću svijetla prepoznaje otisak prsta, a osim optičkog ima još i kapacitivni senzor( koristi se na mobilnim uređajima) i ultrazvučni. Optički senzor otiska prsta je starija tehnologija pa je stoga i jednostavnija od ostalih, ali baš zbog jednostavnosti rada je pristupačna za razne projekte.
Kao što znamo na prstu imamo ispupčenja i udubine koje su jedinstvene za svaku osobu i to je otisak prsta. Da bi detektirao udubine i ispupčenja senzor otiska prsta koristi led diode kao osvjetljenje i fotodetektor kako bi primio odbijene zrake svjetlosti. Naravno senzor nema samo jednu diodu i fotodetektor nego se unutar njega nalazi puno fotodetektora smještenih u matricu, kao i prizma i leća kako bi točnije mogao primiti odbijenu svjetlost. Na slici vidimo princip na koji senzor radi i koji je prethodno objašnjen.

Naravno u senzoru imamo i kontroler koji upravlja diodama i fotodetektorima te analizira primljene signale. Kako bi mogao prepoznati otisak kontroler u memoriji ima bazu spremljenih otisaka te ih uspoređuje s trenutnim otiskom i ako ga ima u bazi vraća nam koliko se podudaraju.

KAKO POVEZATI?

Senzor koristi serijsku komunikaciju za razmjenu podataka s mikrokontrolerom, te ga je jednostavno povezati. Senzor ima 6 pinski kabl, ali za spajanje se koristi samo 4 pina( 2 za napajanje i 2 za komunikaciju). RX pin spajamo na D3, a TX sa senzora spajamo na D2 na Dasduinu, za napajanje koristimo 3,3V kako je naznačeno na senzoru.
Kako bi senzor lakše povezali koristi se adapter koji nam pinove sa PicoBlade headera na standardni header kako bi ga mogli povezati s mikrokontrolerom, adapter se može naći na linku.

ARDUINO KOD

Kako bi mogli raditi sa senzorom potrebno je preuzeti i instalirati biblioteku s linka. Naravno ako ne znate kako instalirati biblioteku tu je tutorial koji objašnjava postupak instalacije.
U dijelu gdje je objašnjen način rada spomenuta je baza otisaka koju senzor ima pohranjenu unutar svoje memorije. Naravno kada kupimo senzor u njemu nema niti jedan otisak te je potrebno je dodati novi otiska, a možemo imati do 200 spremljenih otisaka što je jako puno.
Kako bi spremili novi otisak u bazu podataka potrebno je prebaciti dani kod na mikrokontroler te otvoriti Serial monitor i pratiti upute koje nam se ispisuju. Svaki otisak je spremljen pod identifikacijskim brojem kojeg biramo prilikom spremanja otiska u bazu, te ga je potrebno zapamtiti jer će nam taj broj senzor vračati kada skeniramo određeni prst koji je u bazi.

//uključujemo biblioteku za rad sa senzorom otiska prsta
#include <Adafruit_Fingerprint.h>
SoftwareSerial mySerial(2, 3);//(RX, TX)( D2(RX) sa Croduina spajamo na TX senzora, a D3(TX) sa Croduina na RX senzora
//Konstruktor za Adafruit_Fingerprint biblioteku kojemu predajemo Serijski port na koji je spojen senzor( u našem slučaju je to Softverski serijski port)
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
//varijabla u koju spremamo ID pod kojim korisnik želi spremiti novi otisak prsta
uint8_t id;
void setup()
{
 Serial.begin(9600);//Inicijalizacija serijske komunikacije( brzina 9600 bauda) za ispis poruka na Serial monitor
 delay(100);//pauza 100 ms
 Serial.println("\nUpisivanje novog otiska prsta");
 
 finger.begin(57600);//Inicijalizacija komunikacije sa senzorom
 
 //provjeravamo lozinku senzora koja je postavljena u biblioteci( može se promijeniti u kodu)
 //ako je lozinka točna( ako nismo mijenjali onda će biti točna) ispisujemo poruku da je senzor pronađen( ako smo provjerili lozinku znači da je i komunikacija sa senzorom uspjela)
 if (finger.verifyPassword()) {
 Serial.println("Pronadjen senzor otiska prsta!");
 } else {//ako je lozinka netočna ili nije pronađen senzor ispisujemo poruku na serial monitor ostajemo u beskonačnoj while petlji
 Serial.println("Senzor otiska prsta nije pronadjen");
 while (1) while (1) { delay(1); }
 }
}
//funkcija koja čita broj sa Serial monitora i vraća taj broj
uint8_t readnumber(void) {
 uint8_t num = 0;
 
 while (num == 0) {
 while (! Serial.available());
 num = Serial.parseInt();
 }
 return num;
}
void loop()
{
 Serial.println("\nSpreman za dodavanje otiska!");
 Serial.println("Unesite ID#(od 1 do 127) pod kojim zelite spremiti novi otisak prsta...");
 id = readnumber();
 if (id == 0) {//ako je uneseni broj 0 vraćamo se na početak i tražimo ponovno unošenje broja
 return;
 }
 Serial.print("Upisivanje ID #");
 Serial.println(id);
 //pozivamo funkciju koja obavlja unošenje novog otiska
 while (! getFingerprintEnroll() );
}
uint8_t getFingerprintEnroll() {
 int p = -1;
 Serial.print("cekam novi otisak prsta s ID #"); Serial.println(id);
 //sve dok ne dobijemo ispravan otisak ponavljamo postupak slikanja
 while (p != FINGERPRINT_OK) {
 p = finger.getImage();// uzimamo sliku sa senzora otiska i u varijablu p spremamo povratnu vrijednost
 //prema vrijednosti u varijabli p ispisujemo odgovarajuću poruku što je senzor napravio, odnosno dali se dogodila greška
 switch (p) {
 case FINGERPRINT_OK:
 Serial.println("Slika napravljena");
 break;
 case FINGERPRINT_NOFINGER:
 Serial.println(".");
 delay(100);//pauza da se . ne ispisuje stalno
 break;
 case FINGERPRINT_PACKETRECIEVEERR:
 Serial.println("Komunikacijska greska");
 break;
 case FINGERPRINT_IMAGEFAIL:
 Serial.println("Greska sa slikom");
 break;
 default:
 Serial.println("Nepoznata greska");
 break;
 }
 }
 p = finger.image2Tz(1);//snimljenu sliku pretvaramo u drugi format koji se može pohraniti u memoriju
 switch (p) {
 //prema vrijednosti u varijabli p ispisujemo dali je pretvaranje uspjelo ili se dogodila greška
 case FINGERPRINT_OK:
 Serial.println("Slika pretvorena");
 break;
 case FINGERPRINT_IMAGEMESS:
 Serial.println("Slika neispravna");
 return p;
 case FINGERPRINT_PACKETRECIEVEERR:
 Serial.println("Komunikacijska greska");
 return p;
 case FINGERPRINT_FEATUREFAIL:
 Serial.println("Nemoguce pronaci znacajke otiska");
 return p;
 case FINGERPRINT_INVALIDIMAGE:
 Serial.println("Nemoguce pronaci znacajke otiska");
 return p;
 default:
 Serial.println("Nepoznata greska");
 return p;
 }
 // korisnik treba maknuti prst sa senzora te onda ponovno staviti kako bi potvrdili otisak
 Serial.println("Maknite prst sa senzora");
 delay(2000);
 p = 0;
 while (p != FINGERPRINT_NOFINGER) {
 p = finger.getImage();
 }
 Serial.print("ID "); Serial.println(id);
 p = -1;
 Serial.println("Stavite isti prst ponovno na senzor");
 //kada korisnik ponovno stavi prst ponavljamo slikanje i konverziju slike te ispisujemo poruke ako se dogodi greška kao i u prethodnom slučaju
 while (p != FINGERPRINT_OK) {
 p = finger.getImage();
 switch (p) {
 case FINGERPRINT_OK:
 Serial.println("Slika napravljena");
 break;
 case FINGERPRINT_NOFINGER:
 Serial.print(".");
 delay(100);//pauza da se . ne ispisuje stalno
 break;
 case FINGERPRINT_PACKETRECIEVEERR:
 Serial.println("Komunikacijska greska");
 break;
 case FINGERPRINT_IMAGEFAIL:
 Serial.println("Greska sa slikom");
 break;
 default:
 Serial.println("Nepoznata greska");
 break;
 }
 }
 p = finger.image2Tz(2);
 switch (p) {
 case FINGERPRINT_OK:
 Serial.println("Slika pretvorena");
 break;
 case FINGERPRINT_IMAGEMESS:
 Serial.println("Slika neispravna");
 return p;
 case FINGERPRINT_PACKETRECIEVEERR:
 Serial.println("Komunikacijska greska");
 return p;
 case FINGERPRINT_FEATUREFAIL:
 Serial.println("Nemoguce pronaci znacajke otiska");
 return p;
 case FINGERPRINT_INVALIDIMAGE:
 Serial.println("Nemoguce pronaci znacajke otiska");
 return p;
 default:
 Serial.println("Nepoznata greska");
 return p;
 }
 
 //Ispisujemo korisniku da je obrada slike gotova i da se izrađuje model otiska
 Serial.print("Pravim model za #"); Serial.println(id);
 
 p = finger.createModel();//funkcija koju pozivamo kako bi napravili model otiska prsta
 // provjeravamo povratnu vrijednost funkcije kako bi znali što je napravljeno
 if (p == FINGERPRINT_OK) {
 Serial.println("Otisci se poklapaju!");
 } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
 Serial.println("Komunikacijska greska");
 return p;
 } else if (p == FINGERPRINT_ENROLLMISMATCH) {
 Serial.println("Otisci se ne poklapaju");
 return p;
 } else {
 Serial.println("Nepoznata greska");
 return p;
 }
 //ako se otisci poklapaju onda spremamo model otiska u memoriju senzora
 Serial.print("ID "); Serial.println(id);
 p = finger.storeModel(id);//funkcija za spremanje modela otiska u memoriju senzora koja nam vraća jeli spremanje uspjelo ili ne
 //Ispisujemo poruku ovisno o povratnoj vrijednosti funkcije za spremanje
 if (p == FINGERPRINT_OK) {
 Serial.println("Spremljeno!\n");
 } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
 Serial.println("Komunikacijska greska");
 return p;
 } else if (p == FINGERPRINT_BADLOCATION) {
 Serial.println("Nemoguce spremiti na toj lokaciji ( probajte drugi ID)");
 return p;
 } else if (p == FINGERPRINT_FLASHERR) {
 Serial.println("Greska sa spremanjem u memoriju");
 return p;
 } else {
 Serial.println("Nepoznata greska");
 return p;
 }
}

Sada kada imamo otiske u bazi idemo isprobati kako senzor radi, te nam za to treba drugi kod koji je dan u primjeru. U ovom kodu kada senzor očita otisak koji je u bazi vrati nam identifikacijski broj koji smo dodijelili određenom otisku prilikom spremanja otisaka u bazu.

//uključujemo biblioteku za rad sa senzorom otiska prsta
#include <Adafruit_Fingerprint.h>
SoftwareSerial mySerial(2, 3);//(RX, TX)( D2(RX) sa Croduina spajamo na TX senzora, a D3(TX) sa Croduina na RX senzora
//Konstruktor za Adafruit_Fingerprint biblioteku kojemu predajemo Serijski port na koji je spojen senzor( u našem slučaju je to Softverski serijski port)
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
void setup()
{
 Serial.begin(9600);//Inicijalizacija serijske komunikacije( brzina 9600 bauda) za ispis poruka na Serial monitor
 delay(100);//pauza 100 ms
 
 Serial.println("\nSenzor otiska prsta_ ocitavanje");
 finger.begin(57600);//Inicijalizacija komunikacije sa senzorom
 delay(5);
 //provjeravamo lozinku senzora koja je postavljena u biblioteci( može se promijeniti u kodu)
 //ako je lozinka točna( ako nismo mijenjali onda će biti točna) ispisujemo poruku da je senzor pronađen( ako smo provjerili lozinku znači da je i komunikacija sa senzorom uspjela)
 if (finger.verifyPassword()) {
 Serial.println("Pronadjen senzor otiska prsta!");
 } else {//ako je lozinka netočna ili nije pronađen senzor ispisujemo poruku na serial monitor ostajemo u beskonačnoj while petlji
 Serial.println("Senzor otiska prsta nije pronadjen");
 while (1) { delay(1); }
 }
 finger.getTemplateCount();//funkcija za dohvaćanje podataka o broju spremljenih otisaka
 //ispisujemo broje spremljenih otisaka na Serial monitor
 Serial.print("Senzor ima "); Serial.print(finger.templateCount); Serial.println(" spremljenih otisaka");
 Serial.println("Prislonite prst za provjeru...");
}
void loop()
{
 getFingerprintIDez();//funkcija u kojoj očitavamo otiska prsta, ako je prst prislonjen na senzor
 delay(50);
}
//funkcija u kojoj očitavamo otisak i koja nam vraća -1 ako se dogodila greška ili ID otiska prsta kao se podudara s nekim od spremljenih otisaka
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;
 
 Serial.print("Pronadjen ID #");
 Serial.print(finger.fingerID); //ispisujemo ID otiska prsta
 Serial.print(" s pouzdanjem ");
 Serial.println(finger.confidence);//ispisujemo koliko je pouzdan pročitan otisak s određenim otiskom iz baze
 return finger.fingerID; //funkcija vraća ID otiska prsta
}

Naravno da ćemo nekada imati potrebu za maknuti određeni otisak iz baze, a to je vrlo jednostavno s ovim senzorom. Potrebno je prebaciti dani kod na mikrokontroler i otvoriti serial monitor, te nakon toga upisati ID otiska koji želimo ukloniti i on će biti uklonjen.

//uključujemo biblioteku za rad sa senzorom otiska prsta
#include <Adafruit_Fingerprint.h>
SoftwareSerial mySerial(2, 3);//(RX, TX)( D2(RX) sa Croduina spajamo na TX senzora, a D3(TX) sa Croduina na RX senzora
//Konstruktor za Adafruit_Fingerprint biblioteku kojemu predajemo Serijski port na koji je spojen senzor( u našem slučaju je to Softverski serijski port)
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
void setup()
{
 Serial.begin(9600);//Inicijalizacija serijske komunikacije( brzina 9600 bauda) za ispis poruka na Serial monitor
 delay(100);//pauza 100 ms
 
 Serial.println("\nBrisanje spremljenih otisaka");
 finger.begin(57600);//Inicijalizacija komunikacije sa senzorom
 //provjeravamo lozinku senzora koja je postavljena u biblioteci( može se promijeniti u kodu)
 //ako je lozinka točna( ako nismo mijenjali onda će biti točna) ispisujemo poruku da je senzor pronađen( ako smo provjerili lozinku znači da je i komunikacija sa senzorom uspjela)
 if (finger.verifyPassword()) {
 Serial.println("Pronadjen senzor otiska prsta!");
 } else {//ako je lozinka netočna ili nije pronađen senzor ispisujemo poruku na serial monitor ostajemo u beskonačnoj while petlji
 Serial.println("Senzor otiska prsta nije pronadjen");
 while (1) while (1) { delay(1); }
 }
}
//funkcija koja čita broj sa Serial monitora i vraća taj broj
uint8_t readnumber(void) {
 uint8_t num = 0;
 
 while (num == 0) {
 while (! Serial.available());
 num = Serial.parseInt();
 }
 return num;
}
void loop()
{
 Serial.println("Unesite ID # otiska (od 1 do 127) koji želite obrisati...");
 uint8_t id = readnumber();//u varijablu id spremamo broj koji nam vraća funkcija readnumber koja čita broj sa Serial monitora
 if (id == 0) {// ako je id nula vraćamo se na početak te ponovno čekamo unos broja
 return;
 }
 Serial.print("Brisanje ID #");
 Serial.println(id);//ispisujemo koji ID se briše
 
 deleteFingerprint(id);// pozivamo funkciju za brisanje otiska
}
// funkcija za brisanje otisaka
uint8_t deleteFingerprint(uint8_t id) {
 uint8_t p = -1;
 
 p = finger.deleteModel(id);//brišemo otisak s predanim ID brojem, a funkcija nam vraća rezultat brisanja
 //ovisno što nam je prethodna funkcija vratila( uspješno brisanje ili pogrešku) ispisujem poruku ovisno što se dogodilo
 if (p == FINGERPRINT_OK) {
 Serial.println("Obrisano!");
 } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
 Serial.println("Komunikacijska greska");
 return p;
 } else if (p == FINGERPRINT_BADLOCATION) {
 Serial.println("Nije moguce obrisati na toj lokaciji");
 return p;
 } else if (p == FINGERPRINT_FLASHERR) {
 Serial.println("Greska pisanja po memoriji");
 return p;
 } else {
 Serial.print("Nepoznata greska: 0x"); Serial.println(p, HEX);
 return p;
 }
}

Zadnji primjer koda služi za brisanje cijele baze otiska, ako ne želimo više koristiti senzor, ili je potrebno iz drugog razloga obrisati sve spremljene otiske sa ovim kodom to možemo učiniti u par koraka.

//uključujemo biblioteku za rad sa senzorom otiska prsta
#include <Adafruit_Fingerprint.h>
SoftwareSerial mySerial(2, 3);//(RX, TX)( D2(RX) sa Croduina spajamo na TX senzora, a D3(TX) sa Croduina na RX senzora
//Konstruktor za Adafruit_Fingerprint biblioteku kojemu predajemo Serijski port na koji je spojen senzor( u našem slučaju je to Softverski serijski port)
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
void setup()
{
 Serial.begin(9600);//Inicijalizacija serijske komunikacije( brzina 9600 bauda) za ispis poruka na Serial monitor
 delay(100);//pauza 100 ms
 
 Serial.println("\n Brisanje svih spremljenih otisaka!");
 Serial.println("Pritisnite Y za nastavak.");
//čekamo sve dok korisnik ne unese Y u serial monitor
 while (1) {
 if (Serial.available() && (Serial.read() == 'Y')) {
 break;
 }
 }
 finger.begin(57600);//Inicijalizacija komunikacije sa senzorom
 delay(5);
 //provjeravamo lozinku senzora koja je postavljena u biblioteci( može se promijeniti u kodu)
 //ako je lozinka točna( ako nismo mijenjali onda će biti točna) ispisujemo poruku da je senzor pronađen( ako smo provjerili lozinku znači da je i komunikacija sa senzorom uspjela)
 if (finger.verifyPassword()) {
 Serial.println("Pronadjen senzor otiska prsta!");
 } else {//ako je lozinka netočna ili nije pronađen senzor ispisujemo poruku na serial monitor ostajemo u beskonačnoj while petlji
 Serial.println("Senzor otiska prsta nije pronadjen");
 while (1) { delay(1); }
 }
 //funkciaj za brisanje cijele baze senzora
 finger.emptyDatabase();
Serial.println("Otisci obrisani!");
Serial.println("Baza otisaka je prazna");
}
void loop() {
}