一.指纹概念

1.指纹的由来

指纹是人类手指末端指腹上由凹凸的皮肤所形成的纹路,在胎儿第三四个月便开始产生,到六个月左右就形成了。当婴儿长大成人,指纹也只不过放大增粗,纹样终生不会发生改变。指纹能使手在接触物件时增加摩擦力,从而更容易发力及抓紧物件,它是人类进化过程中自然形成的。
伸出手,仔细观察,可以发现小小的指纹也分三种类型:有同心圆或螺旋纹线,看上去像水中漩涡的,叫斗形纹(whorl);有的纹线是一边开口的,即像簸箕似的,叫箕形纹(loop);有的纹形像弓一样,叫弓形纹(arch)。除总体形状不同之外,各人指纹纹形的多少、长短也不同。
在这里插入图片描述

2.指纹的唯一性

由于每个人的遗传基因均不同,故指纹也不同。然而,指纹的形成虽然主要受到遗传影响,但是也有环境因素(5%),当胎儿在母体内发育三至四个月时,指纹就已经形成,儿童在成长期间指纹会略有改变,直到青春期14岁左右时才会定型。在皮肤发育过程中,虽表皮、真皮,以及基质层都在共同成长,但柔软的皮下组织长得比相对坚硬的表皮快。 有人说骨髓移植后指纹会改变,那是不对的。除非是植皮或者深达基底层的损伤,否则指纹是不会变的。
并且它们的复杂度足以提供用于鉴别的足够特征。指纹除了具有唯一性外,还具有遗传性和不变性。尚未发现有不同的人拥有相同的指纹,所以每个人的指纹也是不一样的。由于指纹是每个人独有的标记,近几百年来,罪犯在犯案现场留下的指纹,均成为警方追捕疑犯的重要线索。现今鉴别指纹方法已经电脑化,使鉴别程序更快更准。

二、指纹检测

1.获取方式

光学识别技术
借助光学技术采集指纹是历史最久远、使用最广泛的技术。将手指放在光学镜片上,手指在内置光源照射下,用棱镜将其投射在电荷耦合器件(CCD) 上,进而形成脊线(指纹图像中具有一定宽度和走向的纹线)呈黑色、谷线(纹线之间的凹陷部分)呈白色的数字化的、可被指纹设备算法处理的多灰度指纹图像。
温差感应式识别技术
它的优点是可在0.1s内获取指纹图像,而且传感器体积和面积最小,即通常所说的滑动式指纹识别仪就是采用该技术。缺点是:受制于温度局限,时间一长,手指和芯片就处于相同的温度了。
半导体硅感技术(电容式技术)
半导体电容传感器根据指纹的嵴和峪与半导体电容感应颗粒形成的电容值大小不同,来判断什么位置是嵴什么位置是峪。其工作过程是通过对每个像素点上的电容感应颗粒预先充电到某一参考电压。当手指接触到半导体电容指纹表现上时,因为嵴是凸起、峪是凹下,根据电容值与距离的关系,会在嵴和峪的地方形成不同的电容值。然后利用放电电流进行放电。因为嵴和峪对应的电容值不同,所以其放电的速度也不同。嵴下的像素(电容量高)放电较慢,而处于峪下的像素(电容量低)放电较快。根据放电率的不同,可以探测到嵴和峪的位置,从而形成指纹图像数据。
超声波技术
超声波技术所使用的超声波频率为1×104Hz-1×109Hz,能量被控制在对人体无损的程度(与医学诊断的强度相同)。超声波技术产品能够达到最好的精度,它对手指和平面的清洁程度要求较低,但其采集时间会明显地长于前述两类产品,而且价格昂贵,也并不能做到活体指纹识别,故使用稀少。

2.指纹识别

