Silicon Fingerprint Scanner

From LinkSprite Playgound
Jump to: navigation, search

Description

LinkSprite SD-ARA-EM02 series is a serial of high-performance fingerprint identification module. It has simple structure and powerful features. Used together with host, it can do fingerprint record, image processing, features extraction, model generation, model storage, fingerprints matching (including 1:1 and 1:N), fingerprints delete and etc. It is widely used in E-commerce, information security, access control, identity authentication, and other security application field.

[model:SEN_ID_FP_AREA]

Fingerprintscanner.jpg

Features

  • Module has embedded completed fingerprints identification algorithm and protocols.
  • Standard TTL serial communication
  • Module has embedded fingerprint library storage.
  • Specification of embedded algorithm:
  • FRR < 0.1%
  • FAR < 0.001%;
  • Image processing time < 0.4s
  • Storage occupied 52K bytes.
  • support 1:1 matching and 1:N search matching.
  • 1:100 searching time < 0.5s
  • Module has embedded 32-bit random number generator

Arduino Sample Code

#include <SoftwareSerial.h>                            //Include the NewSoftSerial library to send serial commands to the cellular module.
#include <string.h>  
SoftwareSerial  FPM10A(2,3);                           //Create a 'fake' serial port. Pin 2 is the Rx pin, pin 3 is the Tx pin.
/*----------外部命令,数组位数要大于输入的字符个数----------*/
char receive_command[20]={};
char GenImg[10]="GenImg ";                             //录指纹图像
char UpImg[10]="UpImg ";                               //上传图像
char DownImg[10]="DownImg ";                           //下载图像
char Img1Tz[10]="Img1Tz ";                             //图像生成特征存放在CharBuffer1
char Img2Tz[10]="Img2Tz ";                             //图像生成特征存放在CharBuffer2
char RegMode1[10]="RegMode1 ";                         //特征合成模板
char UpChar[10]="UpChar ";                             //上传特征或模板
char DownChar[10]="DownChar ";                         //下载特征或模板
char Store[10]="Store ";                               //存储模板
char LoadChar[10]="LoadChar ";                         //读出模板
char DeletChar[11]="DeletChar ";                       //删除模板
char Empty[10]="Empty ";                               //清空指纹库
char Match[10]="Match ";                               //精确对比两枚指纹特征
char Search[10]="Search ";                             //搜索指纹
char Check[10]="Check ";
 
