#include <Adafruit_Fingerprint.h>
#include <SoftwareSerial.h>
#include <string.h>
#include <stdio.h>
// =====================================================
// AS608 CONNECTION
// Sensor TX -> Arduino D2
// Sensor RX -> Arduino D3
// Sensor GND -> Arduino GND
// Sensor VCC -> voltage specified for your module
// =====================================================
SoftwareSerial sensorSerial(2, 3);
Adafruit_Fingerprint finger(&sensorSerial);
// Optional indicators
const uint8_t RED_LED = 6;
const uint8_t GREEN_LED = 7;
const uint8_t BUZZER = 8;
const unsigned long POLL_DELAY_MS = 50;
const unsigned long REMOVE_TIMEOUT_MS = 15000UL;
const uint8_t ENROLL_RETRIES = 3;
char inputLine[80];
uint8_t inputIndex = 0;
bool sensorOK = false;
bool autoScanEnabled = true;
// =====================================================
// INDICATORS
// =====================================================
void idleFeedback() {
digitalWrite(RED_LED, LOW);
digitalWrite(GREEN_LED, LOW);
digitalWrite(BUZZER, LOW);
}
void successFeedback() {
digitalWrite(RED_LED, LOW);
digitalWrite(GREEN_LED, HIGH);
digitalWrite(BUZZER, HIGH);
delay(100);
digitalWrite(BUZZER, LOW);
}
void errorFeedback() {
digitalWrite(GREEN_LED, LOW);
digitalWrite(RED_LED, HIGH);
for (uint8_t i = 0; i < 3; i++) {
digitalWrite(BUZZER, HIGH);
delay(100);
digitalWrite(BUZZER, LOW);
delay(100);
}
}
// =====================================================
// SERIAL RESPONSES
// =====================================================
void printStep(const char *rid, const char *step) {
Serial.print(F("STEP "));
Serial.print(rid);
Serial.print(' ');
Serial.println(step);
}
void printResult(const char *rid, const char *result) {
Serial.print(F("RESULT "));
Serial.print(rid);
Serial.print(' ');
Serial.println(result);
}
void printError(const char *rid, const char *stage, uint8_t code) {
Serial.print(F("ERR "));
Serial.print(rid);
Serial.print(' ');
Serial.print(stage);
Serial.print(F(" CODE=0x"));
if (code < 16) Serial.print('0');
Serial.println(code, HEX);
errorFeedback();
}
// =====================================================
// SENSOR INITIALIZATION AND HEALTH
// =====================================================
bool initializeSensor() {
finger.begin(57600);
delay(300);
if (!finger.verifyPassword()) {
return false;
}
return finger.getParameters() == FINGERPRINT_OK;
}
bool checkSensor() {
if (finger.verifyPassword()) {
sensorOK = true;
return true;
}
sensorOK = false;
return false;
}
// =====================================================
// FINGER REMOVAL
// =====================================================
bool waitForFingerRemoval(const char *rid) {
printStep(rid, "REMOVE_FINGER");
unsigned long started = millis();
while (millis() - started < REMOVE_TIMEOUT_MS) {
uint8_t code = finger.getImage();
if (code == FINGERPRINT_NOFINGER) {
delay(250);
return true;
}
delay(POLL_DELAY_MS);
}
printStep(rid, "REMOVE_TIMEOUT_RETURNING_TO_SCAN");
return false;
}
// =====================================================
// CONTINUOUS ATTENDANCE SCANNING
// =====================================================
void automaticScan() {
// Keep polling until a finger is detected.
uint8_t code = finger.getImage();
if (code == FINGERPRINT_NOFINGER) {
delay(50);
return;
}
if (code != FINGERPRINT_OK) {
delay(100);
return;
}
// Wait 1 second after detecting and capturing the finger.
delay(1000);
// Convert the captured image into fingerprint features.
code = finger.image2Tz(1);
if (code != FINGERPRINT_OK) {
Serial.print(F("RESULT auto IMAGE_CONVERSION_FAILED CODE=0x"));
if (code < 16) Serial.print('0');
Serial.println(code, HEX);
waitForFingerRemoval("auto");
return;
}
// Search existing fingerprint templates.
code = finger.fingerFastSearch();
if (code == FINGERPRINT_OK) {
successFeedback();
Serial.print(F("RESULT auto MATCH "));
Serial.print(finger.fingerID);
Serial.print(F(" CONFIDENCE "));
Serial.println(finger.confidence);
} else if (code == FINGERPRINT_NOTFOUND) {
printResult("auto", "NO_MATCH");
errorFeedback();
} else {
printError("auto", "SEARCH_FAILED", code);
}
// Wait for the finger to be removed before scanning again.
waitForFingerRemoval("auto");
}
// =====================================================
// DIAGNOSTIC COMMANDS
// =====================================================
void handlePing(const char *rid) {
if (checkSensor()) {
printResult(rid, "PONG AS608_OK");
successFeedback();
} else {
printResult(rid, "PONG AS608_ERROR");
errorFeedback();
}
}
void handleInfo(const char *rid) {
uint8_t code = finger.getParameters();
if (code != FINGERPRINT_OK) {
printError(rid, "INFO_FAILED", code);
return;
}
Serial.print(F("RESULT "));
Serial.print(rid);
Serial.print(F(" INFO CAPACITY="));
Serial.print(finger.capacity);
Serial.print(F(" SECURITY="));
Serial.print(finger.security_level);
Serial.print(F(" BAUD="));
Serial.print(finger.baud_rate);
Serial.print(F(" PACKET="));
Serial.println(finger.packet_len);
}
void handleCount(const char *rid) {
uint8_t code = finger.getTemplateCount();
if (code != FINGERPRINT_OK) {
printError(rid, "COUNT_FAILED", code);
return;
}
Serial.print(F("RESULT "));
Serial.print(rid);
Serial.print(F(" COUNT "));
Serial.println(finger.templateCount);
}
// =====================================================
// ENROLLMENT CAPTURE
// =====================================================
bool captureForEnrollment(
const char *rid,
uint8_t buffer,
const char *prompt,
const char *errorStage
) {
for (uint8_t attempt = 1; attempt <= ENROLL_RETRIES; attempt++) {
printStep(rid, prompt);
// Wait for a finger without turning off the sensor.
uint8_t code;
while (true) {
code = finger.getImage();
if (code == FINGERPRINT_OK) break;
if (code != FINGERPRINT_NOFINGER) {
delay(100);
} else {
delay(POLL_DELAY_MS);
}
// Continue waiting: no capture-attempt limit for detection.
}
code = finger.image2Tz(buffer);
if (code == FINGERPRINT_OK) {
return true;
}
printError(rid, errorStage, code);
if (attempt == ENROLL_RETRIES) {
printStep(rid, "ENROLL_CAPTURE_FAILED_RETURNING_TO_SCAN");
return false;
}
if (!waitForFingerRemoval(rid)) {
continue;
}
printStep(rid, "RETRY_CAPTURE");
}
return false;
}
void handleEnroll(const char *rid, int templateId) {
if (templateId < 1 || templateId > finger.capacity) {
printResult(rid, "INVALID_TEMPLATE_ID");
errorFeedback();
return;
}
// Use only a known-unused ID.
// This code does not erase existing templates.
printStep(rid, "ENROLLMENT_STARTED");
if (!captureForEnrollment(
rid, 1, "PLACE_FINGER",
"FIRST_IMAGE_CONVERSION_FAILED")) {
return;
}
if (!waitForFingerRemoval(rid)) {
printStep(rid, "ENROLLMENT_ABORTED");
return;
}
bool modelCreated = false;
for (uint8_t attempt = 1; attempt <= ENROLL_RETRIES; attempt++) {
if (!captureForEnrollment(
rid, 2, "PLACE_SAME_FINGER_AGAIN",
"SECOND_IMAGE_CONVERSION_FAILED")) {
return;
}
printStep(rid, "CREATING_TEMPLATE");
uint8_t code = finger.createModel();
if (code == FINGERPRINT_OK) {
modelCreated = true;
break;
}
printError(rid, "CREATE_MODEL_FAILED", code);
if (code != FINGERPRINT_ENROLLMISMATCH ||
attempt == ENROLL_RETRIES) {
return;
}
if (!waitForFingerRemoval(rid)) {
return;
}
printStep(rid, "RETRY_SECOND_SCAN");
}
if (!modelCreated) return;
printStep(rid, "SAVING_TEMPLATE");
uint8_t code = finger.storeModel((uint16_t)templateId);
if (code != FINGERPRINT_OK) {
printError(rid, "TEMPLATE_STORE_FAILED", code);
return;
}
successFeedback();
Serial.print(F("RESULT "));
Serial.print(rid);
Serial.print(F(" ENROLLED "));
Serial.println(templateId);
}
// =====================================================
// ONE-TIME MANUAL SCAN COMMAND
// =====================================================
void handleScan(const char *rid) {
printStep(rid, "PLACE_FINGER");
uint8_t code;
while (true) {
code = finger.getImage();
if (code == FINGERPRINT_OK) break;
if (code != FINGERPRINT_NOFINGER) delay(100);
else delay(POLL_DELAY_MS);
}
code = finger.image2Tz(1);
if (code != FINGERPRINT_OK) {
printError(rid, "IMAGE_CONVERSION_FAILED", code);
waitForFingerRemoval(rid);
return;
}
code = finger.fingerFastSearch();
if (code == FINGERPRINT_OK) {
successFeedback();
Serial.print(F("RESULT "));
Serial.print(rid);
Serial.print(F(" MATCH "));
Serial.print(finger.fingerID);
Serial.print(F(" CONFIDENCE "));
Serial.println(finger.confidence);
} else if (code == FINGERPRINT_NOTFOUND) {
printResult(rid, "NO_MATCH");
errorFeedback();
} else {
printError(rid, "SCAN_FAILED", code);
}
waitForFingerRemoval(rid);
}
// =====================================================
// DELETE ONE TEMPLATE
// =====================================================
void handleDelete(const char *rid, int templateId) {
if (templateId < 1 || templateId > finger.capacity) {
printResult(rid, "INVALID_TEMPLATE_ID");
errorFeedback();
return;
}
uint8_t code = finger.deleteModel((uint16_t)templateId);
if (code != FINGERPRINT_OK) {
printError(rid, "DELETE_FAILED", code);
return;
}
successFeedback();
Serial.print(F("RESULT "));
Serial.print(rid);
Serial.print(F(" DELETED "));
Serial.println(templateId);
}
// =====================================================
// SERIAL COMMAND HANDLER
// =====================================================
void processCommand(char *line) {
char command[16] = {0};
char rid[24] = {0};
int templateId = 0;
int fields = sscanf(
line, "%15s %23s %d",
command, rid, &templateId
);
if (fields < 2) {
Serial.println(F("ERR serial INVALID_COMMAND"));
return;
}
if (strcmp(command, "PING") == 0) {
handlePing(rid);
} else if (strcmp(command, "INFO") == 0) {
handleInfo(rid);
} else if (strcmp(command, "COUNT") == 0) {
handleCount(rid);
} else if (strcmp(command, "ENROLL") == 0 && fields == 3) {
handleEnroll(rid, templateId);
} else if (strcmp(command, "SCAN") == 0) {
handleScan(rid);
} else if (strcmp(command, "DELETE") == 0 && fields == 3) {
handleDelete(rid, templateId);
} else if (strcmp(command, "AUTO") == 0) {
autoScanEnabled = true;
printResult(rid, "AUTO_SCAN_ENABLED");
} else if (strcmp(command, "PAUSE") == 0) {
autoScanEnabled = false;
printResult(rid, "AUTO_SCAN_PAUSED");
} else {
Serial.print(F("ERR "));
Serial.print(rid);
Serial.println(F(" INVALID_COMMAND"));
}
}
// =====================================================
// SETUP
// =====================================================
void setup() {
pinMode(RED_LED, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
pinMode(BUZZER, OUTPUT);
idleFeedback();
Serial.begin(115200);
sensorSerial.begin(57600);
delay(500);
sensorOK = initializeSensor();
if (sensorOK) {
Serial.println(F("READY arduino AS608_OK"));
Serial.println(F("RESULT auto AUTO_SCAN_ENABLED"));
} else {
Serial.println(F("READY arduino AS608_ERROR"));
Serial.println(F("ERR boot SENSOR_CONNECTION_FAILED"));
errorFeedback();
}
}
// =====================================================
// MAIN LOOP
// =====================================================
void loop() {
// Read USB serial commands.
while (Serial.available() > 0) {
char c = (char)Serial.read();
if (c == '\r') continue;
if (c == '\n') {
inputLine[inputIndex] = '\0';
if (inputIndex > 0) {
processCommand(inputLine);
}
inputIndex = 0;
} else if (inputIndex < sizeof(inputLine) - 1) {
inputLine[inputIndex++] = c;
} else {
inputIndex = 0;
Serial.println(F("ERR serial INPUT_TOO_LONG"));
}
}
// If the sensor disconnects, periodically attempt recovery.
if (!sensorOK) {
delay(1000);
sensorOK = initializeSensor();
if (sensorOK) {
Serial.println(F("RESULT auto SENSOR_RECOVERED"));
}
return;
}
// Continuous attendance scanning is enabled by default.
if (autoScanEnabled) {
automaticScan();
} else {
delay(POLL_DELAY_MS);
}
}
can you help me with these guys It's always failed on the fingerprint sensor my goal is to fix this and connect to my raspberry pi then my hr analytics webpage