指纹识别技术作为一个新的IT技术领域,自身具有许多新的概念。了解指纹识别技术的概念有助于准确的理解指纹识别技术。
识别系统
指纹识别系统经过人工识别到机器识别的发展之后,进入自动识别阶段,称为自动指纹识别系统(AFIS)。一个典型的自动指纹识别系统,包括与人交互的前端子系统――自动指纹采集设备、完成指纹图像处理和特征值提取的后台子系统,以及用于指纹库存储的数据库子系统。当后台子系统用于指纹注册过程时,可以称为指纹注册子系统。当它用于指纹辨识过程时,称为指纹辨识子系统。
注册匹配
指纹注册又叫指纹登记。这是从指纹图像中提取指纹特征值,形成指纹特征值模板,并与人的身份信息结合起来,存储在指纹识别系统中的过程。它相当于为指纹报户口。所以指纹注册的时候,需要保证指纹与身份信息之间的正确对应。尤其对于政府、社团、公司等单位进行指纹注册时,防止冒名顶替,避免指纹与身份信息关联错误,这是非常重要的。因此在这类指纹应用中,指纹登记的过程,需要现场督导人员参与。甚至把督导人的指纹采集到系统中,作为注册者指纹特征值模板的组成部分,以示职责之重要,并为后续责任审计提供依据。
识别验证
识别与验证并不是指纹识别算法领域的问题,而是指纹识别系统的问题。指纹识别是指在1:N模式下匹配指纹特征值。它是从多个指纹模板中识别出一个特定指纹的过程。其结果是,“有”或者“没有”。有时会给出“是谁”的信息。
指纹验证是指在1:1模式下匹配指纹特征值。它是拿待比对的指纹特征模板与事先存在的另一个指纹特征模板进行一次匹配的过程。其结果是“是不是”。在一个系统中既可以采用1:1模式也可以采用1:N模式,这是取决于应用系统的特点和要求。有时候还可以业务模式的需要,把1:N模式转化为1:1模式以提高系统安全性和比对速度。

优点:

1.指纹是人体不一样的的特征,并且它们的复杂度足以提供用于鉴别的足够特征;
2.如果要增加可靠性,只需登记更多的指纹、鉴别更多的手指,最多可以多达十个,而每一个指纹都是不一样的;
3.扫描指纹的速度很快,使用非常方便;
4.读取指纹时,用户必需将手指与指纹采集头相互接触,与指纹采集头直接;
5.接触是读取人体生物特征最可靠的方法;
6.指纹采集头可以更加小型化,并且价格会更加的低廉;

缺点:

1.某些人或某些群体的指纹特征少,难成像;
2.过去因为在犯罪记录中使用指纹,使得某些人害怕“将指纹记录在案”。
3.实际上指纹鉴别技术都可以不存储任何含有指纹图像的数据,而只是存储从指纹中得到的加密的指纹特征数据;
4.每一次使用指纹时都会在指纹采集头上留下用户的指纹印痕,而这些指纹痕迹存在被用来复制指纹的可能性。

三、光学指纹模块

1.ATK-AS608 光学指纹模块

ATK-AS608 指纹识别模块是 ALIENTEK 推出的一款高性能的光学指纹识别模块。ATK-AS608 模块采用了国内著名指纹识别芯片公司杭州晟元芯片技术有限公司(Synochip)的 AS608 指纹识别芯片。芯片内置 DSP 运算单元,集成了指纹识别算法,能高效快速采集图像并识别指纹特征。模块配备了串口、USB 通讯接口,用户无需研究复杂的图像处理及指纹识别算法,只需通过简单的串口、USB 按照通讯协议便可控制模块。本模块可应用于各种考勤机、保险箱柜、指纹门禁系统、指纹锁等场合。
在这里插入图片描述

2.技术指标

在这里插入图片描述

3.硬件接口

模块接口采用 8 芯 1.25 mm 间距单排插座,PCB 如图 2.1.1 所示。模块内部内置了手指 探测电路,用户可读取状态引脚(WAK)判断有无手指按下,模块接线口如下图左侧所示。
在这里插入图片描述
接着是模块引脚描述。
在这里插入图片描述
还有模块的实物图和标配的防呆头排线,7脚8脚的两根线有的商家会预留,有的商家给的排线上抽掉了这两根线,大概模块主要还是以串口数据收发为主。
在这里插入图片描述

4.系统资源
缓冲区与指纹库

