정보나눔

오픈소스하드웨어 프로젝트에 대한 다양한 정보를 나누는 공간입니다.

DIY 금고 지문인식 관련해서 질문합니다.
safasf | 2019-11-27

GT-511C3 제품의 재고가 없어서 Grove FingerSensor를 사용하였습니다.

* 키패드 비밀번호 입력 >> 지문인식 등록 >> 지문 확인 >> 열림  순으로 동작합니다.

  지문 등록 >> 비밀번호 입력 >> 지문인식 입력 >> 열림 순으로 동작시키고 싶습니다.

 

-----------------------------------------------------------------------------------------------------------------------

#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
#include <Adafruit_Fingerprint.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo myservo;
SoftwareSerial mySerial(12, 13);

char secretCode[4] = {'1', '1', '1', '1'};
char input[4];
char key;

int wrong = 0;
int i = 0;
int j = 0;
int pos = 90;
int a = 0;
int b = 0;
int judge_finger = 0; // 각각 비번과 지문이 일치할 때, 1의 값을 반환함.

const byte rows = 4;
const byte cols = 4;
boolean c = false;

char keys[rows][cols] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[rows] = {A0, A1, A2, A3};
byte colPins[cols] = {5, 4, 3, 2};

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);

void input_key();
void password();
void password_check();

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); 
// 지문 센서 사용을 위한 객체선언 

uint8_t id; // 지문을 구분하는 아이디(숫자 1~127)

//=========================================================
void setup()
{
  Serial.begin(9600);
  while (!Serial);
  lcd.begin();
  myservo.attach(10);
  finger.begin(57600);

  delay(5);
  
  if (finger.verifyPassword()) { // 지문 센서 동작 여부 판단 
    Serial.println("Found fingerprint sensor!");
  } else {
    Serial.println("Did not find fingerprint sensor :(");
    while (1) { delay(1); }
  }

  finger.getTemplateCount();
  Serial.print("Sensor contains "); 
  Serial.print(finger.templateCount); 
  Serial.println(" templates");
  Serial.println("Waiting for valid finger...");
}

 


void loop()

  int stat = 0, count = 0;

  
  while(a == 0)//비밀번호가 일치하지 않을경우 
  {
    input_key();            // Password Input Mode
    password();             // Confirm Password
    password_check();       // Display current state
    
    if(count >= 5){
      Serial.println("비밀번호 5회 이상 실패!");
      break;
    }
    count++;
  }

  /*if(count >= 5){ // 비밀번호를 5회 이상 실패시 뒤의 과정 생략 후, 맨 처음으로
    count = 0;
    stat = 1;
  } else count = 0; // 지문 인식을 위해 카운트 초기화 */

  

  if(keypad.getKey() == '#'){ // 입력한 키패드가 #이면 지문 등록 모드로 진입 
    id = readnumber(); // 1~127 ID에 지문을 등록 
    // 지문 등록 모드시 지문 등록을 완료할 때까지 대기상태로 들어감.
    
    Serial.print("Enrolling ID #");
    Serial.println(id);
    while (!  getFingerprintEnroll() ); // 지문 등록 
  }
  
  if (id == 0) {// ID #0 not allowed, try again!
     return;
  }
  
  while (b == 0)//지문이 일치하지 않을 경우 일치할 때까지 반복.
  {
    if(stat == 1){
        break;
    }

    int judge = 0;

    getFingerprintIDez(); // 인식이 실패할 경우 -1을 반환함 
    delay(50);
    
    if(judge == -1){
      count++;
      Serial.println("지문이 일치하지 않습니다.");
    } else{
      b = 1;
      break;
    }
    
    if(count >= 5){
      Serial.println("지문인식 5회 이상 실패!");
      break;
    }
  }
 
  /*if(count >= 5){ // 지문을 5회 이상 실패시 뒤의 과정 생략 후, 맨 처음으로.
    count = 0;
    continue;
  } else count = 0; // 다음 작업을 위해 초기화 */


  if(a == 1 && b == 1){ // 비밀번호와 지문이 일치한다면 
    lcd.clear();
    lcd.setCursor(0, 0);
    //pinMode(10, OUTPUT);

    myservo.write(180);      //열림
    lcd.print("perfect complete");
    delay(2000);
    
    if (keypad.getKey() == '*')// '*'을 누르면 잠근다.(getkey는 한 글자만 입력받음)
    {
      a = 0;                // Clear Flag
      b = 0;                // Clear Flag
      lcd.clear();
      lcd.setCursor(0, 0);
      
      myservo.write(90);     //잠김
      lcd.print("    Lock ON");
      delay(2000);
    }
  }
}

