So, first of all, we need to make the all the required connection as shown in Circuit Diagram below. Connections are simple, we have just connected fingerprint module to PIC microcontroller’s UART. A 16×2 LCD is used for displaying all messages. A 10k pot is also used with LCD for controlling the contrast of the same. 16×2 LCD data pins are connected PORTA pins. LCD’s d4, d5, d6, and d7 pins are connected with Pin RA0, RA1, RA2, and RA3 of PIC microcontroller respectively. Four push buttons (or keypad) is connected to PORTD’s Pin RD0, RD1, RD2, and RD. LED is also connected at port PORTC’s pin RC3. Here we have used an 18.432000 MHz external crystal oscillator to clock the microcontroller.
Operation of this project is simple, just upload hex file, generated from source code, into the PIC microcontroller with the help of PIC programmer or burner (PIckit2 or Pickit3 or others)and then you will see some intro messages over LCD and then the user will be asked to enter a choice for operations. To match fingerprint user need to press key 1 then LCD will ask for Place Finger on Finger Print Sensor. Now by putting a finger over fingerprint module, we can check whether our fingerprints are already stored or not. If your fingerprint is stored then LCD will show the message with the storing ID of fingerprint-like ‘ID:2’ otherwise it will show ‘Not Found’.
FingerPrint interfacing Note: Program of this project is a little bit complex for a beginner. But its simple interfacing code made by using reading r305 fingerprint module datasheet. All the instruction of functioning of this fingerprint module is given in the datasheet.
In programming, we have used the below frame format.
Code
#define _XTAL_FREQ 18432000
#include <xc.h>
#include<pic.h>
#include <stdio.h>
#include <stdlib.h>
// BEGIN CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
//END CONFIG
#define uchar unsigned char
#define uint unsigned int
#define LCDPORTDIR TRISA
#define LCDPORT PORTA
#define RS RE1
#define EN RE0
#define SWPORTdir TRISD
#define SWPORT PORTD
#define enrol RD4
#define match RD5
#define delet RD7
#define ok RD6
#define up RD5
#define down RD4
#define LEDdir TRISC3
#define LED RC3
#define HIGH 1
#define LOW 0
#define PASS 0
#define ERROR 1
#define checkKey(id) id=up<down?++id:down<up?–id:id;
uchar buf[20];
uchar buf1[20];
volatile uint index=0;
volatile int flag=0;
uint msCount=0;
uint g_timerflag=1;
volatile uint count=0;
uchar data[10];
uint id=1;
enum
{
CMD,
DATA,
SBIT_CREN=4,
SBIT_TXEN,
SBIT_SPEN,
};
const char passPack[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x7, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1B};
const char f_detect[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x3, 0x1, 0x0, 0x5};
const char f_imz2ch1[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x4, 0x2, 0x1, 0x0, 0x8};
const char f_imz2ch2[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x4, 0x2, 0x2, 0x0, 0x9};
const char f_createModel[]={0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x3,0x5,0x0,0x9};
char f_storeModel[]={0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x6,0x6,0x1,0x0,0x1,0x0,0xE};
const char f_search[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x8, 0x1B, 0x1, 0x0, 0x0, 0x0, 0xA3, 0x0, 0xC8};
char f_delete[]={0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x7,0xC,0x0,0x0,0x0,0x1,0x0,0x15};
void lcdwrite(uchar ch,uchar rw)
{
LCDPORT= ch>>4 & 0x0F;
RS=rw;
EN=1;
__delay_ms(5);
EN=0;
LCDPORT= ch & 0x0F;
EN=1;
__delay_ms(5);
EN=0;
}
lcdprint(char *str)
{
while(*str)
{
lcdwrite(*str++,DATA);
//__delay_ms(20);
}
}
lcdbegin()
{
uchar lcdcmd[5]={0x02,0x28,0x0E,0x06,0x01};
uint i=0;
for(i=0;i<5;i++)
lcdwrite(lcdcmd[i], CMD);
}
void lcdinst()
{
lcdwrite(0x80, CMD);
lcdprint(“1-Match 2-Enroll”);
lcdwrite(0xc0, CMD);
lcdprint(“3-delete Finger”);
__delay_ms(10);
}
void serialbegin(uint baudrate)
{
SPBRG = (18432000UL/(long)(64UL*baudrate))-1; // baud rate @18.432000Mhz Clock
TXSTAbits.SYNC = 0; //Setting Asynchronous Mode, ie UART
RCSTAbits.SPEN = 1; //Enables Serial Port
TRISC7 = 1; //As Prescribed in Datasheet
TRISC6 = 0; //As Prescribed in Datasheet
RCSTAbits.CREN = 1; //Enables Continuous Reception
TXSTAbits.TXEN = 1; //Enables Transmission
GIE = 1; // ENABLE interrupts
INTCONbits.PEIE = 1; // ENable peripheral interrupts.
PIE1bits.RCIE = 1; // ENABLE USART receive interrupt
PIE1bits.TXIE = 0; // disable USART TX interrupt
PIR1bits.RCIF = 0;
}
void serialwrite(char ch)
{
while(TXIF==0); // Wait till the transmitter register becomes empty
TXIF=0; // Clear transmitter flag
TXREG=ch; // load the char to be transmitted into transmit reg
}
serialprint(char *str)
{
while(*str)
{
serialwrite(*str++);
}
}
void interrupt SerialRxPinInterrupt(void)
{
if((PIR1bits.RCIF == 1) && (PIE1bits.RCIE == 1))
{
uchar ch=RCREG;
buf[index++]=ch;
if(index>0)
flag=1;
RCIF = 0; // clear rx flag
}
}
void serialFlush()
{
for(int i=0;i<sizeof(buf);i++)
{
buf[i]=0;
}
}
int sendcmd2fp(char *pack, int len)
{
uint res=ERROR;
serialFlush();
index=0;
__delay_ms(100);
for(int i=0;i<len;i++)
{
serialwrite(*(pack+i));
}
__delay_ms(1000);
if(flag == 1)
{
if(buf[0] == 0xEF && buf[1] == 0x01)
{
if(buf[6] == 0x07) // ack
{
if(buf[9] == 0)
{
uint data_len= buf[7];
data_len<<=8;
data_len|=buf[8];
for(int i=0;i<data_len;i++)
data[i]=0;
for(int i=0;i<data_len-2;i++)
{
data[i]=buf[10+i];
}
res=PASS;
}
else
{
res=ERROR;
}
}
}
index=0;
flag=0;
return res;
}
}
uint getId()
{
uint id=0;
lcdwrite(1, CMD);
while(1)
{
lcdwrite(0x80, CMD);
checkKey(id);
sprintf(buf1,”Enter Id:%d “,id);
lcdprint(buf1);
__delay_ms(200);
if(ok == LOW)
return id;
}
}
void matchFinger()
{
lcdwrite(1,CMD);
lcdprint(“Place Finger”);
lcdwrite(192,CMD);
__delay_ms(2000);
if(!sendcmd2fp(&f_detect[0],sizeof(f_detect)))
{
if(!sendcmd2fp(&f_imz2ch1[0],sizeof(f_imz2ch1)))
{
if(!sendcmd2fp(&f_search[0],sizeof(f_search)))
{
lcdwrite(1,CMD);
lcdprint(“Finger Found”);
uint id= data[0];
id<<=8;
id+=data[1];
uint score=data[2];
score<<=8;
score+=data[3];
sprintf(buf1,”Id:%d Score:%d”,id,score);
lcdwrite(192,CMD);
lcdprint(buf1);
LED=1;
__delay_ms(1000);
LED=0;
}
else
{
lcdwrite(1,CMD);
lcdprint(“Not Found”);
}
}
}
else
{
lcdprint(“No Finger”);
}
__delay_ms(2000);
}
void enrolFinger()
{
lcdwrite(1,CMD);
lcdprint(“Enroll Finger”);
__delay_ms(2000);
lcdwrite(1,CMD);
lcdprint(“Place Finger”);
lcdwrite(192,CMD);
__delay_ms(1000);
if(!sendcmd2fp(&f_detect[0],sizeof(f_detect)))
{
if(!sendcmd2fp(&f_imz2ch1[0],sizeof(f_imz2ch1)))
{
lcdprint(“Finger Detected”);
__delay_ms(1000);
lcdwrite(1,CMD);
lcdprint(“Place Finger”);
lcdwrite(192,CMD);
lcdprint(” Again “);
__delay_ms(2000);
if(!sendcmd2fp(&f_detect[0],sizeof(f_detect)))
{
if(!sendcmd2fp(&f_imz2ch2[0],sizeof(f_imz2ch2)))
{
lcdwrite(1,CMD);
lcdprint(“Finger Detected”);
__delay_ms(1000);
if(!sendcmd2fp(&f_createModel[0],sizeof(f_createModel)))
{
id=getId();
f_storeModel[11]= (id>>8) & 0xff;
f_storeModel[12]= id & 0xff;
f_storeModel[14]= 14+id;
if(!sendcmd2fp(&f_storeModel[0],sizeof(f_storeModel)))
{
lcdwrite(1,CMD);
lcdprint(“Finger Stored”);
sprintf(buf1,”Id:%d”,id);
lcdwrite(192,CMD);
lcdprint(buf1);
__delay_ms(1000);
}
else
{
lcdwrite(1,CMD);
lcdprint(“Finger Not Stored”);
}
}
else
lcdprint(“Error”);
}
else
lcdprint(“Error”);
}
else
lcdprint(“No Finger”);
}
}
else
{
lcdprint(“No Finger”);
}
__delay_ms(2000);
}
void deleteFinger()
{
id=getId();
f_delete[10]=id>>8 & 0xff;
f_delete[11]=id & 0xff;
f_delete[14]=(21+id)>>8 & 0xff;
f_delete[15]=(21+id) & 0xff;
if(!sendcmd2fp(&f_delete[0],sizeof(f_delete)))
{
lcdwrite(1,CMD);
sprintf(buf1,”Finger ID %d “,id);
lcdprint(buf1);
lcdwrite(192, CMD);
lcdprint(“Deleted Success”);
}
else
{
lcdwrite(1,CMD);
lcdprint(“Error”);
}
__delay_ms(2000);
}
int main()
{
void (*FP)();
ADCON1=0b00000110;
LEDdir= 0;
SWPORTdir=0xF0;
SWPORT=0x0F;
serialbegin(57600);
LCDPORTDIR=0x00;
TRISE=0;
lcdbegin();
lcdprint(“Fingerprint”);
lcdwrite(192,CMD);
lcdprint(“Interfacing”);
__delay_ms(2000);
lcdwrite(1,CMD);
lcdprint(“Using PIC16F877A”);
lcdwrite(192,CMD);
lcdprint(“Circuit Digest”);
__delay_ms(2000);
index=0;
while(sendcmd2fp(&passPack[0],sizeof(passPack)))
{
lcdwrite(1,CMD);
lcdprint(“FP Not Found”);
__delay_ms(2000);
index=0;
}
lcdwrite(1,CMD);
lcdprint(“FP Found”);
__delay_ms(1000);
lcdinst();
while(1)
{
FP=match<enrol?matchFinger:enrol<delet?enrolFinger:delet<enrol?deleteFinger:lcdinst;
FP();
}
return 0;
}