Added fingerprint example

This commit is contained in:
lewis he
2020-06-15 16:34:02 +08:00
parent 2289445a2e
commit 2e85bcc6d8
3 changed files with 807 additions and 0 deletions

View File

@@ -0,0 +1,157 @@
#include <TTGO.h>
#include "fingerprint.h"
#define MODULE_TX 33
#define MODULE_RX 34
#define UART_BAUD 57600
#define VTOUCH_PIN 26
#define BUZZER_PIN 25
#define BUZZER_CHANNEL 2
#define ModuleSerial Serial1
TTGOClass *watch = nullptr;
TFT_eSPI *tft = nullptr;
Fingerprint eic(&Serial1);
SysParams_t params;
bool flag = false;
char buff[512];
void touchPadAttach(void)
{
Serial.println("TouchPad Attach");
flag = true;
}
void playSound()
{
ledcWriteTone(BUZZER_CHANNEL, 1000);
delay(200);
ledcWriteTone(BUZZER_CHANNEL, 0);
}
void setup()
{
Serial.begin(115200);
delay(500);
watch = TTGOClass::getWatch();
watch->begin();
tft = watch->eTFT;
tft->setTextFont(2);
tft->fillScreen(TFT_BLACK);
tft->setCursor(0, 0);
watch->sdcard_begin();
if (watch->sdcard_begin()) {
tft->println("SD Begin OK");
} else {
tft->println("SD Begin Failed");
}
tft->println("Begin Fingerprint module ...");
// enable module power
watch->enableLDO3();
// open blacklight
watch->openBL();
ModuleSerial.begin(UART_BAUD, SERIAL_8N1, MODULE_RX, MODULE_TX);
// buzzer init
ledcSetup(BUZZER_CHANNEL, 1000, 8);
ledcAttachPin(BUZZER_PIN, BUZZER_CHANNEL);
// module interrupt pin init
pinMode(VTOUCH_PIN, INPUT_PULLDOWN);
attachInterrupt(VTOUCH_PIN, touchPadAttach, CHANGE);
// Wait for module ack
do {
eic.readSysParams(&params);
Serial.printf("address: 0x%x --packSize : %u -- %d bps -- level:%d -- statusReg:0x%x -- code:0x%x\n",
params.address,
params.packSize,
9600 * params.bps,
params.level,
params.statusReg,
params.code
);
delay(1000);
} while (params.address != 0xFFFFFFFF);
tft->setTextColor(TFT_GREEN, TFT_BLACK);
tft->print("Address:"); tft->println(params.address, HEX);
tft->print("Pack Size:"); tft->println(params.packSize);
tft->print("Speed:"); tft->println(9600 * params.bps);
tft->print("Level:"); tft->println(params.level);
tft->print("StatusReg:"); tft->println(params.statusReg, HEX);
tft->print("Code:"); tft->println(params.code);
playSound();
playSound();
playSound();
playSound();
}
bool loop1(GR_BufID_t id)
{
// while (!flag) {
// delay(500);
// }
flag = false;
if (eic.entryFinger()) {
Serial.println("entery PASS");
delay(200);
if (eic.generateFeature(id)) {
Serial.println("generater PASS");
return true;
} else {
Serial.println("generater FAIL");
}
}
return false;
}
void loop()
{
while (!loop1(GR_CHAR_BUFFER_1));
while (!loop1(GR_CHAR_BUFFER_2));
if (eic.mergeFeature()) {
Serial.println("merge PASS");
if (eic.storeFeature(GR_CHAR_BUFFER_1, 0)) {
Serial.println("storeFeature PASS");
} else {
Serial.println("storeFeature FAIL");
}
} else {
Serial.println("merge FAIL");
}
while (1) {
if (loop1(GR_CHAR_BUFFER_1)) {
if (eic.searchFingerprint(GR_CHAR_BUFFER_1, 0, 10)) {
Serial.println("Fingerprint valid PASS");
playSound();
} else {
// Serial.println("Fingerprint valid FAIL");
}
}
}
}