//=========================================================
void input_key()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("    Password");
  for (i = 0; i < 4; i++)
  {
    key = keypad.waitForKey();
    input[i] = key;
    lcd.setCursor(i + 6, 1);
    lcd.print("*");
    Serial.print(input[i], DEC);
    Serial.print("*");
    if (i == 3)
    {
      Serial.println("");
    }
  }
}


//=========================================================
void password()
{
  wrong = 0;
  for (j = 0; j < 4; j++)
  {
    if (secretCode[j] == input[j])
    {
    }
    else if (secretCode[j] != input[j])
    {
      wrong += 1;
    }
  }
}//input배열에 입력한 숫자가 설정한 비밀번호와 같으면 wrong = 0, 아니면  1~4의 값을 가짐

 

//=========================================================
void password_check()
{
  if (wrong == 0) // 입력한 숫자가 비밀번호와 같을 때
  {
    Serial.println("correct");
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("      PASS");
    delay(2000);
    a = 1;
    lcd.clear();
  }// a = 1
  else if (wrong != 0) //입력한 숫자가 비밀번호와 같지 않을 때
  {
    Serial.println("wrong");
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("     wrong");
    delay(2000);
    a = 0;
    lcd.clear();
    wrong = 0;
  }//a = 0
}


//=========================================================
int getFingerprintIDez() { // -1를 반환하면 인식 실패, 그 외에는 ID를 반환 
  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;
  
  // found a match!
  Serial.print("Found ID #"); 
  Serial.print(finger.fingerID); 
  Serial.print(" with confidence of "); 
  Serial.println(finger.confidence);
  
  return finger.fingerID; 
}


//=========================================================
uint8_t getFingerprintID() { // 인증을 위한 함수 
  uint8_t p = finger.getImage();
  
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.println("No finger detected");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("Imaging error");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  // OK success!

  p = finger.image2Tz();
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }
  
  // OK converted!
  p = finger.fingerFastSearch();
  if (p == FINGERPRINT_OK) {
    Serial.println("Found a print match!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_NOTFOUND) {
    Serial.println("Did not find a match");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }   
  
  // found a match!
  Serial.print("Found ID #"); Serial.print(finger.fingerID); 
  Serial.print(" with confidence of "); Serial.println(finger.confidence); 

  return finger.fingerID;
}


//=========================================================
uint8_t readnumber(void) { // 1~127 번호 등록을 위한 함수. 
  uint8_t num = 0;
  while (num == 0) {
    while (! Serial.available());
    num = Serial.parseInt(); // 시리얼 모니터에 정수 입력
  }
  
  return num;
}


//=========================================================
uint8_t getFingerprintEnroll() { // 등록을 위한 함수 
  int p = -1;
  Serial.print("Waiting for valid finger to enroll as #"); 
  Serial.println(id);
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();

    switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.println("");
      break;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      break;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("Imaging error");
      break;
    default:
      Serial.println("Unknown error");
      break;
    }
  }

  // OK success!

  p = finger.image2Tz(1);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }
  
  Serial.println("Remove finger");
  delay(2000);
  p = 0;
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  Serial.print("ID "); Serial.println(id);
  p = -1;
  Serial.println("Place same finger again");
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.print(".");
      break;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      break;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("Imaging error");
      break;
    default:
      Serial.println("Unknown error");
      break;
    }
  }

  // OK success!

  p = finger.image2Tz(2);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }
  
  // OK converted!
  Serial.print("Creating model for #");  Serial.println(id);
  
  p = finger.createModel();
  if (p == FINGERPRINT_OK) {
    Serial.println("Prints matched!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_ENROLLMISMATCH) {
    Serial.println("Fingerprints did not match");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }   
  
  Serial.print("ID "); Serial.println(id);
  p = finger.storeModel(id);
  if (p == FINGERPRINT_OK) {
    Serial.println("Stored!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_BADLOCATION) {
    Serial.println("Could not store in that location");
    return p;
  } else if (p == FINGERPRINT_FLASHERR) {
    Serial.println("Error writing to flash");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }   
}

이전글   |    아두이노 프로그래밍과정을 익히면서 합쳐봤는데 잘 안되네요...... 2019-11-26
다음글   |    web client예제의 활용에 대해 질문 드립니다.... 2019-11-27