Hardware components | ||||||
![]() |
| × | 40 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
| × | 1 | ||||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
Software apps and online services | ||||||
![]() |
|
(외관)
서울과학고등학교에서는 7시부터 9시, 9시 30분부터 11시까지 2번의 자습시간이 존재한다. 그리고 자습시간에 학생들은 각자 자신의 자리에 앉아 자습을 하거나 특별한 경우 이석신청을 하고 여러 장소에 이석을 해 각자 할 일을 한다. 그리고 이러한 시간에 이탈한 학생이 없는지 확인하기 위해 사감선생님들은 자습실과 여러 이석장소들을 돌아다니며 학생들의 출석을 체크한다. 그러나 사감선생님께서 직접 돌아다니며 출석체크를 하는 방식은 사감선생님의 이동거리가 길기 때문에 비효율적이며, 각 이석장소 별 출석체크의 시간이 다르다 보니 지각생을 정확히 확인할 수 없는 문제점이 존재한다. 이러한 문제점을 해결하기 위해 지문인식센서를 통해 사감선생님 대신 출석체크를 할 수 있도록 해주는 기기를 아두이노를 통해 발명하게 되었다.
이 기기의 겉에는 크게 2가지의 장치가 있는데, 먼저 지문은 인식하는 지문인식센서, 그리고 지문이 인식되면 정보가 나오는 디스플레이로 이루어져 있다. 학생들이 출석체크를 위해 이 기기를 사용할 경우 등록된 자신의 손가락을 지문인식센서에 인식시키면 디스플레이에 현제 출석 체크한 학생의 번호와 현재 시간과 같은 정보가 출력된다.
이 기기를 구현하기 위해서 먼저 지문을 인식하는 지문인식센서와 지문인식센서를 통해 인식한 정보를 송수신할 수 있는 블루투스 모듈, 그리고 받아들인 정보를 출력하는 디스플레이가 필요했다. 그리고 체크한 시간을 확인하기 위한 시계도 기기 내부에 내장되어 있다. 따라서 지문인식센서가 지문을 인식하면 인식한 지문의 주인을 알아낸 뒤, 지문의 주인에 대한 정보와 현재 시간을 디스플레이에 나타냄과 동시에 블루투스 모듈을 통해 핸드폰 앱으로도 그 정보를 전달하여 저장한다. 만약 성공적으로 지문이 인식되어 정보를 수집했다면 기기 위의 LED에 불이 켜져 출석 체크가 성공적으로 수집되었음을 알린다.
이 기기를 사용하게 된다면 사감 선생님들도 이동할 필요가 없어져 피로가 감소하게 되고 학생들도 사감선생님이 출석체크를 할때까지 화장실도 가지 못하고 자신의 자리에서 기다릴 필요가 없어져 사감선생님과 학생 모두 더 행복한 출석체크를 할 수 있을 것이다. 그러나 정보의 송신을 블루투스를 이용하기 때문에 서로 연결이 가능한 범위가 상대적으로 짧은 점은 개선해야 할 부분이다.
다음은 앱 개발을 할 때 사용했던 프로그램의 캡쳐이다.
#include <Adafruit_Fingerprint.h>
#include <TimeLib.h>
#include <DS1302RTC.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
DS1302RTC RTC(4, 3, 2);
#define BT_RXD 40
#define BT_TXD 42
SoftwareSerial bluetooth(BT_RXD, BT_TXD);
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
SoftwareSerial mySerial(10, 11);
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
int redPin = 7;
int greenPin = 8;
int bluePin = 9;
int gPin = 6;
int bPin = 5;
int SHJHBH = 32;
int checklist[128]={0};
tmElements_t tm;
void setup()
{
lcd.init(); // initialize the lcd
// Print a message to the LCD.
lcd.backlight();
Serial.begin(9600);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(gPin, OUTPUT);
pinMode(bPin, OUTPUT);
digitalWrite(gPin, LOW);
digitalWrite(bPin, HIGH);
digitalWrite(SHJHBH, HIGH);
RTC.haltRTC(0);
RTC.writeEN(false);
bluetooth.begin(9600);
Serial.begin(9600);
while (!Serial); // For Yun/Leo/Micro/Zero/...
delay(100);
Serial.println("\n\nAdafruit finger detect test");
// set the data rate for the sensor serial port
finger.begin(57600);
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() // run over and over again
{
for(int j=0; checklist[j]; j++) {
bluetooth.print(checklist[j]);
bluetooth.println(" student checked in at");
bluetooth.print(tm.Month);
bluetooth.print("/");
bluetooth.print(tm.Day);
bluetooth.print(", ");
bluetooth.print(tm.Hour);
bluetooth.print(":");
bluetooth.print(tm.Minute);
bluetooth.print(":");
bluetooth.print(tm.Second);
}
getFingerprintIDez();
delay(50); //don't ned to run this at full speed.
}
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");
setColor(255, 0, 0); // red
digitalWrite(redPin , HIGH);
delay(1000);
digitalWrite(redPin, LOW);
return p;
} else if (p == FINGERPRINT_NOTFOUND) {
Serial.println("Did not find a match");
setColor(255, 0, 0); // red
digitalWrite(redPin , HIGH);
delay(1000);
digitalWrite(redPin, LOW);
return p;
} else {
Serial.println("Unknown error");
setColor(255, 0, 0); // red
digitalWrite(redPin , HIGH);
delay(1000);
digitalWrite(redPin, LOW);
return p;
}
// found a match!
Serial.print("Found ID #"); Serial.print(finger.fingerID);
Serial.print(" with confidence of "); Serial.println(finger.confidence);
lcd.setCursor(0, 0);
lcd.print(finger.fingerID);
lcd.print(" student ");
lcd.setCursor(0, 1);
if(RTC.read(tm)==0){
//lcd.print(tmYearToCalendar(tm.Year));
//lcd.print("/");
lcd.print(tm.Month);
lcd.print("/");
lcd.print(tm.Day);
lcd.print(", ");
lcd.print(tm.Hour);
lcd.print(":");
lcd.print(tm.Minute);
lcd.print(":");
lcd.print(tm.Second);
}
else lcd.print("TRY AGAIN");
for(int i=0; 1;) {
if(!checklist[i]) {
checklist[i] = finger.fingerID;
break;
}
i++;
}
setColor(0, 255, 0); // green
delay(1000);
digitalWrite(greenPin,LOW);
digitalWrite(redPin,LOW);
digitalWrite(bluePin,LOW);
return finger.fingerID;
}
// returns -1 if failed, otherwise returns 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;
// found a match!
lcd.setCursor(0, 0);
lcd.print(finger.fingerID);
lcd.print(" student ");
lcd.setCursor(0, 1);
if(RTC.read(tm)==0){
//lcd.print(tmYearToCalendar(tm.Year));
//lcd.print("/");
lcd.print(tm.Month);
lcd.print("/");
lcd.print(tm.Day);
lcd.print(", ");
lcd.print(tm.Hour);
lcd.print(":");
lcd.print(tm.Minute);
lcd.print(":");
lcd.print(tm.Second);
}
else lcd.print("TRY AGAIN");
bluetooth.print(finger.fingerID);
bluetooth.println(" student checked in at");
bluetooth.print(tm.Month);
bluetooth.print("/");
bluetooth.print(tm.Day);
bluetooth.print(", ");
bluetooth.print(tm.Hour);
bluetooth.print(":");
bluetooth.print(tm.Minute);
bluetooth.print(":");
bluetooth.print(tm.Second);
setColor(0, 255, 0); // green
delay(1000);
digitalWrite(greenPin,LOW);
digitalWrite(redPin,LOW);
digitalWrite(bluePin,LOW);
return finger.fingerID;
}
void setColor(int red, int green, int blue)
{
analogWrite(redPin, red);
analogWrite(greenPin, green);
analogWrite(bluePin, blue);
}
#include <Adafruit_Fingerprint.h>
// On Leonardo/Micro or others with hardware serial, use those! #0 is green wire, #1 is white
// uncomment this line:
// #define mySerial Serial1
// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino (WHITE wire)
// comment these two lines if using hardware serial
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10,11);
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
uint8_t id;
int led1 = 5;
int led2 = 6;
void setup()
{
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
Serial.begin(9600);
while (!Serial); // For Yun/Leo/Micro/Zero/...
delay(100);
Serial.println("\n\nAdafruit Fingerprint sensor enrollment");
// set the data rate for the sensor serial port
finger.begin(57600);
if (finger.verifyPassword()) {
Serial.println("Found fingerprint sensor!");
} else {
Serial.println("Did not find fingerprint sensor :(");
while (1) { delay(1); }
}
}
uint8_t readnumber(void) {
uint8_t num = 0;
while (num == 0) {
while (! Serial.available());
num = Serial.parseInt();
}
return num;
}
void loop() // run over and over again
{
Serial.println("Ready to enroll a fingerprint!");
Serial.println("Please type in the ID # (from 1 to 127) you want to save this finger as...");
id = readnumber();
if (id == 0) {// ID #0 not allowed, try again!
return;
}
Serial.print("Enrolling ID #");
Serial.println(id);
while (! getFingerprintEnroll() );
}
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!");
digitalWrite(led1, HIGH);
delay(1000);
digitalWrite(led1, LOW);
} 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;
}
}
Comments