View File

@@ -0,0 +1,515 @@
#include "fingerprint.h"
/*起始帧*/
#define GR_PACK_HEAD 0XEF01
/* 包标识*/
#define GR_PACK_COMMAND_FLAG 0X01
//当为2时表示后续还有包
#define GR_PACK_DATA_FALG 0X02
#define GR_PACK_ACK_FALG 0X07
#define GR_PACK_END_FALG 0X08
// 包长度 = 数据到校验和之间的长度
// 校验和 = 包标识 ~ 校验和之间的和 ,超两个字节对高位进行忽略
Fingerprint::Fingerprint(Stream *UART, uint32_t ADDRRESS)
{
_uart = UART;
_addr = ADDRRESS;
_headBuffer[0] = 0xEF;
_headBuffer[1] = 0x01;
memcpy(&_headBuffer[2], &_addr, sizeof(_addr));
};
Fingerprint::~Fingerprint(void)
{
};
/*********************
* 0 1 2 3 4 5 6 7 8 9 10 11
* ef 01 ff ff ff ff flag len_h len_l code sum_h sum_l
* *******************/
bool Fingerprint::validSum(uint8_t *resp, uint8_t len)
{
uint16_t sum = 0;
for (int i = 6; i < len - 2; i++) {
sum += resp[i];
}
// Serial.printf("sum:%x -2:%x -1:%x \n", sum, resp[len - 2], resp[len - 1]);
// Serial.printf("merge: %x \n", (resp[len - 2] << 8 | resp[len - 1]));
return sum == (resp[len - 2] << 8 | resp[len - 1]);
}
bool Fingerprint::waitForAck(uint8_t *reqs, uint8_t len)
{
uint32_t i = 0, timerStart = millis();
while (1) {
if (_uart->available()) {
reqs[i++] = _uart->read();
Serial.print(reqs[i - 1], HEX);
Serial.print(" ");
if (i >= len) {
Serial.println();
break;
}
}
if (millis() - timerStart > 1000) {
Serial.printf("time out\n");
return false;
}
}
return true;
}
int Fingerprint::waitForResp(uint8_t respSize, uint32_t timeout)
{
int i = 0;
uint32_t timerStart = millis();
uint8_t response[respSize];
while (1) {
if (_uart->available()) {
response[i++] = _uart->read();
if (i >= sizeof(response))
break;
}
if (millis() - timerStart > 1000 * timeout) {
return -1;
}
}
if (validSum(response, sizeof(response))) {
return response[9];
}
return -1;
}
void Fingerprint::__sendCom(uint8_t command, uint16_t len)
{
uint16_t sum = 0;
uint8_t commandBuffer[6];
commandBuffer[0] = GR_PACK_COMMAND_FLAG;
commandBuffer[1] = (len & 0xFF00) >> 8;
commandBuffer[2] = len & 0xFF;
commandBuffer[3] = command;
for (int i = 0; i < sizeof(commandBuffer) - 2; i++) {
sum += commandBuffer[i];
}
commandBuffer[4] = (sum & 0xFF00) >> 8;
commandBuffer[5] = sum & 0xFF;
_uart->write(_headBuffer, sizeof(_headBuffer));
_uart->write(commandBuffer, sizeof(commandBuffer));
}
/**
* @brief 录入指纹到ImageBuffer
* @note 标准应答格式 12Bytes
* @retval 0H ~ 03H
*/
bool Fingerprint::entryFinger(void)
{
int ret = GR_OK;
__sendCom(GR_GET_IMAGE, 0x03);
ret = waitForResp(12, 15);
if (ret != GR_OK) {
getErrorReason(ret);
}
return ret == GR_OK;
}
void Fingerprint::getErrorReason(int err)
{
// Serial.printf("Error :[%d]\n", err);
switch (err) {
case 0:
break;
}
}
/**
* @brief 生成特征标识
* @note 标准应答格式 12Bytes
* @param id: 01H ~ 02H
* @retval
*/
bool Fingerprint::generateFeature(GR_BufID_t id)
{
int ret = GR_OK;
uint8_t commandBuffer[7];
_uart->write(_headBuffer, 6);
commandBuffer[0] = GR_PACK_COMMAND_FLAG;
commandBuffer[1] = 0x00;
commandBuffer[2] = 0x04;
commandBuffer[3] = GR_GET_CHAR;
commandBuffer[4] = id;
commandBuffer[5] = 0x00;
commandBuffer[6] = 0x07 + id;
_uart->write(commandBuffer, sizeof(commandBuffer));
ret = waitForResp(12, 1);
if (ret != GR_OK) {
getErrorReason(ret);
}
return ret == GR_OK;
}
/**
* @brief 精确比对两枚指纹特征
* @note //! 非标准应答格式 14Bytes
* @retval 0x00 0x01 0x08
*/
bool Fingerprint::matchFingerprint(void)
{
int ret = GR_OK;
__sendCom(GR_MATCH, 0x03);
ret = waitForResp(14, 1);
if (ret != GR_OK) {
getErrorReason(ret);
}
return ret == GR_OK;
}
/**
* @brief 搜索指纹
* @note //! 非标准应答格式 16Bytes
* @retval 确认字,页码(相配指纹模板)
*/
bool Fingerprint::searchFingerprint(GR_BufID_t id, uint16_t sPage, uint16_t pNum)
{
int ret = GR_OK;
uint32_t sum = 0;
uint8_t commandBuffer[11];
_uart->write(_headBuffer, 6);
commandBuffer[0] = GR_PACK_COMMAND_FLAG;
commandBuffer[1] = 0x00;
commandBuffer[2] = 0x08;
commandBuffer[3] = GR_SEARCH;
commandBuffer[4] = id;
commandBuffer[5] = (sPage & 0xFF00) >> 8;
commandBuffer[6] = sPage & 0xFF;
commandBuffer[7] = (pNum & 0xFF00) >> 8;
commandBuffer[8] = pNum & 0xFF;
for (int i = 0; i < sizeof(commandBuffer) - 2; i++) {
sum += commandBuffer[i];
}
commandBuffer[9] = (sum & 0x00FF00) >> 8;
commandBuffer[10] = sum & 0xFF;
_uart->write(commandBuffer, sizeof(commandBuffer));
ret = waitForResp(16, 1);
if (ret != GR_OK) {
getErrorReason(ret);
}
return ret == GR_OK;
}
/**
* @brief 合并特征(生成模板)
* @note 标准应答格式 12Bytes
* @retval 0x00 0x01 0x0A
*/
bool Fingerprint::mergeFeature(void)
{
int ret = GR_OK;
uint8_t commandBuffer[6];
_uart->write(_headBuffer, 6);
commandBuffer[0] = GR_PACK_COMMAND_FLAG;
commandBuffer[1] = 0x00;
commandBuffer[2] = 0x03;
commandBuffer[3] = GR_REG_MODEL;
commandBuffer[4] = 0x00;
commandBuffer[5] = 0x09;
_uart->write(commandBuffer, sizeof(commandBuffer));
ret = waitForResp(12, 1);
if (ret != GR_OK) {
getErrorReason(ret);
}
return ret == GR_OK;
}
/**
* @brief 储存模板
* @note 标准应答格式 12Bytes
* @retval
*/
bool Fingerprint::storeFeature(GR_BufID_t id, uint16_t posNum)
{
int ret = GR_OK;
uint32_t sum = 0;
uint8_t commandBuffer[9];
_uart->write(_headBuffer, 6);
commandBuffer[0] = GR_PACK_COMMAND_FLAG;
commandBuffer[1] = 0x00;
commandBuffer[2] = 0x06;
commandBuffer[3] = GR_STORE_CHAR;
commandBuffer[4] = id;
commandBuffer[5] = (posNum & 0xFF00) >> 8;
commandBuffer[6] = posNum & 0xFF;
for (int i = 0; i < sizeof(commandBuffer) - 2; i++) {
sum += commandBuffer[i];
}
commandBuffer[7] = (sum & 0x00FF00) >> 8;
commandBuffer[8] = sum & 0xFF;
_uart->write(commandBuffer, sizeof(commandBuffer));
ret = waitForResp(12, 1);
if (ret != GR_OK) {
getErrorReason(ret);
}
return ret == GR_OK;
}
/**
* @brief 读出模板
* @note 标准应答格式 12Bytes,将flash数据库中指定ID号的指纹模板读入到模板缓冲区CharBuffer1或CharBuffer2
* @retval
*/
bool Fingerprint::loadFeature(GR_BufID_t id, uint16_t pNum)
{
int ret = GR_OK;
uint32_t sum = 0;
uint8_t commandBuffer[9];
_uart->write(_headBuffer, 6);
commandBuffer[0] = GR_PACK_COMMAND_FLAG;
commandBuffer[1] = 0x00;
commandBuffer[2] = 0x06;
commandBuffer[3] = GR_LOAD_CHAR;
commandBuffer[4] = id;
commandBuffer[5] = (pNum & 0xFF00) >> 8;
commandBuffer[6] = pNum & 0xFF;
for (int i = 0; i < sizeof(commandBuffer) - 2; i++) {
sum += commandBuffer[i];
}
commandBuffer[7] = (sum & 0x00FF00) >> 8;
commandBuffer[8] = sum & 0xFF;
_uart->write(commandBuffer, sizeof(commandBuffer));
ret = waitForResp(12, 1);
if (ret != GR_OK) {
getErrorReason(ret);
}
return ret == GR_OK;
}
/**
* @brief 上传特征或模板
* @note 标准应答格式 12Bytes
* @retval
*/
bool Fingerprint::uplaodFeature(GR_BufID_t id)
{
int ret = GR_OK;
uint32_t sum = 0;
uint8_t commandBuffer[7];
_uart->write(_headBuffer, 6);
commandBuffer[0] = GR_PACK_COMMAND_FLAG;
commandBuffer[1] = 0x00;
commandBuffer[2] = 0x04;
commandBuffer[3] = GR_UP_CHAR;
commandBuffer[4] = id;
for (int i = 0; i < sizeof(commandBuffer) - 2; i++) {
sum += commandBuffer[i];
}
commandBuffer[5] = (sum & 0x00FF00) >> 8;
commandBuffer[6] = sum & 0xFF;
_uart->write(commandBuffer, sizeof(commandBuffer));
ret = waitForResp(12, 1);
if (ret != GR_OK) {
getErrorReason(ret);
}
return ret == GR_OK;
}
/**
* @brief 下载特征或模板
* @note 标准应答格式 12Bytes
* @retval
*/
bool Fingerprint::downloadFeature(GR_BufID_t id)
{
return true;
}
// /**
// * @brief 上传原始图像
// * @note 标准应答格式 12Bytes
// * @retval
// */
// bool Fingerprint::uploadImage(void)
// {
// }
// /**
// * @brief 下载原始图像
// * @note 标准应答格式 12Bytes
// * @retval
// */
// bool Fingerprint::downloadImage(void)
// {
// }
// /**
// * @brief 删除模板
// * @note 标准应答格式 12Bytes
// * @retval
// */
// bool Fingerprint::uploadImage(void)
// {
// }
// /**
// * @brief 清空指纹库
// * @note 标准应答格式 12Bytes
// * @retval
// */
// bool Fingerprint::deleteLibarry(void)
// {
// }
// /**
// * @brief 写系统寄存器
// * @note 标准应答格式 12Bytes
// * @retval
// */
// bool Fingerprint::writeSysReg(void)
// {
// }
/**
* @brief 读系统基本参数
* @note //! 非标准应答格式 28Bytes
* @retval
*/
bool Fingerprint::readSysParams(SysParams_t *params)
{
uint8_t response[28];
const uint8_t order[] = {0x01, 0x00, 0x03, 0x0F, 0x00, 0x13};
_uart->write(_headBuffer, sizeof(_headBuffer));
_uart->write(order, sizeof(order));
if (waitForAck(response, sizeof(response))) {
if (validSum(response, sizeof(response)) && response[9] == GR_OK) {
Serial.printf("\nvalid pass\n\n");
params->statusReg = (response[10] << 8) | response[11];
params->code = response[12] << 8 | response[13];
params->libSize = response[14] << 8 | response[15];
params->level = response[16] << 8 | response[17];
params->address = response[18] << 24 | response[19] << 16 | response[20] << 8 | response[21];
params->packSize = response[22] << 8 | response[23];
params->bps = response[24] << 8 | response[25];
return true;
}
}
return false;
}
bool Fingerprint::readINFpage()
{
uint8_t response[255];
const uint8_t order[] = {0x01, 0x00, 0x03, 0x16, 0x00, 0x19};
_uart->write(_headBuffer, sizeof(_headBuffer));
_uart->write(order, sizeof(order));
if (waitForAck(response, sizeof(response))) {
if (validSum(response, sizeof(response)) && response[9] == GR_OK) {
Serial.printf("\nvalid pass\n\n");
return true;
}
}
return false;
}
// /**
// * @brief 设置口令
// * @note //! 非标准应答格式 11Bytes
// * @retval
// */
// bool Fingerprint::setPassWord(void)
// {
// }
// /**
// * @brief 验证口令
// * @note 标准应答格式 12Bytes
// * @retval
// */
// bool Fingerprint::setPassWord(void)
// {
// }
// /**
// * @brief 采样随机数
// * @note //! 非标准应答格式 16Bytes
// * @retval
// */
// bool Fingerprint::getRandom(void)
// {
// }
// /**
// * @brief 设置模块地址
// * @note 标准应答格式 12Bytes
// * @retval
// */
// bool Fingerprint::setAddress(void)
// {
// }
// /**
// * @brief 端口控制
// * @note 标准应答格式 12Bytes
// * @retval
// */
// bool Fingerprint::setAddress(void)
// {
// }
// /**
// * @brief 写记事本
// * @note 标准应答格式 12Bytes
// * @retval
// */
// bool Fingerprint::writeNotepad(void)
// {
// }
// /**
// * @brief 读记事本
// * @note //! 非标准应答格式 44Bytes
// * @retval
// */
// bool Fingerprint::readNotepad(void)
// {
// }
// /**
// * @brief 生成细化指纹图像
// * @note 标准应答格式 12Bytes
// * @retval
// */
// bool Fingerprint::generateBinImage(void)
// {
// }
// /**
// * @brief 读有效模板个数
// * @note //! 标准应答格式 14Bytes
// * @retval
// */
// bool Fingerprint::generateBinImage(void)
// {
// }
// /**
// * @brief 读索引表
// * @note //! 非标准应答格式 44Bytes
// * @retval
// */
// bool Fingerprint::readNotepad(void)
// {
// }