系统内设有一个 72K 字节的图像缓冲区与二个 512bytes 大小的特征文件缓冲区,名字 分别称为:ImageBuffer,CharBuffer1 和 CharBuffer2。用户可以通过指令读写任意一个缓冲区。 CharBuffer1 或 CharBuffer2 既可以用于存放普通特征文件也可以用于存放模板特征文件。通过 UART 口上传或下载图像时为了加快速度,只用到像素字节的高 4 位,即将两个像素合 成一个字节传送。通过 USB 口则是整 8 位像素。 指纹库容量根据挂接的 FLASH 容量不同而改变,系统会自动判别。指纹模板按照序号 存放,序号定义为:0—(N-1)( N 为指纹库容量)。用户只能根据序号访问指纹库内容。

用户记事本

系统在 FLASH 中开辟了一个 512 字节的存储区域作为用户记事本,该记事本逻辑上被 分成 16 页,每页 32 字节。上位机可以通过 PS_WriteNotepad 指令和 PS_ReadNotepad 指令 访问任意一页。注意写记事本某一页的时候,该页 32 字节的内容被整体写入,原来的内容 被覆盖。

随机数产生器

系统内部集成了硬件 32 位随机数生成器(不需要随机数种子),用户可以通过指令让模 块产生一个随机数并上传给上位机。

5.软件开发指南
模块地址(大小:4bytes,属性:读写)

模块的默认地址为0xFFFFFFFF,可通过指令修改,数据包的地址域必须与该地址相配, 命令包/数据包才被系统接收。注:与上位机通讯必须是默认地址 0xFFFFFFFF!

模块口令(大小:4bytes,属性:写)

系统默认口令为 0,可通过指令修改。若默认口令未被修改,则系统不要求验证口令, 上位机和 MCU 与芯片通讯;若口令被修改,则上位机与芯片通讯的第一个指令必须是验证 口令,只有口令验证通过后,芯片才接收其它指令。注:不建议修改口令!

数据包大小设置(大小:1bytes,属性:读写)

发送数据包和接收数据包的长度根据该值设定。

波特率系数 N 设置(大小:1bytes,属性:读写)

USART 波特率=N×9600,N=1~12。

安全等级 level 设置(大小:1bytes,属性:读写)

系统根据安全等级设定比对阀值,level=1~5。安全等级为 1 时认假率最高,拒认率最低。 安全等级为 5 时认假率最低,拒认率最高。
注:以上设置均可通过指令修改,详细指令配置请参考 ATK-AS608 指纹识别模块资料文件 夹中的 AS60x 指纹识别 SOC 通讯手册 v1.0。
通讯协议、模块上位机测试等资料较繁杂就不写上了,有需要的留意末尾的资源下载分享

四、指纹管理系统(程序)

1.实验说明

实现一套指纹管理系统,对用户指纹的添加录入、对模块指纹库中的指纹进行擦除、对用户指纹
进行特征验证,使用到5个功能按键和OLED显示屏来进行系统管理。

2.实验器材
  • Arduino Mega2560 *1
  • AS608光学指纹模块 *1
  • 0.96寸 12864 OLED显示屏(IIC) *1
  • 轻触按键 *5
  • 面包板 *1
  • 杜邦线若干

不用多说还有usb线和指纹模块的通讯排线了,板子博主用的2560,用uno也可。

3.器件接线

直接上图,面包板的按键一端共地,另一端接入数字引脚2、3、4、5、6;OLED模块5V供电,另外就是SDA接2560的SDA,SCL接SCL,不是问题
在这里插入图片描述
指纹模块接线单独发一张,串口接2560的TX1,RX1,收对发,发对收
在这里插入图片描述
指纹模块需要3.3V供电,接错了可能烧坏模块,这里要注意下,按键为了省接线用了面包板,比较推荐使用面包板,1是好分辨按键序号,2还是减少接线烦恼跟部分人的强迫症哈哈哈。

4.实验源码
demo1-按键管理

在这之前你需要用IDE的库管理器安装u8g2 和Adafruit Fingerprint 两个库,另外还有OLED显示中文需要的字库文件,这个按个人需求自己搞了。

#include "font.h"
#include <U8g2lib.h>
#include <Adafruit_Fingerprint.h>

#define x_coordinate   40

#define KEY1 2
#define KEY2 3
#define KEY3 4
#define KEY4 5
#define KEY5 6

#define mySerial Serial1
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

U8G2_SH1106_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 2, /* data=*/ 11, /* reset=*/ U8X8_PIN_NONE);

u8 key_num=0;

void key_init()
{
  、、、
}

