基于arduion uno 和FPM383C指纹传感器的指纹开锁(0基础)

自备组件:

舵机(根据自己的需要选择扭力,一般945舵机扭力够大)

fpm383c指纹组件

arduion uno板

杜邦公对公线>7条

安装端口驱动https://www.wch.cn/downloads/file/65.html?time=2023-11-26%2017:57:00&code=oUySNf0z1xcLSTNYjZIiNc917AdOG39h2d5gXniF

安装arduion ide软件 (打开软件用ctrl+,可以打开首选项修改语言为中文)

并且安装Adafruit_Fingerprint库

接线:电源线按自己需求连接,如果监视器显示匹配成功,但是舵机不转动,可能是没有接好舵机电源。指纹模块tx连接2号数字引脚,rx连接3号数字引脚,舵机信号线连接4号数字引脚

用arduion ied连接板(自己选择自己端口和板)先上传注册代码按流程注册后,再上传主代码就可以控制舵机了

可以在串口监测器看到状态

本文章主要修改了一下Adafruit_Fingerprint库的示例Fingerprint作为主代码,并且对其进行翻译。

主要目的是直接可用。并没有做更好的优化。

主代码:

/*************************************************** 这是一个专为光学指纹传感器设计的示例程序

特别适用于与Adafruit BMP085模块配合使用 ----> http://www.adafruit.com/products/751

这些显示器通过TTL串行通信,需要2个引脚进行接口连接

Adafruit投入时间和资源提供此开源代码,请通过购买Adafruit的产品来支持我们以及开源硬件!

由Limor Fried/Ladyada为Adafruit Industries编写。 采用BSD许可协议,以上所有文本在任何重新发布的版本中都必须予以包含
 ****************************************************/ 
#include <Adafruit_Fingerprint.h>
#include <Servo.h>

#if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__)

// 设置串口以使用软件串口
void(*resetFunc) (void) = 0;
SoftwareSerial mySerial(2, 3);//设置输入引脚
#else

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


//舵机驱动函数
void moveServoAndReset(Servo& servoInstance, uint8_t initialAngle, uint8_t finalAngle, unsigned long delayTime) {
  servoInstance.attach(4); // 将控制线连接到数字引脚4
  servoInstance.write(initialAngle);
  delay(delayTime);          // 等待转动到指定角度

  servoInstance.write(finalAngle);
  delay(delayTime);          // 再次等待转动到指定角度
  servoInstance.detach();   // 断开舵机与引脚的连接,清除寄存器残留值
 
}



Servo myservo;//声明舵机控制


void setup()
{
  Serial.begin(9600);
  




  while (!Serial);  // 等待Yun/Leo/Micro/Zero/...初始化完成
  delay(100);
  Serial.println("\n\nAdafruit指纹识别测试");
  // 设置传感器串口的数据速率
  finger.begin(57600);
  delay(5);
  if (finger.verifyPassword()) {
    Serial.println("已找到指纹传感器!");
  } else {
    Serial.println("未找到指纹传感器 :(");
    delay(3000);                     
    resetFunc();  // 调用复位函数
    while (1) { delay(1); }
  }

  Serial.println(F("读取传感器参数"));
  finger.getParameters();
  Serial.print(F("状态: 0x")); Serial.println(finger.status_reg, HEX);
  Serial.print(F("系统ID: 0x")); Serial.println(finger.system_id, HEX);
  Serial.print(F("容量: ")); Serial.println(finger.capacity);
  Serial.print(F("安全级别: ")); Serial.println(finger.security_level);
  Serial.print(F("设备地址: ")); Serial.println(finger.device_addr, HEX);
  Serial.print(F("数据包长度: ")); Serial.println(finger.packet_len);
  Serial.print(F("波特率: ")); Serial.println(finger.baud_rate);

  finger.getTemplateCount();

  if (finger.templateCount == 0) {
    Serial.print("传感器中不含任何指纹数据。请运行'enroll'示例进行录入。");
  }
  else {
    Serial.println("等待有效指纹...");
      Serial.print("传感器包含 "); Serial.print(finger.templateCount); Serial.println(" 个模板");
  }
}

void loop()                     // 不断循环执行
{
  getFingerprintID();
  delay(15);            // 没有必要全速运行
}

uint8_t getFingerprintID() {
  uint8_t p = finger.getImage();
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("已采集图像");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.println("未检测到手指");
      delay(1000);
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("通信错误");
      return p;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("成像失败");
      return p;
    default:
      Serial.println("未知错误");
      return p;
  }

  // 成功获取图像!

  p = finger.image2Tz();
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("图像转换成功");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("图像质量差");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("通信错误");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("找不到指纹特征");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("无效的指纹图像");
      return p;
    default:
      Serial.println("未知错误");
      return p;
  }

  // 图像成功转换!
  p = finger.fingerSearch();
  if (p == FINGERPRINT_OK) {
    Serial.println("找到匹配的指纹!!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("通信错误");
    return p;
  } else if (p == FINGERPRINT_NOTFOUND) {
    Serial.println("未找到匹配的指纹");
    return p;
  } else {
    Serial.println("未知错误");
    return p;
  }
  // 找到匹配项!
  Serial.print("找到ID #"); Serial.print(finger.fingerID);
  Serial.print(",置信度为 "); Serial.println(finger.confidence);
   
  moveServoAndReset(myservo, 0, 180, 1800);//控制舵机转到角度,初始角度,等待时间
  return finger.fingerID;
}

