自备组件:
舵机(根据自己的需要选择扭力,一般945舵机扭力够大)
fpm383c指纹组件
arduion uno板
杜邦公对公线>7条
安装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翻译了代码和注释。