u8 key_scan(u8 mode)
{
  、、、
}

void Add_FR()
{
  u8 i,ensure,processnum=0;
  u8 ID_NUM=0;
  char str2[10];
  while(1)
  {
    switch (processnum)
    {
      case 0:
        i++;
        u8g2.clearBuffer();               		// 清屏
        u8g2.drawXBMP(32,24,64,16,State5);  	/* 字串 请按手指   64x16  */
        u8g2.sendBuffer();
        ensure=finger.getImage();
        if(ensure==FINGERPRINT_OK) 
        {
          ensure=finger.image2Tz(1);			//生成特征
          if(ensure==FINGERPRINT_OK)
          {
            u8g2.clearBuffer();         		// 清屏
            u8g2.drawXBMP(32,24,64,16,State6);  /* 字串 指纹正常   64x16  */ 
            u8g2.sendBuffer();
            i=0;
            processnum=1;						//跳到第二步            
          }else {};       
        }else {};           
        break;
      
      case 1:
        i++;
        u8g2.clearBuffer();         			// 清屏
        u8g2.drawXBMP(32,24,64,16,State7); 		/* 字串 再按一次   64x16  */
        u8g2.sendBuffer();
        ensure=finger.getImage();
        if(ensure==FINGERPRINT_OK) 
        {
          ensure=finger.image2Tz(2);			//生成特征
          if(ensure==FINGERPRINT_OK)
          {
            u8g2.clearBuffer();         		// 清屏
            u8g2.drawXBMP(32,24,64,16,State6);	/* 字串 指纹正常   64x16  */
            u8g2.sendBuffer();
            i=0;
            processnum=2;						//跳到第三步
          }else {}; 
        }else {};   
        break;

      case 2:
        u8g2.clearBuffer();         			// 清屏
        u8g2.drawXBMP(32,24,64,16,State8);		/* 字串 创建模板   64x16  */   
        u8g2.sendBuffer();
        ensure=finger.createModel();
        if(ensure==FINGERPRINT_OK) 
        {
          u8g2.clearBuffer();         			// 清屏
          u8g2.drawXBMP(16,24,96,16,State9);  	/* 字串 模板创建成功   96x16  */   
          u8g2.sendBuffer();
          processnum=3;							//跳到第四步
        }
        else
        {         
          u8g2.clearBuffer();         			// 清屏
          u8g2.drawXBMP(16,24,96,16,State10);  	//显示字模汉字   
          u8g2.sendBuffer();
          i=0;
          processnum=0;							//跳回第一步    
        }
        delay(500);
        break;        
      case 3: 
        u8g2.clearBuffer();         			// 清屏
        u8g2.drawXBMP(1,0,128,48,State11);  	//显示字模汉字 
        u8g2.setFont(u8g2_font_gb16st_t_2); 	// 选择字体
        u8g2.drawStr(40,62,"ID=00");  
        u8g2.sendBuffer();
        
        while(key_num!=3)
        {
          key_num=key_scan(0);
          if(key_num==2)
          {
            key_num=0;
            if(ID_NUM>0)
              ID_NUM--;
            if(ID_NUM<10)
              sprintf(str2,"ID=0%d",ID_NUM);
            else
              sprintf(str2,"ID=%d",ID_NUM);
            u8g2.drawStr(40,62,str2);
            u8g2.sendBuffer();
          }
          if(key_num==4)
          {
            key_num=0;
            if(ID_NUM<99)
              ID_NUM++;
            if(ID_NUM<10)
              sprintf(str2,"ID=0%d",ID_NUM);
            else
              sprintf(str2,"ID=%d",ID_NUM);
            u8g2.drawStr(40,62,str2);
            u8g2.sendBuffer();
          }
        }
        key_num=0;
        ensure=finger.storeModel(ID_NUM);		//储存模板
        if(ensure==0x00) 
        {   
          u8g2.clearBuffer();         			// 清屏
          u8g2.drawXBMP(16,24,96,16,State12);  	//显示字模汉字   
          u8g2.sendBuffer();
          delay(1500);
          return ;
        }else {processnum=0;}         
        break;        
    }
    delay(400);
    if(i==10)									//超过5次没有按手指则退出
    {
      break;  
    }
  } 
}

void Press_FR()
{
  、、、
}