/*----------接收字符串的的循环个数数值----------*/
char cnt;
unsigned int Templete_Num;
unsigned int ACK_Sum;
/*----------FPM10A接收命令后应答数组----------*/
volatile unsigned char UART1_FINGERPRINT_RECEVICE_BUFFER[24];
unsigned char receive_ACK[24];
/*----------FINGERPRINT通信协议定义-----------*/
const unsigned char FP_Pack_Head[6] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF};                                               //协议包头
const unsigned char FP_VfyPwd[10] = {0x01,0x00,0x07,0x13,0x11,0x11,0x11,0x11,0x00,0x5f};   
const unsigned char FP_Get_Img[6] = {0x01,0x00,0x03,0x01,0x0,0x05};                                                  //获得指纹图像
const unsigned char FP_Templete_Num[6] ={0x01,0x00,0x03,0x1D,0x00,0x21 };                                            //获得模版总数
const unsigned char FP_Search[11]={0x01,0x0,0x08,0x04,0x01,0x0,0x0,0x03,0xA1,0x0,0xB2};                              //搜索指纹搜索范围0 - 929
const unsigned char FP_Search_0_9[11]={0x01,0x0,0x08,0x04,0x01,0x0,0x0,0x0,0x13,0x0,0x21};                           //搜索0-9号指纹
unsigned char FP_Img_To_Buffer1[7]={0x01,0x0,0x04,0x02,0x01,0x0,0x08};                                               //将图像放入到BUFFER1
unsigned char FP_Img_To_Buffer2[7]={0x01,0x0,0x04,0x02,0x02,0x0,0x09};                                               //将图像放入到BUFFER2
unsigned char FP_Reg_Model[6]={0x01,0x0,0x03,0x05,0x0,0x09};                                                         //将BUFFER1跟BUFFER2合成特征模版
unsigned char FP_Delet_All_Model[6]={0x01,0x0,0x03,0x0d,0x00,0x11};                                                  //删除指纹模块里所有的模版
unsigned char FP_Reg_Match[6]={0x01,0x00,0x03,0x03,0x00,0x07};                                                       //对比charbuffer1与charbuffer2
unsigned char FP_Reg_Store[9]={0x01,0x00,0x06,0x06,0x02,0x00,0x00,0x00,0x0f};                                        //存储charbuffer2 to 模板 ID0
unsigned char FP_Reg_LoadChar[9]={0x01,0x00,0x06,0x07,0x02,0x00,0x00,0x00,0x10};                                     //读出模板ID0 to charbuffer2
volatile unsigned char  FP_Save_Finger[9]={0x01,0x00,0x06,0x06,0x01,0x00,0x0B,0x00,0x19};                            //将BUFFER1中的特征码存放到指定的位置
volatile unsigned char FP_Delete_Model[10]={0x01,0x00,0x07,0x0C,0x0,0x0,0x0,0x1,0x0,0x0};                            //删除指定的模版
//volatile unsigned char FINGER_NUM;
/*----------初始化-----------*/
void setup()
{
  pinMode(3, OUTPUT);  
  Serial.begin(9600); // 打开串口,设置波特率为9600 bps
  FPM10A.begin(9600);
}
/*----------循环主程序-----------*/
void loop()
{
  if (Serial.available() > 0)                                                    //判断串口缓冲器是否有数据装入
  {
    receive_command[cnt] = Serial.read();                                        //读取串口
    if( receive_command[cnt]==' ')
    {
      if(strcmp(receive_command,Check)==0)                                        //查看输入字符串是否是Check
      {
          Check_single_fingerprint();
      }   
 
      else if(strcmp(receive_command,Store)==0)                                        //查看输入字符串是否是Check
      {
          Store_Number_Fingerprint();
      } 
      else if(strcmp(receive_command,Search)==0)                                        //查看输入字符串是否是Check
      {
         Search_One_Fingerprint();
      }   
      else if(strcmp(receive_command,Empty)==0)                                        //查看输入字符串是否是Check
      {
         Empty_Finger();
      }   
 
 
      /*---------- 查看字符串是否为指定字符串,不是就输出错误提示 -----------*/
      else
      {
        Serial.println("ERROR Command");
      } 
      /*---------- 输入一个字符串命令执行结束后,将命令数组跟位数清零 -----------*/
      Command_Clear();
      cnt=0;
     }
    /*---------- 如果字符串没到空格结尾时,自加一 -----------*/
    else
    {
        cnt++;
    }
  }
}
 
/*------------------ UART1_Send_Byte(unsigned char command_data)-----------------------*/
void UART1_Send_Byte(unsigned char command_data)
{
  FPM10A.print(command_data);
} 
 
 
//COMMAND_CLEAR
void Command_Clear(void)
{  
   unsigned int i;
   for(i=0;i<20;i++) //包头
     {
       receive_command[i]= 0x00;
     }
}
/*------------------ UART1_Recrive_Byte(unsigned char command_data)-----------------------*/
unsigned char UART1_Receive_Byte(void)
{
  unsigned char data;
  data = FPM10A.read(); //读取串口
  return data;
}
 
/*------------------ 12位应答数据存储 --------------------------*/
 
void array_ACK(unsigned char temp)
{
    for(unsigned char i=0;i<temp;i++)                                           
    {
       receive_ACK[i]= FPM10A.read();
    }
}
/*------------------ FINGERPRINT命令字 --------------------------*/
 