View File

@@ -0,0 +1,135 @@
#pragma once
#include <Arduino.h>
typedef enum {
GR_GET_IMAGE = 0X01,
GR_GET_CHAR = 0X02,
GR_MATCH = 0X03,
GR_SEARCH = 0X04,
GR_REG_MODEL = 0X05,
GR_STORE_CHAR = 0X06,
GR_LOAD_CHAR = 0X07,
GR_UP_CHAR = 0X08,
GR_DOWN_CHAR = 0X09,
GR_UP_IMAGE = 0X0A,
GR_DOWN_IMAGE = 0X0B,
GR_DEL_CHAR = 0X0C,
GR_EMPTY = 0X0D,
GR_WRITE_REG = 0X0E,
GR_READ_STATE = 0X0F,
GR_SET_PASSWORD = 0X12,
GR_VALID_PASSWORD = 0X13,
GR_GET_RANDOM = 0X14,
GR_SET_ADDRESS = 0X15,
GR_PORT_CONTROL = 0X17,
GR_WRITE_NOTEPAD = 0X18,
GR_READ_NOTEPAD = 0X19,
GR_GEN_BIN_IMAGE = 0X1C,
GR_VALID_TEMPLETE_NUM = 0X1D,
GR_READ_INDEX_TABLE = 0X1F
} GR_ORDER;
typedef enum {
GR_CHAR_BUFFER_1 = 0x01,
GR_CHAR_BUFFER_2 = 0x02
} GR_BufID_t;
enum {
GR_OK = 0X00,
PACK_ERROR = 0X01,
GR_NO_FINGERPRINT = 0X02,
GR_ENTERY_FAIL = 0X03,
GR_IMAGE_FAIL_1 = 0X04,
GR_IMAGE_FAIL_2 = 0X05,
GR_IMAGE_FAIL_3 = 0X06,
GR_IMAGE_FAIL_4 = 0X07,
GR_IMAGE_NO_MATCH = 0X08,
GR_IMAGE_SEARCH_FAIL = 0X09,
GR_MERGE_FAIL = 0X0A,
GR_REFUSE_PACK = 0X0E,
GR_IMAGE_UP_FAIL = 0X0F,
GR_IMAGE_DEL_FAIL = 0X10,
GR_DATABASE_DEL_FAIL = 0X11,
GR_ORDER_NO_MATCH = 0X12,
GR_BUFFER_EMPTY = 0X13,
GR_RW_FLASH_FAIL = 0X18,
GR_ERROR_OTHER,
GR_INVALID_REG,
GR_REG_NUM_ERROR,
GR_NOTEBOOK_ERROR,
GR_PORT_FAIL,
GR_REGISTER_FAIL,
GR_DATABASE_FULL,
};
//数据包大小 1word
//波特率 1word N * 9600
//模块口令 2word default<0>
// 默 认 波 特 率 为 57600bps
#define MODLUES_ADDRESS 0xffffffff //2WORD
#define STATUS_REG 0 //1WORD
#define SECURITY_LEVEL //1WORD
/*设备地址*/
#define GR_MD_ADDRESS 0XFFFFFFFF
typedef struct {
uint16_t statusReg;
uint16_t code;
uint16_t libSize;
uint16_t level;
uint32_t address;
uint16_t packSize;
uint16_t bps;
} SysParams_t;
class Fingerprint
{
public:
Fingerprint(Stream *UART, uint32_t ADDRRESS = GR_MD_ADDRESS);
~Fingerprint(void);
bool entryFinger(void);
bool readSysParams(SysParams_t *params);
bool generateFeature(GR_BufID_t id);
bool mergeFeature(void);
bool storeFeature(GR_BufID_t id, uint16_t posNum);
bool searchFingerprint(GR_BufID_t id, uint16_t sPage, uint16_t pNum);
bool readINFpage();
private:
bool waitForAck(uint8_t *reqs, uint8_t len);
int waitForResp(uint32_t timeout);
bool validSum(uint8_t *resp, uint8_t len);
int waitForResp(uint8_t respSize, uint32_t timeout);
void __sendCom(uint8_t command, uint16_t len);
void getErrorReason(int err);
bool matchFingerprint(void);
bool loadFeature(GR_BufID_t id, uint16_t pNum);
bool uplaodFeature(GR_BufID_t id);
bool downloadFeature(GR_BufID_t id);
// bool uploadImage(void);
// bool downloadImage(void);
// bool uploadImage(void);
// bool deleteLibarry(void);
// bool writeSysReg(void);
// bool setPassWord(void);
// bool setPassWord(void);
// bool getRandom(void);
// bool setAddress(void);
// bool setAddress(void);
// bool writeNotepad(void);
// bool readNotepad(void);
// bool generateBinImage(void);
// bool generateBinImage(void);
// bool readNotepad(void);
bool isPowerUp;
Stream *_uart;
uint32_t _addr;
uint8_t _headBuffer[6];
protected:
};