void Del_FR()
{
  、、、
}


void setup() {
  // put your setup code here, to run once:
  key_init();
  u8g2.begin();
  finger.begin(57600);
  u8g2.clearBuffer();         			// 清屏
  u8g2.setFont(u8g2_font_gb16st_t_2); 	// 选择字体
  u8g2.drawXBMP(1,0,128,16,State1);  	//显示字模汉字   /* 指纹模块测试程序  128x16  */
  u8g2.drawXBMP(40,16,64,16,State2); 
  u8g2.drawXBMP(40,32,64,16,State3); 
  u8g2.drawXBMP(40,48,64,16,State4);
  u8g2.drawStr(22,30,"K1"); 			// write something to the internal memory
  u8g2.drawStr(22,46,"K3"); 			// write something to the internal memory
  u8g2.drawStr(22,62,"K5"); 			// write something to the internal memory

  u8g2.sendBuffer();          			// 发送显示
  
}

void loop() {

  key_num = key_scan(0);
  if(key_num == 1)
  {
    key_num = 0;
    Add_FR();
    u8g2.clearBuffer();         		// 清屏
    u8g2.setFont(u8g2_font_gb16st_t_2); // 选择字体
    u8g2.drawXBMP(1,0,128,16,State1);  	//显示字模汉字   /* 指纹模块测试程序  128x16  */
    u8g2.drawXBMP(40,16,64,16,State2); 
    u8g2.drawXBMP(40,32,64,16,State3); 
    u8g2.drawXBMP(40,48,64,16,State4);
    u8g2.drawStr(22,30,"K1"); 			// write something to the internal memory
    u8g2.drawStr(22,46,"K3"); 			// write something to the internal memory
    u8g2.drawStr(22,62,"K5"); 			// write something to the internal memory

    u8g2.sendBuffer();          		// 发送显示
  }
  if(key_num == 3)
  {
    key_num = 0;
    Del_FR();
    u8g2.clearBuffer();         		// 清屏
    u8g2.setFont(u8g2_font_gb16st_t_2); // 选择字体
    u8g2.drawXBMP(1,0,128,16,State1);  	//显示字模汉字   /* 指纹模块测试程序  128x16  */
    u8g2.drawXBMP(40,16,64,16,State2); 
    u8g2.drawXBMP(40,32,64,16,State3); 
    u8g2.drawXBMP(40,48,64,16,State4);
    u8g2.drawStr(22,30,"K1"); 			// write something to the internal memory
    u8g2.drawStr(22,46,"K3"); 			// write something to the internal memory
    u8g2.drawStr(22,62,"K5"); 			// write something to the internal memory

    u8g2.sendBuffer();          		// 发送显示
  }
  if(key_num == 5)
  {
    key_num = 0;
    Press_FR();
    u8g2.clearBuffer();         		// 清屏
    u8g2.setFont(u8g2_font_gb16st_t_2); // 选择字体
    u8g2.drawXBMP(1,0,128,16,State1);  	//显示字模汉字   /* 指纹模块测试程序  128x16  */
    u8g2.drawXBMP(40,16,64,16,State2); 
    u8g2.drawXBMP(40,32,64,16,State3); 
    u8g2.drawXBMP(40,48,64,16,State4);
    u8g2.drawStr(22,30,"K1"); 			// write something to the internal memory
    u8g2.drawStr(22,46,"K3"); 			// write something to the internal memory
    u8g2.drawStr(22,62,"K5"); 			// write something to the internal memory

    u8g2.sendBuffer();          		// 发送显示
  }
}

源码部分过长,仅展示指纹添加部分(进行两次的指纹输入,生成特征,创建模板,再选择指纹ID号保存至模块的指纹库中),指纹验证和删除部分省略了,OLED显示语句占了将近一半,完整源码跟字库文件可留意末尾资源下载分享

demo2-串口指令控制

将OLED的操作提示换成串口提示,当然只能是英文输出啦,而且简略了选择ID保存等操作,可以实现指纹添加和验证操作。

#include <Adafruit_Fingerprint.h>

//需要添加Adafruit_Fingerprint 库

#define mySerial Serial1
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

char user_order = ' ';        //存储用户输入的串口指令
u8 ID_NUM = 0;                //存储添加的指纹ID