//FINGERPRINT_获得指纹图像命令
void FINGERPRINT_Cmd_Get_Img(void)
{
    unsigned char i;
 
    for(i=0;i<6;i++) //发送包头
       UART1_Send_Byte(FP_Pack_Head[i]);
 
    for(i=0;i<6;i++) //发送命令 0x1d
       UART1_Send_Byte(FP_Get_Img[i]);
}
 
//讲图像转换成特征码存放在Buffer1中
void FINGERPRINT_Cmd_Img_To_Buffer1(void)
{
 	    unsigned char i;
 
	       for(i=0;i<6;i++)    //发送包头
	         {
    	       UART1_Send_Byte(FP_Pack_Head[i]);   
   		     }
 
   		   for(i=0;i<7;i++)   //发送命令 将图像转换成 特征码 存放在 CHAR_buffer1
             {
      		   UART1_Send_Byte(FP_Img_To_Buffer1[i]);
   		     }
}
 
//将图像转换成特征码存放在Buffer2中
void FINGERPRINT_Cmd_Img_To_Buffer2(void)
{
     unsigned char i;
           for(i=0;i<6;i++)    //发送包头
	         {
    	       UART1_Send_Byte(FP_Pack_Head[i]);   
   		     }
 
   		   for(i=0;i<7;i++)   //发送命令 将图像转换成 特征码 存放在 CHAR_buffer2
             {
      		   UART1_Send_Byte(FP_Img_To_Buffer2[i]);
   		     }
}
 
//将BUFFER1 跟 BUFFER2 中的特征码合并成指纹模版
void FINGERPRINT_Cmd_Reg_Model(void)
{
    unsigned char i;    
 
    for(i=0;i<6;i++) //包头
    {
      UART1_Send_Byte(FP_Pack_Head[i]);   
    }
 
    for(i=0;i<6;i++) //命令合并指纹模版
    {
      UART1_Send_Byte(FP_Reg_Model[i]);   
    }
 
}
//对比指纹Match
void FINGERPRINT_Cmd_Match(void)
{
    unsigned char i;    
 
    for(i=0;i<6;i++) //包头
    {
      UART1_Send_Byte(FP_Pack_Head[i]);   
    }
 
    for(i=0;i<6;i++) //对比指纹Match
    {
      UART1_Send_Byte(FP_Reg_Match[i]);   
    }
}
 
//存储模板
void FINGERPRINT_Cmd_Store(void)
{
    unsigned char i;    
 
    for(i=0;i<6;i++) //包头
    {
      UART1_Send_Byte(FP_Pack_Head[i]);   
    }
 
    for(i=0;i<9;i++) //存储charbuffer2 to 模板0
    {
      UART1_Send_Byte(FP_Reg_Store[i]);   
    }
}
 
//读出模板
void FINGERPRINT_Cmd_LoadChar(void)
{
    unsigned char i;    
 
    for(i=0;i<6;i++) //包头
    {
      UART1_Send_Byte(FP_Pack_Head[i]);   
    }
 
    for(i=0;i<9;i++) //存储charbuffer to 模板0
    {
      UART1_Send_Byte(FP_Reg_LoadChar[i]);   
    }
}
 
 
 
//删除指纹模块里的所有指纹模版
void FINGERPRINT_Cmd_Delete_All_Model(void)
{
     unsigned char i;    
 
    for(i=0;i<6;i++) //包头
      UART1_Send_Byte(FP_Pack_Head[i]);   
 
    for(i=0;i<6;i++) //命令合并指纹模版
      UART1_Send_Byte(FP_Delet_All_Model[i]);   
}
 
 
 
