Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <HardwareSerial.h>
- #include <fpm.h>
- FPM finger(&Serial2);
- FPMSystemParams params;
- /* for convenience */
- #define PRINTF_BUF_SZ 60
- char printfBuf[PRINTF_BUF_SZ];
- /* This should be equal to the template size for your sensor,
- which can be anywhere from 512 to 1536 bytes.
- So check the printed result of readTemplate() to determine
- the correct template size for your sensor and adjust the buffer
- size below accordingly. If this example doesn't work at first, try increasing
- this value, provided you have sufficient RAM.
- */
- #define TEMPLATE_SZ 1536
- uint8_t template_buffer[TEMPLATE_SZ];
- #define RXD2 16
- #define TXD2 17
- void setup()
- {
- Serial.begin(57600);
- Serial2.begin(57600, SERIAL_8N1, RXD2, TXD2);
- Serial.println("TEMPLATES example");
- if (finger.begin()) {
- finger.readParams(¶ms);
- Serial.println("Found fingerprint sensor!");
- Serial.print("Capacity: "); Serial.println(params.capacity);
- Serial.print("Packet length: "); Serial.println(FPM::packetLengths[static_cast<uint8_t>(params.packetLen)]);
- }
- else {
- Serial.println("Did not find fingerprint sensor :(");
- while (1) yield();
- }
- }
- void loop() {
- Serial.println("\r\nSend any character to enroll a finger...");
- while (Serial.available() == 0) yield();
- Serial.println("Searching for a free slot to store the template...");
- int16_t fid;
- if (getFreeId(&fid))
- {
- enrollFinger(fid);
- }
- else
- {
- Serial.println("No free slot/ID in database!");
- }
- while (Serial.read() != -1); // clear buffer
- }
- bool getFreeId(int16_t * fid)
- {
- for (int page = 0; page < (params.capacity / FPM_TEMPLATES_PER_PAGE) + 1; page++)
- {
- FPMStatus status = finger.getFreeIndex(page, fid);
- switch (status)
- {
- case FPMStatus::OK:
- if (*fid != -1) {
- Serial.print("Free slot at ID ");
- Serial.println(*fid);
- return true;
- }
- break;
- default:
- snprintf(printfBuf, PRINTF_BUF_SZ, "getFreeIndex(%d): error 0x%X", page, static_cast<uint16_t>(status));
- Serial.println(printfBuf);
- return false;
- }
- yield();
- }
- Serial.println("No free slots!");
- return false;
- }
- bool enrollFinger(int16_t fid)
- {
- FPMStatus status;
- const int NUM_SNAPSHOTS = 2;
- #if defined(FPM_LED_CONTROL_ENABLED)
- finger.ledOn();
- #endif
- /* Take snapshots of the finger,
- and extract the fingerprint features from each image */
- for (int i = 0; i < NUM_SNAPSHOTS; i++)
- {
- Serial.println(i == 0 ? "Place a finger" : "Place same finger again");
- do {
- #if defined(FPM_LED_CONTROL_ENABLED)
- status = finger.getImageOnly();
- #else
- status = finger.getImage();
- #endif
- switch (status)
- {
- case FPMStatus::OK:
- Serial.println("Image taken");
- break;
- case FPMStatus::NOFINGER:
- //Serial.println(".");
- break;
- default:
- /* allow retries even when an error happens */
- snprintf(printfBuf, PRINTF_BUF_SZ, "getImage(): error 0x%X", static_cast<uint16_t>(status));
- Serial.println(printfBuf);
- break;
- }
- yield();
- }
- while (status != FPMStatus::OK);
- status = finger.image2Tz(i + 1);
- switch (status)
- {
- case FPMStatus::OK:
- Serial.println("Image converted");
- break;
- default:
- snprintf(printfBuf, PRINTF_BUF_SZ, "image2Tz(%d): error 0x%X", i + 1, static_cast<uint16_t>(status));
- Serial.println(printfBuf);
- return false;
- }
- finger.ledOff();
- Serial.println("Remove finger");
- delay(2000);
- finger.ledOn();
- do {
- #if defined(FPM_LED_CONTROL_ENABLED)
- status = finger.getImageOnly();
- #else
- status = finger.getImage();
- #endif
- delay(200);
- }
- while (status != FPMStatus::NOFINGER);
- }
- #if defined(FPM_LED_CONTROL_ENABLED)
- finger.ledOff();
- #endif
- /* Images have been taken and converted into features a.k.a character files.
- Now, need to create a model/template from these features and store it. */
- status = finger.generateTemplate();
- switch (status)
- {
- case FPMStatus::OK:
- Serial.println("Template created from matching prints!");
- break;
- case FPMStatus::ENROLLMISMATCH:
- Serial.println("The prints do not match!");
- return false;
- default:
- snprintf(printfBuf, PRINTF_BUF_SZ, "createModel(): error 0x%X", static_cast<uint16_t>(status));
- Serial.println(printfBuf);
- return false;
- }
- status = finger.storeTemplate(fid);
- switch (status)
- {
- case FPMStatus::OK:
- snprintf(printfBuf, PRINTF_BUF_SZ, "Template stored at ID %d!", fid);
- Serial.println(printfBuf);
- break;
- case FPMStatus::BADLOCATION:
- snprintf(printfBuf, PRINTF_BUF_SZ, "Could not store in that location %d!", fid);
- Serial.println(printfBuf);
- return false;
- default:
- snprintf(printfBuf, PRINTF_BUF_SZ, "storeModel(): error 0x%X", static_cast<uint16_t>(status));
- Serial.println(printfBuf);
- return false;
- }
- uint16_t totalRead = readTemplate(fid, template_buffer, TEMPLATE_SZ);
- Serial.print("Total Read: ");
- Serial.println(totalRead);
- Serial.println();
- return true;
- }
- uint16_t readTemplate(uint16_t fid, uint8_t * buffer, uint16_t bufLen)
- {
- /* Load the template from the sensor's storage into one of its Buffers
- (Buffer 1 by default) */
- FPMStatus status = finger.loadTemplate(fid);
- switch (status)
- {
- case FPMStatus::OK:
- Serial.print("Template "); Serial.print(fid); Serial.println(" loaded");
- break;
- case FPMStatus::DBREADFAIL:
- Serial.println(F("Invalid template or location"));
- return false;
- default:
- snprintf_P(printfBuf, PRINTF_BUF_SZ, PSTR("loadTemplate(%d): error 0x%X"), fid, static_cast<uint16_t>(status));
- Serial.println(printfBuf);
- return false;
- }
- /* Inform the sensor that we're about to download a template from that Buffer */
- status = finger.downloadTemplate();
- switch (status)
- {
- case FPMStatus::OK:
- break;
- default:
- snprintf_P(printfBuf, PRINTF_BUF_SZ, PSTR("downloadTemplate(%d): error 0x%X"), fid, static_cast<uint16_t>(status));
- Serial.println(printfBuf);
- return false;
- }
- /* Now, the sensor will send us the template from that Buffer, one packet at a time */
- bool readComplete = false;
- /* As an argument, this holds the max number of bytes to read from the sensor.
- Whenever the function returns successfully, it then holds the number of bytes actually read. */
- uint16_t readLen = bufLen;
- uint16_t bufPos = 0;
- while (!readComplete)
- {
- bool ret = finger.readDataPacket(buffer + bufPos, NULL, &readLen, &readComplete);
- if (!ret)
- {
- snprintf_P(printfBuf, PRINTF_BUF_SZ, PSTR("readDataPacket(): failed after reading %u bytes"), bufPos);
- Serial.println(printfBuf);
- return 0;
- }
- bufPos += readLen;
- readLen = bufLen - bufPos;
- yield();
- }
- uint16_t totalBytes = bufPos;
- /* just for pretty-printing */
- uint16_t numRows = totalBytes / 16;
- Serial.println(F("Printing template:"));
- const char * dashes = "---------------------------------------------";
- Serial.println(dashes);
- for (int row = 0; row < numRows; row++) {
- for (int col = 0; col < 16; col++) {
- Serial.print("0x");
- Serial.print(buffer[row * 16 + col], HEX);
- Serial.print(", ");
- }
- Serial.println();
- yield();
- }
- Serial.println(dashes);
- Serial.print(totalBytes); Serial.println(" bytes read.");
- return totalBytes;
- }
- bool deleteTemplate(int fid)
- {
- FPMStatus status = finger.deleteTemplate(fid);
- switch (status)
- {
- case FPMStatus::OK:
- snprintf_P(printfBuf, PRINTF_BUF_SZ, PSTR("Deleted ID #%u."), fid);
- Serial.println(printfBuf);
- break;
- case FPMStatus::DELETEFAIL:
- snprintf_P(printfBuf, PRINTF_BUF_SZ, PSTR("Failed to delete ID #%u."), fid);
- Serial.println(printfBuf);
- return false;
- default:
- snprintf_P(printfBuf, PRINTF_BUF_SZ, PSTR("deleteTemplate(): error 0x%X"), static_cast<uint16_t>(status));
- Serial.println(printfBuf);
- return false;
- }
- return true;
- }
- bool writeTemplate(uint16_t fid, uint8_t * buffer, uint16_t templateSz)
- {
- /* Inform the sensor that we're about to upload a template to one of its Buffers
- (Buffer 1 by default) */
- FPMStatus status = finger.uploadTemplate();
- switch (status)
- {
- case FPMStatus::OK:
- Serial.println("Starting template upload...");
- break;
- default:
- snprintf_P(printfBuf, PRINTF_BUF_SZ, PSTR("uploadTemplate(%u): error 0x%X"), fid, static_cast<uint16_t>(status));
- Serial.println(printfBuf);
- return false;
- }
- /* One packet at a time, upload the template to that Buffer */
- uint16_t writeLen = templateSz;
- uint16_t written = 0;
- const uint16_t PACKET_LENGTH = FPM::packetLengths[static_cast<uint8_t>(params.packetLen)];
- while (writeLen)
- {
- /* the write is completed when we have no more than PACKET_LENGTH left to write */
- bool ret = finger.writeDataPacket(buffer + written, NULL, &writeLen, writeLen <= PACKET_LENGTH);
- if (!ret)
- {
- snprintf_P(printfBuf, PRINTF_BUF_SZ, PSTR("writeDataPacket(): failed after writing %u bytes"), written);
- Serial.println(printfBuf);
- return false;
- }
- written += writeLen;
- writeLen = templateSz - written;
- yield();
- }
- /* Finally, store the template at the specified location */
- status = finger.storeTemplate(fid);
- switch (status)
- {
- case FPMStatus::OK:
- snprintf_P(printfBuf, PRINTF_BUF_SZ, PSTR("Template stored at ID %d!"), fid);
- Serial.println(printfBuf);
- break;
- case FPMStatus::BADLOCATION:
- snprintf_P(printfBuf, PRINTF_BUF_SZ, PSTR("Could not store in that location %d!"), fid);
- Serial.println(printfBuf);
- return false;
- default:
- snprintf_P(printfBuf, PRINTF_BUF_SZ, PSTR("storeModel(%u): error 0x%X"), fid, static_cast<uint16_t>(status));
- Serial.println(printfBuf);
- return false;
- }
- return true;
- }
Add Comment
Please, Sign In to add comment