void Add_FR()
{ 
  u8 i = 0,ensure,processnum=0;
  Serial.println("---------------------------");
  while(1)
  {
    switch (processnum)
    {
      case 0:
        i++;
        //请按手指
        Serial.println("Please Press...");
        ensure=finger.getImage();
        if(ensure==FINGERPRINT_OK) 
        {
          ensure=finger.image2Tz(1);                      //生成特征
          if(ensure==FINGERPRINT_OK)
          {
            //指纹正常
            Serial.println("Press OK"); 
            i=0;
            processnum=1;                                 //跳到第二步            
          }else {};       
        }else {};           
        break;
      
      case 1:
        i++;
        //再按一次
        Serial.println("Please Press Again...");
        ensure=finger.getImage();
        if(ensure==FINGERPRINT_OK) 
        {
          ensure=finger.image2Tz(2);                      //生成特征
          if(ensure==FINGERPRINT_OK)
          {
            //指纹正常
            Serial.println("Press Again OK");
            i=0;
            processnum=2;                                 //跳到第三步
          }else {}; 
        }else {};   
        break;

      case 2:
        // 创建模板
        Serial.print("Finger Create...");
        ensure=finger.createModel();
        if(ensure==FINGERPRINT_OK) 
        {
          Serial.println("Success");
          processnum=3;                                   //跳到第四步
        }
        else
        {         
          //创建模板失败
          Serial.println("Fail");
          i=0;
          processnum=0;                                   //跳回第一步    
        }
        delay(500);
        break;        
      case 3: 
        //写入指纹ID
        ID_NUM++;
        ensure=finger.storeModel(ID_NUM);                 //储存模板
        if(ensure==0x00) 
        {   
          //录入指纹成功 ID打印
          Serial.print("Add Fingerprint Success --- ");
          if((ID_NUM>0) && (ID_NUM<10))
            Serial.print("ID = 0");
          if(ID_NUM >= 10)
            Serial.print("ID = ");
          Serial.println(ID_NUM);
          Serial.println(" ");
          delay(1500);
          return ;
        }else {processnum=0;}         
        break;        
    }
    delay(400);
    if(i==10)                                 //超过5次没有按手指则退出
    {
      Serial.println("Timeout !!!");
      break;  
    }
  }
}

void Press_FR()
{
  u8 ensure,i,j = 0;
  //请按手指
  Serial.println("---------------------------");
  Serial.print("Please Press Fingerprint...");
  for(i=0;i<15;i++)
  {
    ensure=finger.getImage();
    if(ensure==0x00)                          //获取图像成功 
    {   
      ensure=finger.image2Tz();
      if(ensure==0x00)                        //生成特征成功
      {     
        ensure=finger.fingerFastSearch();
        if(ensure==0x00)                      //搜索成功
        {       
          //指纹验证成功
          Serial.println(" ");   
          Serial.println("Fingerprint verification successful !!!");
          if((0 < finger.fingerID)&&(finger.fingerID < 10))
            Serial.print("Welcome ID : 0");
          if(finger.fingerID >= 10)
            Serial.print("Welcome ID : ");
          Serial.println(finger.fingerID);     
          Serial.println(" ");
          j = 0;
          delay(2000);
          break;
        }
        else 
        {
          //未搜索到指纹 
          Serial.println(" ");
          Serial.println("!!! Fingerprint not found !!!");
          Serial.println(" ");
          delay(2000);
          break;
        }                 
      }
      else
        {
          
        }
    }
    j++;
    delay(200);

    if(j >= 15)
    {
      //等待超时
      Serial.println("Timeout !!!");
      Serial.println(" ");
    }  
  }  
}

void setup()
{
  finger.begin(57600);                        //设置指纹模块串口波特率57600
  Serial.begin(115200);                       //设置串口波特率115200

  while(finger.emptyDatabase());              //清空AS608指纹库

  Serial.println("AS608 is Ready............");
  Serial.println(" ");
  Serial.println("Input 'a' to Add Fingerprint    |   Input 'b' to Press Fingerprint");
}