//删除指纹模块里的指定指纹模版
void FINGERPRINT_Cmd_Delete_Model(unsigned int uiID_temp)
{
    volatile unsigned int uiSum_temp = 0;
	unsigned char i;    
 
	FP_Delete_Model[4]=(uiID_temp&0xFF00)>>8;
	FP_Delete_Model[5]=(uiID_temp&0x00FF);
 
	for(i=0;i<8;i++)
	    uiSum_temp = uiSum_temp + FP_Delete_Model[i];
 
	//UART0_Send_Byte(uiSum_temp);	
 
	FP_Delete_Model[8]=(uiSum_temp&0xFF00)>>8;
	FP_Delete_Model[9]=uiSum_temp&0x00FF;
 
 
    for(i=0;i<6;i++) //包头
      UART1_Send_Byte(FP_Pack_Head[i]);   
 
    for(i=0;i<10;i++) //命令合并指纹模版
      UART1_Send_Byte(FP_Delete_Model[i]);   
}
 
 
 
 
//获得指纹模板数量
void FINGERPRINT_Cmd_Get_Templete_Num(void)
{  unsigned int i;
   unsigned char temp[14];
 
   for(i=0;i<6;i++) //包头
      UART1_Send_Byte(FP_Pack_Head[i]);
 
   //发送命令 0x1d
   for(i=0;i<6;i++)
     UART1_Send_Byte(FP_Templete_Num[i]);
 
 
}
 
 
 
 
 
//搜索全部用户999枚
void FINGERPRINT_Cmd_Search_Finger(void)
{
       unsigned char i;	   
	   for(i=0;i<6;i++)   //发送命令搜索指纹库
           {
    	      UART1_Send_Byte(FP_Pack_Head[i]);   
   		   }
 
       for(i=0;i<11;i++)
           {
    	      UART1_Send_Byte(FP_Search[i]);   
   		   }
}
 
 
//指纹模块ID 0-9
void FINGERPRINT_Cmd_Search_Finger_Admin(void)
{
       unsigned char i;	   
	   for(i=0;i<6;i++)   //发送命令搜索指纹库
           {
    	      UART1_Send_Byte(FP_Pack_Head[i]);   
   		   }
 
       for(i=0;i<11;i++)
           {
    	      UART1_Send_Byte(FP_Search_0_9[i]);   
   		   }
 
 
}
void FINGERPRINT_Cmd_Save_Finger( unsigned char ucH_Char,unsigned char ucL_Char )
{
           unsigned long temp = 0;
		   unsigned char i;
 
//           SAVE_FINGER[9]={0x01,0x00,0x06,0x06,0x01,0x00,0x0B,0x00,0x19};//将BUFFER1中的特征码存放到指定的位置
 
           FP_Save_Finger[5] = ucH_Char;
           FP_Save_Finger[6] = ucL_Char;
 
		   for(i=0;i<7;i++)   //计算校验和
		   	   temp = temp + FP_Save_Finger[i];
 
		   FP_Save_Finger[7]=(temp & 0x00FF00) >> 8; //存放校验数据
		   FP_Save_Finger[8]= temp & 0x0000FF;
 
           for(i=0;i<6;i++)    
    	       UART1_Send_Byte(FP_Pack_Head[i]);        //发送包头
 
           for(i=0;i<9;i++)  
      		   UART1_Send_Byte(FP_Save_Finger[i]);      //发送命令 将图像转换成 特征码 存放在 CHAR_buffer1
}
 