// 返回-1表示失败,否则返回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;

  // 找到匹配项!
  Serial.print("找到ID #"); Serial.print(finger.fingerID);
  Serial.print(",置信度为 "); Serial.println(finger.confidence);
  return finger.fingerID;
}

注册指纹方法:使用Adafruit_Fingerprint库示例enroll

或者直接用这段代码(在串口监测器输入id编号)

/***************************************************
  这是一个用于光学指纹传感器的示例代码

  特别设计用于与Adafruit BMP085模块配合使用
  ----> http://www.adafruit.com/products/751

  这些显示器通过TTL串行通信,需要2个引脚进行接口连接
  Adafruit投入时间和资源提供此开源代码,请支持Adafruit和开源硬件,
  通过购买Adafruit的产品来表达您的支持!

  由Limor Fried/Ladyada为Adafruit Industries编写。
  使用BSD许可协议,以上所有文本必须包含在任何再发布的代码中
 ****************************************************/

#include <Adafruit_Fingerprint.h>

#if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__)

SoftwareSerial mySerial(2, 3);

#else

#define mySerial Serial1

#endif

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
uint8_t id; // 存储指纹ID变量

void setup()
{
  Serial.begin(9600);
  while (!Serial);  // 等待Yun/Leo/Micro/Zero/...初始化完成
  delay(100);
  Serial.println("\n\nAdafruit 指纹传感器注册程序");

  // 设置传感器串口的数据速率
  finger.begin(57600);

  if (finger.verifyPassword()) {
    Serial.println("已连接到指纹传感器");
  } else {
    Serial.println("未连接到传感器");
    while (1) { delay(1); }
  }

  Serial.println(F("读取传感器参数"));
  finger.getParameters();
  Serial.print(F("状态: 0x")); Serial.println(finger.status_reg, HEX);
  Serial.print(F("系统ID: 0x")); Serial.println(finger.system_id, HEX);
  Serial.print(F("容量: ")); Serial.println(finger.capacity);
  Serial.print(F("安全级别: ")); Serial.println(finger.security_level);
  Serial.print(F("设备地址: ")); Serial.println(finger.device_addr, HEX);
  Serial.print(F("数据包长度: ")); Serial.println(finger.packet_len);
  Serial.print(F("波特率: ")); Serial.println(finger.baud_rate);
}

uint8_t readnumber(void) {
  uint8_t num = 0;

  // 循环直至获取到一个非零数字
  while (num == 0) {
    while (! Serial.available());
    num = Serial.parseInt();
  }
  return num;
}

void loop()                     // 不断循环执行
{
  Serial.println("准备登记指纹");
  Serial.println("请选择保存编号");
  id = readnumber();
  if (id == 0) { // ID #0不允许使用,尝试重新选择
     return;
  }
  Serial.print("正在登记ID #");
  Serial.println(id);

  // 循环直到成功登记指纹
  while (!  getFingerprintEnroll() );
}

uint8_t getFingerprintEnroll() {

  int p = -1;
  Serial.print("等待有效指纹进行登记为ID #"); Serial.println(id);
  // 循环直至获取到有效的指纹图像
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println("已采集图像");
        break;
      case FINGERPRINT_NOFINGER:
        Serial.println(".");
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        Serial.println("通信错误");
        break;
      case FINGERPRINT_IMAGEFAIL:
        Serial.println("成像错误");
        break;
      default:
        Serial.println("未知错误");
        break;
    }
  }

  // 成功采集图像!

  p = finger.image2Tz(1);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("图像已转换");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("图像太模糊");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("通信错误");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("未能找到指纹特征");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("无效的指纹图像");
      return p;
    default:
      Serial.println("未知错误");
      return p;
  }

  Serial.println("请移除手指");
  delay(2000);
  p = 0;
  // 等待手指移除
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  Serial.print("ID "); Serial.println(id);
  p = -1;
  Serial.println("请再次放置同一手指");
  // 循环直至获取到有效的指纹图像
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println("已采集图像");
        break;
      case FINGERPRINT_NOFINGER:
        Serial.print(".");
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        Serial.println("通信错误");
        break;
      case FINGERPRINT_IMAGEFAIL:
        Serial.println("成像错误");
        break;
      default:
        Serial.println("未知错误");
        break;
    }
  }

  // 成功采集图像!

  p = finger.image2Tz(2);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("图像已转换");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("图像太模糊");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("通信错误");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("未能找到指纹特征");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("无效的指纹图像");
      return p;
    default:
      Serial.println("未知错误");
      return p;
  }

  // 图像成功转换!

  Serial.print("为ID #"); Serial.println(id);
  Serial.print("创建模型");
  p = finger.createModel();
  if (p == FINGERPRINT_OK) {
    Serial.println("指纹匹配成功!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("通信错误");
    return p;
  } else if (p == FINGERPRINT_ENROLLMISMATCH) {
    Serial.println("两次指纹图像不匹配");
    return p;
  } else {
    Serial.println("未知错误");
    return p;
  }

  Serial.print("ID "); Serial.println(id);
  p = finger.storeModel(id);
  if (p == FINGERPRINT_OK) {
    Serial.println("存储成功!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("通信错误");
    return p;
  } else if (p == FINGERPRINT_BADLOCATION) {
    Serial.println("无法在该位置存储");
    return p;
  } else if (p == FINGERPRINT_FLASHERR) {
    Serial.println("写入闪存时出错");
    return p;
  } else {
    Serial.println("未知错误");
    return p;
  }

  return true;
}

2024.3.14更新,解决了舵机抖动问题。用ai翻译了代码和注释。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值