void loop()
{
  //串口指令读取
  if(Serial.available())
    user_order = Serial.read();

  //串口收到字符a,执行指纹添加操作
  if(user_order == 'a')
  {
    Add_FR();                         //调用Add_FR函数
    user_order = ' ';                 //清空user_order指令
    Serial.println("Input 'a' to Add Fingerprint    |   Input 'b' to Press Fingerprint");
  }

  //串口收到指纹b,执行指纹验证操作
  if(user_order == 'b')
  {
    Press_FR();                       //调用Press_FR函数
    user_order = ' ';                 //清空user_order指令
    Serial.println("Input 'a' to Add Fingerprint    |   Input 'b' to Press Fingerprint");
  }
}

串口操作的源码是完整的,只需要Adafruit Fingerprint的库

5.实验效果
demo1

正确接线后,烧写程序,稍作等待,可以看到OLED屏幕显示指纹模块测试程序,并指引了K1按键添加指纹,K3按键删除指纹,K5按键验证指纹。
在这里插入图片描述
指纹添加步骤稍微多,直接把显示步骤做成九宫格,差点出来了密集恐惧症,,,
在这里插入图片描述
指纹添加步骤具体如下:

  1. 按一次指纹
  2. 指纹读取成功
  3. 再按一次指纹
  4. 指纹二次读取成功
  5. 创建指纹模板
  6. 模板创建成功
  7. 选择指纹ID号(按K4 ID号+1,按K2 ID号-1)
  8. 确定要保存的ID号,按K3保存
  9. 指纹成功录入模块指纹库

按K3进行指纹删除,如图所示,按K2K4进行要删除的ID号选择,最后按K3确定删除,或者狠一点直接按K5清除整个指纹库。
在这里插入图片描述
指纹删除步骤具体如下:

  • A1.选择需要删除的ID号(K2 ID号-1,K4 ID号+1)
  • A2.选择了要删除的ID号01,按下K3确认删除
  • A3.ID号01删除成功
  • B.在A1的步骤时按下K5,清除整个指纹库

按K5进行指纹验证,在提示按下手指时按住指纹模块,等待验证成功并给出指纹ID号,Score是按下的指纹跟指纹库中对应的2号指纹的对比度,当然按下的指纹如果在指纹库中找不到相同特征的指纹ID,将提示“为搜索到指纹”
在这里插入图片描述

demo2

上传程序后打开IDE的串口监视器,能看到程序初始化后的操作提示,输入字符'a' 进行指纹添加,输入字符 'b' 进行指纹验证(硬件连接只需要接好指纹模块的线,这里不展示)
在这里插入图片描述
串口输入 字符'a' ,看到提示“Please Press”要求按指纹
在这里插入图片描述
如果在限定时间内没手指按下的操作,程序将退出到初始状态(继续检测串口指令字符'a''b'
在这里插入图片描述
在指纹添加操作时,从指纹模块扫描口按下手指,根据串口提示进行两次指纹按压操作,直到提示指纹添加成功,并获得指纹ID。
在这里插入图片描述
随后录入的指纹ID号将以叠加的方式的方式分配(像02、03、04…)。
指纹添加成功后将返回继续等待串口指令;这时候在监视器发送框输入b,进行指纹验证操作。
在这里插入图片描述
同样一定时间内模块没有指纹输入,将检测超时返回初始状态等待串口指令
在这里插入图片描述
当检测到输入的指纹特征在模块指纹库中没有记录时,会提示指纹没有找到
在这里插入图片描述
当检测到输入的指纹特征能在指纹库有对比的模板时,显示其对应ID号,随后继续回到主界面
在这里插入图片描述

五、结语

指纹检测模块在生活中越来越常见,甚至还出现了活体指纹检测的设备,即活人的指纹按下才有效,盗取的指纹或者kan下来的手指去检测都是无效的。上面提供的两个demo在做实验的时候都比较实用,各有所长,条件有限的不一定要OLED的


来了来了,你们要的例程资源,包含模块用户手册,数据手册,Arduino例程源码(demo1的),AS608模块的上位机和上位机操作视频,够丰富吧,有需要32例程跟51例程的评论区留言,有空就补上资源链接
Arduino指纹案例跳转链接 — 点我点我点我


哦,对了,指纹在扫描录入或者验证时都是对比的指纹特征,那什么是指纹的特征呢,你可能还不清楚,上一张图给瞅瞅,就能了解个大概了,剩下的找度娘去
在这里插入图片描述

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