//接收反馈数据缓冲
void FINGERPRINT_Recevice_Data(unsigned char ucLength)
{
  unsigned char i;
 
  for (i=0;i<ucLength;i++)
     UART1_FINGERPRINT_RECEVICE_BUFFER[i] = UART1_Receive_Byte();
 
}
void Check_single_fingerprint(void)
{
        /*---------- 循环录指纹图像到imagebuff,直到应答确认 -----------*/
       do{
            FINGERPRINT_Cmd_Get_Img();                                            //发送录指纹图像命令
            array_ACK(12);                                                        //接收返回值,并且判断是否确认
            delay(100);
          }
        while(receive_ACK[9]!=0x00);                                              //如果确认,将输出GenImg_OK
        Serial.println("GenImg_OK"); 
        delay(1000);
         /*---------- 图像生成特征,并且保存到charbuffer1 -----------*/
        FINGERPRINT_Cmd_Img_To_Buffer1();                                         //发送图像生成特征,并且保存到charbuffer1命令
        array_ACK(12);                                                            //接收返回值,并且判断是否确认
        if(receive_ACK[9]==0x00)
        {
          Serial.println("Img1Tz_OK");  
        }
        else
        {
           Serial.println("Img1Tz_ERROR");
        }
       delay(1000);
       /*---------- 读出模板,并且保存到charbuffer2 -----------*/
       FINGERPRINT_Cmd_LoadChar();
       array_ACK(12);                                                            //接收返回值,并且判断是否确认
       if(receive_ACK[9]==0x00)
       {
         Serial.println("LoadChar_OK"); 
       }
       else
       {
         Serial.println("LoadChar_ERROR");
       }
       delay(1000);
       /*---------- 精确对比charbuffer1与charbuffer2 -----------*/
       FINGERPRINT_Cmd_Match();
       array_ACK(12);                                                           //接收返回值,并且判断是否确认
       if(receive_ACK[9]==0x00)
       {
         Serial.println("MAN");
       }  
       else if (receive_ACK[9]==0x08)
       {
         Serial.println("pig");
       }
       delay(1000);
}  
void Store_Number_Fingerprint(void)
{
         Serial.println("Press your finger");
        /*---------- 循环录指纹图像到imagebuff,直到应答确认 -----------*/
       do{
            FINGERPRINT_Cmd_Get_Img();                                            //发送录指纹图像命令
            array_ACK(12);                                                        //接收返回值,并且判断是否确认
            delay(100);
          }
        while(receive_ACK[9]!=0x00);                                              //如果确认,将输出GenImg_OK
        Serial.println("GenImg_OK"); 
        delay(1000);
         /*---------- 图像生成特征,并且保存到charbuffer1 -----------*/
        FINGERPRINT_Cmd_Img_To_Buffer1();                                         //发送图像生成特征,并且保存到charbuffer1命令
        array_ACK(12);                                                            //接收返回值,并且判断是否确认
        if(receive_ACK[9]==0x00)
        {
          Serial.println("Img1Tz_OK");  
        }
        else
        {
           Serial.println("Img1Tz_ERROR");
        }
       delay(1000);
       delay(1000);
        Serial.println("Press your finger");
       /*---------- 循环录指纹图像到imagebuff,直到应答确认 -----------*/
       do{
            FINGERPRINT_Cmd_Get_Img();                                            //发送录指纹图像命令
            array_ACK(12);                                                        //接收返回值,并且判断是否确认
            delay(100);
          }
        while(receive_ACK[9]!=0x00);                                              //如果确认,将输出GenImg_OK
        Serial.println("GenImg_OK"); 
        delay(1000);
         /*---------- 图像生成特征,并且保存到charbuffer2 -----------*/
        FINGERPRINT_Cmd_Img_To_Buffer2();                                         //发送图像生成特征,并且保存到charbuffer2命令
        array_ACK(12);                                                            //接收返回值,并且判断是否确认
        if(receive_ACK[9]==0x00)
        {
          Serial.println("Img2Tz_OK");  
        }
        else
        {
           Serial.println("Img2Tz_ERROR");
        }
       delay(1000);
        /*---------- 合成特征模板RegMode1 -----------*/
        FINGERPRINT_Cmd_Reg_Model();                                              //合成特征模板RegMode1,并且保存到charbuffer1和charbuffer2命令
        array_ACK(12);                                                            //接收返回值,并且判断是否确认
        if(receive_ACK[9]==0x00)
        {
          Serial.println("RegMode1_OK");  
        }
        else
        {
           Serial.println("RegMode1_ERROR");
        }
       delay(1000);
       /*---------- 读出特征模板个数 -----------*/
        FINGERPRINT_Cmd_Get_Templete_Num();                                       //读出特征模板个数命令
        array_ACK(14);                                                            //接收返回值,并且判断是否确认
        if(receive_ACK[9]==0x00)
        {
          Serial.println("TempleteNum_OK");  
        }
        else
        {
           Serial.println("TempleteNum_ERROR");
        }
        Templete_Num=(((int)receive_ACK[10]*256)+(int)receive_ACK[11]);
        Serial.println(Templete_Num);
       delay(1000);
        /*---------- 存储charbuffer2缓存到模板n -----------*/
        FP_Reg_Store[5]=(unsigned char)(Templete_Num/256);
        FP_Reg_Store[6]=(unsigned char)(Templete_Num);
        ACK_Sum=(int)FP_Reg_Store[0]+(int)FP_Reg_Store[1]+(int)FP_Reg_Store[2]+(int)FP_Reg_Store[3]+(int)FP_Reg_Store[4]+(int)FP_Reg_Store[5]+(int)FP_Reg_Store[6];
        FP_Reg_Store[7]=(unsigned char)(ACK_Sum/256);
        FP_Reg_Store[8]=(unsigned char)ACK_Sum;
        FINGERPRINT_Cmd_Store();                                                  //存储charbuffer2缓存到模板n
        array_ACK(12);                                                            //接收返回值,并且判断是否确认
        if(receive_ACK[9]==0x00)
        {
          Serial.println("Store_OK");  
        }
        else
        {
           Serial.println("Store_ERROR");
        }
       delay(1000);   
}  
void Search_One_Fingerprint(void)
{
       Serial.println("Press your finger");
         /*---------- 循环录指纹图像到imagebuff,直到应答确认 -----------*/
       do{
            FINGERPRINT_Cmd_Get_Img();                                            //发送录指纹图像命令
            array_ACK(12);                                                        //接收返回值,并且判断是否确认
            delay(100);
          }
        while(receive_ACK[9]!=0x00);                                              //如果确认,将输出GenImg_OK
        Serial.println("GenImg_OK"); 
        delay(1000);
         /*---------- 图像生成特征,并且保存到charbuffer1 -----------*/
        FINGERPRINT_Cmd_Img_To_Buffer1();                                         //发送图像生成特征,并且保存到charbuffer1命令
        array_ACK(12);                                                            //接收返回值,并且判断是否确认
        if(receive_ACK[9]==0x00)
        {
          Serial.println("Img1Tz_OK");  
        }
        else
        {
           Serial.println("Img1Tz_ERROR");
        }
       delay(1000);
        /*---------- 到模板中找指纹模板的ID -----------*/
        FINGERPRINT_Cmd_Search_Finger_Admin();                                    //搜索全部Page
        array_ACK(16);                                                            //接收返回值,并且判断是否确认
        if(receive_ACK[9]==0x00)
        {
          Serial.println("Search_Finger_OK");
          switch(receive_ACK[11])
         {  
           case 0x00:
           Serial.println("one");
           break;
           case 0x01:
           Serial.println("two");
           break;
           case 0x02:
           Serial.println("three");
           break;
           case 0x03:
           Serial.println("four");
           break;
           case 0x04:
           Serial.println("five");
           break;
           case 0x05:
           Serial.println("six");
           break;
           default:
           Serial.println("NO define");
           break;
         }
        }
        else
        {
           Serial.println("Search_Finger_ERROR");
           //Serial.println(receive_ACK[9]+0x00);
        }
       delay(1000);
}
 void Empty_Finger(void)
{
        FINGERPRINT_Cmd_Delete_All_Model();                                         //删除所有指纹模板
        array_ACK(12);
        if(receive_ACK[9]==0x00)
        {
           Serial.println("Empty_OK");
        }
        else
        {
           Serial.println("Empty_ERROR");
        }
        delay(1000);
}

Resource

User manual