You are on page 1of 31

2/27/2018 Attendance Record System – Tutorial by Cytron

ATTENDANCE RECORD SYSTEM


Home  Arduino  Attendance Record System

By bengchet  12

Arduino Sensor
September 2, 2013

I have been given a task to build an attendance system for staff. The requirements are quite
straight-forward. It needs to be standalone (without computer), fingerprint is preferred, record
real time and the record should be in SD card.

1.0 Introduction
There has been various kinds of attendance record system in the market, RFID-based, fingerprint
scanning-based and barcode-based, etc. Talking about this attendance system, you may think that
it is quite complex and hard to build it. However, after you read this article, you may change your
perception. In this tutorial, we are going to demonstrate how to make a simple attendance system
using Cytron current on-sale product including Arduino board, SM630 fingerprint module, Arduino
Ethernet Shield and other devices such as LCD display shield and RTC (Real Time Clock).

https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 1/31
2/27/2018 Attendance Record System – Tutorial by Cytron

1.1 Feature
The objective of this tutorial is to build an example of standalone attendance record system.

Below are the features of the system:

built using Arduino Mega 2560 main board


utilizes SM630 fingerprint module for fingerprint scanning purpose and extra storage.
utilizes embedded microSD slot on Ethernet Shield to store attendance information which
can be easily accessed by user.
includes LCD Keypad shield that displays time and attendance information.It also contains
5 buttons (not including reset button) in which the user can use them as navigation buttons.
includes RTC module to store real date and clock time information.
includes other device such as buzzer as indicator.

2.0 Getting Started


2.1 Components
The components you need:

1 x Arduino Mega 2560 R3-Main Board


1 x Fingerprint Reader Integrated SM630
1 x LCD keypad Shield
1 x DS3231 RTC Module
1 x Ethernet Shield V2.0
1 x micro SD card, you can get it from any computer store.
1 x Cytron Prototyping Shield (for buzzer, UART and power system)
1 x 12V-2A DC adaptor

Electronic components:

Indicator:

1 x Buzzer-PCB Mount
https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 2/31
2/27/2018 Attendance Record System – Tutorial by Cytron

Fingerprint module UART connection:

2600 PCB Connector Header (R/A) 4 Ways

Power System:

1 x diode 1N5822
1 x 25V 220uF cap
1 x 25V 10uF cap
2 x 0.1uF cap
1 x LM7805 voltage regulator
1 x transistor TIP42C
1 x 3R3 resistor
1 x HL2527 DC Plug
connecting wires

RTC Module System:

1 x Arduino Type Header pin

2.2 Basic Connection:


The system is built by stacking up the main board and shields as shown below.

Before stacking up, we need build a circuit consists of all necessary systems on prototyping shield.

https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 3/31
2/27/2018 Attendance Record System – Tutorial by Cytron

2.21 Power System


Primary objective of this power system is to provides 5VDC to be used by Arduino board and other
devices.

For your information, we have been experimenting the built-in power system but it turned out that
current output is not enough for the current project. The use of LCD keypad shield and Ethernet
shield consumes significant amount of current. The external power system is required to provide
additional current.

User can use the sample power system circuit below. This power system can provide up to 8
Amps, and it shouldn’t be a problem to this project.The user can also make their own power
system if it is appropriate.

https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 4/31
2/27/2018 Attendance Record System – Tutorial by Cytron

Note**: JP2 ,F1 and S1 can be ignored.

In the circuit above, we only connect the 5V from Arduino board to the power system output. User
can connect DC plug voltage output to on board Vin for other uses. Ethernet shield has an
embedded 5V to 3V3 DC power system so for those users who want to use 3V3 applications don’t
need to build another one.

2.22 Indicator
In this project, we add a buzzer in the system to indicate the completion of attendance record
process. For example, one beep sound indicates login success and 2 beep sounds means logout. If
there are 3 beep sounds, error occurs such as improper installation of microSD card, unfound
employee fingerprint, etc.

In the circuit, user just needs to connect one leg (longer leg) of buzzer to 5V and another to GND.

User can customize their own indicator systems. User can even include some visual indicatiors like
LEDs.

2.23 Fingerprint Module UART Connection


The figure below shows the connection between the connector and Arduino prototyping shield.

https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 5/31
2/27/2018 Attendance Record System – Tutorial by Cytron

2.24 RTC module


User can either directly solder the module to prototyping shield or solder a 5 pin or 6 pin header
on the shield for easy removal of the module like we did. This RTC module stores current time
information with the power of a coin cell lithium battery.

Note**: Removal of the battery will instantly erase the information stored and reset the time.
Handle with care!

We are going to use 4 pins only :VCC, SCL, SDA and GND. Leave others as not connected.

You can either use jumper wires to connect to the legs of female header pin, or solder 2 wires
onto the board as SDA and SCL wires.

https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 6/31
2/27/2018 Attendance Record System – Tutorial by Cytron

Connect the SDA wire to pin 20 and SCL to pin21. There should labels for you as guidance.

While inserting battery, make sure the side of battery with “+” sign attached to the
surface of coin cell holder with “+” sign.

2.3 Hardware setup


For your information, Ethernet shield and LCD keypad shield share same pins at pin 4 and pin 10.
We are going to do some modification to prevent pin crashes.

Modification 1: Bend the leg of prototyping shield at pin 4 and 10.

https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 7/31
2/27/2018 Attendance Record System – Tutorial by Cytron

It should be something like photo below if you stack prototyping shield onto Ethernet shield.

Modification 2: Connect pin 4 on prototyping shield to pin A3. We are going to use pin A3 as D4
for LCD.

OKAY, now we can proceed to programming stage!

3.0 Programming
Below is the flow diagram sketch of the designed system. The full sketch can be downloaded here.

https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 8/31
2/27/2018 Attendance Record System – Tutorial by Cytron

Basically the programming involves 4 major parts:

fingerprint scanning process and teaching process


information storing and accessing with fingerprint module and micro SD,
time settings and display
menu interface for time setup, fingerprint teaching ,etc.

i) FINGERPRINT SCANNING AND TEACHING

How does SM630 Fingerprint module work? It is using packet data communication. If we
wants the module to carry out some operations, we need to send a string of bytes in serial to the
device as command. After the device receives the data bytes, it will send back a string of bytes
in serial as response. It is our job to do some programming to ‘write’ and ‘read’ these bytes to
determine the outcome of the device.

Generally the communication packet includes the following:

packet head – 2 bytes


packet flag – 1 byte
packet length – 1 byte
packet content – N bytes
checksum – 1 byte

Let say we want to add fingerprint at position(id) 2, what should we send?

https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 9/31
2/27/2018 Attendance Record System – Tutorial by Cytron

packet head : 0x4D and 0x58


packet flag: 0x01 (command)
packet length:adding operation requires 3 data bytes for packet content, thus here we
should put 0x03
packet content: 0x40 (command code as stated in user manual), 0x00(high byte of value
2), 0x02 (low byte of value 2)
checksum : 0xFA (low byte of total sum from packet head to packet content data)

So we should send a string of data bytes {0x4D,0x58,0x01,0x03,0x40,0x00,0x02,0xFA} in serial


to the fingerprint module.

This is just a brief explanation on the working principle of fingerprint module. To know
more details on how to communicate with the module and execute other functions,
user can refer to the SM630 Fingerprint Module User’s Manual.

Below is the sample code of sending command and receive response. This sample code is not
optimized to full functionality. User can play around to add in more functions or modify the
program for the best performance.

//define fingerprint command code


#define ADD_FINGERPRINT 0x40
#define DELETE_FINGERPRINT 0x42
#define SEARCH_FINGERPRINT 0x44
#define EMPTY_DATABASE 0x46
#define MATCHING 0x4B
//define fingerprint response code
#define OP_SUCCESS 0x31
#define TIME_OUT 0x33
#define PROCESS_FAILED 0x34
#define PARAMETER_ERR 0x35
#define MATCH 0x37
#define FP_FOUND 0x39
#define FP_UNFOUND 0x3A

Sending command

Program Program description

void _cmd(byte cmd,int number) byte cmd refers to which


{ command the user wants to
if(number>767) execute.For example: if
{ user wants to add
msg("INVALID ID"); fingerprint, cmd should be
return; 0x40. int number refers to
} fingerprint id(position) in
the module. If the
Serial.begin(57600); command doesn’t require id
number, just put any
byte packet_content; number.
switch(cmd)
{ The command should not
case SEARCH_FINGERPRINT:packet_content=5;break; be sent if id/position is
case EMPTY_DATABASE:packet_content = 1;break; more than 767 (the module
default: packet_content = 3;break; can only store up to the
} 768 fingerprints only), or
https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 10/31
2/27/2018 Attendance Record System – Tutorial by Cytron

else you will receive


byte Hbyte = number/256; parameter error from
byte Lbyte = number%256; device.
byte checksum = 0;
Initialize the serial
byte send_cmd[packet_content+5]; communication at baud rate
for(byte i=0;i<sizeof(send_cmd);i++) 57600 as stated in user
send_cmd[i]=0; manual.

send_cmd[0] = 0x4D; packet_content will be


send_cmd[1] = 0x58; determined by the cmd
send_cmd[2] = 0x10; value you just
send_cmd[3] = packet_content; inserted. Most of the
send_cmd[4] = cmd; command has packet
content length of 3 bytes.
for(byte i=0;i<sizeof(send_cmd);i++) Search fingerprint and
checksum+=send_cmd[i]; empty database are the
exceptions.
if(packet_content>=3)
{ Determine high byte and
send_cmd[5] = Hbyte;send_cmd[6] = Lbyte; low byte of the id number.
checksum+=send_cmd[5];
checksum+=send_cmd[6]; Declare an array of bytes
with variable size to be sent
if(cmd==SEARCH_FINGERPRINT) to module and initialize it.
{
for(byte i=7;i>4;i--) Start putting appropriate
send_cmd[i+2]=send_cmd[i]; values to the array. 0x4D as
first byte, 0x58 as second
send_cmd[5] = 0;send_cmd[6] = 0; byte and so forth. Please
checksum+=send_cmd[5]; refer to fingerprint module
checksum+=send_cmd[6]; user manual to verify the
} correctness of packet data.
}
Calculate the checksum for
send_cmd[packet_content+5-1]=checksum; first time.

Serial.write(send_cmd,sizeof(send_cmd)); If the packet content length


delay(1); equal or more than 3 bytes,
} add high byte of number as
5th byte and low byte as
6th byte. Calculate the
checksum. Take note that
commands with packet
content length less than 3
bytes will not go through
this part.

If the command is search


fingerprint command, shift
value from 5th byte to 7th
byte and 6th byte to 8th
byte. Now 5th byte and 6th
byte should be replaced
with high byte and low byte
of a number respectively
where this number is the
number that module will
https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 11/31
2/27/2018 Attendance Record System – Tutorial by Cytron

start searching from. Here


we put 0 in both bytes, thus
searching will start from 0.
Recalculate the checksum.

Put the value of final


checksum as last byte.

Send this string of bytes to


the module. Give some
delays.
Receiving response

Program Program description

boolean _respond(byte cmd) byte cmd  refers to the


{ previous command the user
boolean end_flag = false; sends to module.
boolean success = false;
byte addfp_count = 0; Initialize some variables
while(!end_flag) end_flag – determines when
{ this function should
int packet_length = 9; terminate
byte resp_temp[packet_length];
for(byte j=0;j<packet_length;j++) success – determines
{ whether the operation
performs successfully
while(Serial.available()==0)
{ addfp_count – this variable is
//you can add something here made for adding fingerprint
} process. Adding fingerprint
resp_temp[j]=Serial.read(); process requires 2 responses
if(j==3) packet_length = resp_temp[3]+5; to be successful.
addfp_count determines
} when the function ends.
switch(resp_temp[5])
{ Create a temporary array for
case OP_SUCCESS: received packets. Initialise
if(cmd==SEARCH_FINGERPRINT) the array with the size of 9.
//add something here
else if(cmd==ADD_FINGERPRINT) Read and store the received
{ bytes. When 4th byte is read,
//add something here total data packet length is
addfp_count++; determined.
}
else if(cmd==DELETE_FINGERPRINT) Determine high byte and low
{ byte of the id number.
//add something here
end_flag = true; Declare an array of bytes
success = true; with variable size to be sent
} to module and initialize it.
else if(cmd==EMPTY_DATABASE)
{ In attendance system, search
//add something here fingerprint command is
end_flag = true; constantly sent to module. If
success = true; there is no finger on screen
} within about 10 secs, time
https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 12/31
2/27/2018
} Attendance Record System – Tutorial by Cytron

break; out response will be


received. Before this
case TIME_OUT: response is received, the
//add something here program will continue in this
end_flag=true; loop(red highlighted). And
break; also once the command is
sent, fingerprint module will
case PROCESS_FAILED: not receive any other
//add something here commands and do anything
until the response for the
end_flag=true; current command is given
break; out. Therefore user can put
in some functions like time
case PARAMETER_ERR: display.
//add something here
end_flag=true; Check the 6th byte of
break; received data and carry out
functions according to
case MATCH: response code
//add something here
success = true;
end_flag=true; //add something here is the
place where you can put your
break; own functions like light up
LED, make beep sound from
case NO_MATCH: buzzer or display words on
// add something here LCD
end_flag=true;
break; this function is boolean/bool
type, which returns value of
case FP_FOUND: success. User may modify the
//add something here function to any appropriate
Shares worker_id = response[6]*256+response[7]; types and return something
end_flag=true; in which user think is useful
success = true; for next operation. User may
break; change to void type to return
nothing.
case FP_UNFOUND:
//add something here If search fingerprint is
end_flag=true; successful, 6th and 7th bytes
break; will be the id number that
} module returns for
corresponding fingerprint.
if(cmd==byte(ADD_FINGERPRINT)&&addfp_count>1) User may want to define a
{ variable to store the number.
//add something here In this tutorial, we declare a
success = true; global variable worker_id to
end_flag=true; store the number.
}

}
Serial.end();
return success;
}
Fingerprint Searching

These 2 functions allows user to carry out fingerprint searching and teaching process. If user
wants to start searching process, user can write the following lines in the program.

https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 13/31
2/27/2018 Attendance Record System – Tutorial by Cytron

_cmd (SEARCH_FINGERPRINT,100);
_respond(SEARCH_FINGERPRINT);

These lines send a command to the module to search for matching fingerprint designated from id
0 to 100 and gives appropriate response.

Fingerprint Teaching

For fingerprint teaching process like adding fingerprint, user may write the following codes

int id = 10;
_cmd (ADD_FINGERPRINT,id);
_respond(ADD_FINGERPRINT);

The codes above allows user to add fingerprint with id 10 if the response indicates the process is
successful. You can check the response from _respond function. You can also write a program to
select a value for int id so you can add fingerprint with any id number less than 768. You can
utilise the navigation buttons on LCD keypad shield to do so.

The code for deleting fingerprint is almost similar to adding fingerprint:

int id = 10;
_cmd (DELETE_FINGERPRINT,id);
_respond(DELETE_FINGERPRINT);

The codes above allows user to delete fingerprint with id 10 if the process is successful.

ii) INFORMATION STORING AND ACCESSING

Write and read info using SM630 fingerprint module

SM630 fingerprint module has 64K bytes user flash memory to store necessary information. It can
serve as extra storage if user knows how to utilise this function. Below are the sample codes on
how to write strings data into fingerprint flash memory and read data from it.

Write/store strings to flash

Program Program description

void wrFlash(int id,int type,String data2wr) This function is


{ customized and int id
Serial.begin(57600); and type are used to
char data[data2wr.length()+1]; determine the address
data2wr.toCharArray(data,data2wr.length()+1); for the data to be
stored. User can
if(sizeof(data)>128) {msg("too big");return;} modify these 2
parameters.
byte wr_data[sizeof(data)+9];
byte checksum = 0; Initialise the serial
byte i; communication and
convert string to char
wr_data[0] = 0x4D; array.
wr_data[1] = 0x58;
wr_data[2] = 0x10; According to user
wr_data[3] = 4 + sizeof(data); manual, only 128 bytes
wr_data[4] = 0x64; are allowed to be
wr_data[5] = ((id-1)*ADDR + type)/256; written at one time.
wr_data[6] = ((id-1)*ADDR + type)%256;
https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 14/31
2/27/2018
[ ] (( ) yp )Attendance Record System – Tutorial by Cytron
wr_data[7] = sizeof(data); Initialise an array to
store the bytes to be
for(i = 0;i<sizeof(data);i++) wr_data[i+8] = data[i]; sent to the module and
put necessary values
for(i=0;i<(sizeof(wr_data)-1);i++) checksum+= wr_data[i]; to each byte.

wr_data[sizeof(wr_data)-1] = checksum; wr_data[5] refers to


the high byte of
Serial.write(wr_data,sizeof(wr_data)); address and
delay(1); wr_data[6] refers to
low byte of address.
char rx[6]; User may modify these
while(Serial.available()==0){} 2 lines.
Serial.readBytes(rx,6);
send the data bytes to
if(rx[3]==0x01&&rx[4]==0x02) module and waiting for
{ response.
//do something here if receive packet error
return; First response is to
} check whether it is
packet error or not.
char ops_[7];
while(Serial.available()==0){} Second response is to
Serial.readBytes(ops_,7); check whether writing
data to memory is
if(ops_[5]!=OP_SUCCESS) successful or not.
{
//do something here if storing data not successful Take note**: 1
return; address only stores 1
} byte of data. Let say
Serial.end(); you want to store
“Cytron” string, 7
} consecutive addresses
are needed (including
null character). In this
function you only have
to send the starting
address to the module.
If you want to store
multiple data, consider
to plan the address
properly or else you
will find the data
overlapped.
Read data from flash

Program Program description

char* rdFlash(int id,int type,byte num) This function is customized and int id
{ and type are used to determine the
Serial.begin(57600); starting address for the data to be
if(num>128) {msg("too big");return 0;} read. User can modify these 2
parameters. byte num refers to the
byte rd_data[9]; length of data you want to read.
byte checksum = 0;
byte i; Initialise the serial communication.
Same as before, only 128 bytes are
https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 15/31
2/27/2018 Attendance Record System – Tutorial by Cytron
y y
allowed to be read at one time.
rd_data[0] = 0x4D;
rd_data[1] = 0x58; Initialise an array to store the bytes to
rd_data[2] = 0x10; be sent to the module and put
rd_data[3] = 0x04; necessary values to each byte to
rd_data[4] = 0x62; initiate reading data from module.
rd_data[5] = ((id-1)*ADDR + type)/256;
rd_data[6] = ((id-1)*ADDR + type)%256; rd_data[5] refers to the high byte of
rd_data[7] = num; address and rd_data[6] refers to low
for(i=0;i<8;i++) checksum+= rd_data[i]; byte of address. User may modify
these 2 lines.
rd_data[8] = checksum;
Serial.write(rd_data,sizeof(rd_data)); send the data bytes to module and
delay(1); waiting for response.
char rx[6];
while(Serial.available()==0){} First response is to check whether it is
packet error or not.
Serial.readBytes(rx,6);

if(rx[3]==0x01&&rx[4]==0x02) Second response from module contains


{ the data bytes the user requests from
//do something here if receive packet error address. User can create a variable to
return 0; store these data bytes. Here we
declare function as char array type and
} will return the data if the function
ends. User can modify the function
char ops_[6+num]; type to suit their application.
while(Serial.available()==0){}
Serial.readBytes(ops_,sizeof(ops_));
Note**: the only thing you have to
care about is the num value. Make
char dat[num]; sure that you know the size of the data
for(i=0;i<num;i++) dat[i] = ops_[i+5]; you want to read. Let say you want to
read “Ahmad” from module you can
Serial.end(); set num = 8, 6 for the data(including
return dat; null terminator) and 2 for extra length.
}
Write and read info using micro SD

There are a few things you have to do before you proceed.

First you have to make sure pin 4 and pin 10 from Ethernet Shield is not connected with the
same pins of LCD Keypad Shield. If you haven’t modified and disconnected these pins, you may
refer to the instructions shown in 2.3 Hardware Setup.

Second, please include the latest SD library in your Arduino library directory. The file can be found
and downloaded at the end of this tutorial. In this tutorial we are using this library.

Below are the sample codes for accessing,writing and reading data from micro SD.

#include <SdFat.h>
#define chipSelect 4  //CS pin for microSD
Sd2Card card;
SdVolume vol;
SdFat sd;

Checking micro SD condition

Program Program
https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 16/31
2/27/2018 Attendance Record System – Tutorial by Cytron

description

This
function is
to check
SD card
condition
and returns
true value
if card is
detected.

card.init is
to initialise
the card
and vol.init
is to
initialise
the
boolean checkSDCard() accessing
{ volume of
boolean SDCard_status = card.init(SPI_HALF_SPEED,chipSelect); the card.
if (!SDCard_status||!vol.init(&card)) Both
{ functions
//do something here if card is not detected returns
} true if the
process is
uint32_t volumesize= vol.blocksPerCluster()*vol.clusterCount()*512; completed.
uint32_t freespace = 512*vol.freeClusterCount()*vol.blocksPerCluster(); It is
advisable
//check free space available to check
if(freespace==0) these 2
//do something here if memory is full functions
else if(freespace<0.1*volumesize) to see
//do something here if memory is nearly full whether
the card is
detected or
return true; not.
}
In this
function,
calculation
of total
volume
size and
free space
available is
included.
User can
use this to
check the
availability
of the card
to store
data.
Write/Store data to microSD

https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 17/31
2/27/2018 Attendance Record System – Tutorial by Cytron

This is the example on how we store employee’s login and logout information in our company.
User may modify it to suit their application.

Program Program description

void record(String dataString) This function is to store


{ strings to a file in microSD.
// do something here to indicate recording/storing String dataString is the
char filename[fileName.length()+1]; employee’s login and logout
fileName.toCharArray(filename,fileName.length()+1); string info ready to be
stored.
//checking card condition
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) Highlighted lines are the
{ codes to convert string to
if(!checkSDCard()) const char* type. This string
{ is the target filename.
// do something if card failed
} If the file doesn’t exist,
} create a new one. Function
dateTimeCallback(dateTime)
boolean title=false; is to detemine the time
if(!sd.exists(filename)) title = true; when the file is created, so
that when user is accessing
// create or open file the file using computer or
SdFile dataFile; other devices, he or she can
if(title==true) see the proper created time
and date for the file. If this
{ function is not called, the
SdFile::dateTimeCallback(dateTime); date will be incorrect. This
dataFile.open(filename,O_WRITE| O_CREAT| O_APPEND); function is only working
dataFile.println("Date,Time,Worker ID,Status,Remark,"); with the installation of
dataFile.close(); RTC_module.
title = false;
} O_WRITE only in file open
will cause the data in
else dataFile.open(filename, O_WRITE| O_APPEND); existing file to be
overwritten. To store data
// if the file isn't open, pop up an error: without overwritting the
if (!dataFile.isOpen()) existing data, use
{ O_WRITE|O_APPEND
// do something if file cannot be opened instead.
}
else
{// if the file is available, write to it:
dataFile.println(dataString);
dataFile.close();
}
Read file from microSD

Program Program description

void rdAdmin() This function is to read


{ employees’ info from a
SdFile dataFile; file named “admin.csv” in
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) microSD.
{
https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 18/31
2/27/2018 Attendance Record System – Tutorial by Cytron

if(!checkSDCard()) dataFile.read() reads


{ character by character. If
//do something here if card failed no data can’t be read(at
} the end of file), data will
} be < 0.
if (!dataFile.open("admin.csv", O_READ))
{ This function also
//do something here if file not opened implements wrFlash
} function. The data read
char data; will be stored in
String worker_data[5]; fingerprint module flash
int count = 0; memory.
boolean title_flag = true;
int line_count = 0; An temporary array with
size 5 is declared to store
while ((data = dataFile.read()) >= 0) worker’s data, one for
{ one type (although only
if(data!=','&&int(data)!=13&&int(data)!=10) 3 types to be stored).
worker_data[count]+=String(data);
else if(data==',') count++; The file read is in CSV
else if(int(data)==13) //if read data jumps to next line format (comma
{ separated), thus this
dataFile.read(); algorithm uses comma to
if(line_count>0) separate read data and
{ store into different array.
wrFlash((worker_data[0].toInt()),ID,worker_data[0]);
wrFlash((worker_data[0].toInt()),NAME,worker_data[1]); If next line is reached,
wrFlash((worker_data[0].toInt()),POS,worker_data[2]); the arrays are reset so
} that new data can be
line_count++; stored. next line will be
count = 0; indicated by int data
memset(worker_data,0,sizeof(worker_data)); 13(carriage return)and
} 10(new line feed). User
can refer to ASCII code
} table.
dataFile.close();
} There is also a SD library
function call fgets()
which reads line by line.
In this project some of
the functions implement
this. User can have a
guide.
iii) TIME SETTINGS AND DISPLAY

Include the libraries below in your program. DS3231 RTC module is almost similar to DS1307 RTC
and both chip are I2C devices and have the same working principle. Thus DS1307 library can be
used for this project. Wire.h is for I2C configuration, LiquidCrystal.h is for LCD display and
LCD_Key.h is for LCD Keypad button.
#include <Time.h>
#include <DS1307RTC.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#include <LCD_Key.h>
//define keycode
#define None 0
https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 19/31
2/27/2018 Attendance Record System – Tutorial by Cytron

#define Select 1
#define Left 2
#define Up 3
#define Down 4
#define Right 5
LiquidCrystal lcd(8, 9, A3, 5, 6, 7);
LCD_Key keypad;

Setup - Sync the system time with RTC


void setup()
{
.....................//
lcd.begin(16,2);
Wire.begin();
setSyncProvider(RTC.get);
//....................
}

Remember to include setSyncProvider(RTC.get) in void setup() to synchronize the system time

Current Time Display

Program Program description

void Time_Display() This function is to display the current


{ time on LCD display. This function
lcd.setCursor(0,1); implements LCD display function
which is from LiquidCrystal.h library.
lcd.print(Wday[weekday()-1]);lcd.print(" ");
lcd.setCursor(0,0); Available function from Time.h
library:
printDigits(day()); year() – returns the value of
lcd.print("-"); current year
printDigits(month()); month() – returns the value of
lcd.print("-"); current month
printDigits(year()%100);
day() – returns the value of
lcd.setCursor(11,0); current day
printDigits(hourFormat12()); weekday() – returns the value of
lcd.print(":"); current week day
printDigits(minute()); e.g. Sunday – 0, Monday – 1,
//lcd.print(":");lcd.print(second()); etc.
hour() – returns the value of
lcd.setCursor(14,1); current hour in 24 format
if(isAM()==1){ hourFormat12() – returns value
lcd.print("AM"); of current hour in 12 format
} isAM() – returns true if it is AM
isPM() – returns true is it is PM
else{ minute() – returns the value of
lcd.print("PM"); current minute
}
second()- returns the value of
} current second

https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 20/31
2/27/2018 Attendance Record System – Tutorial by Cytron

printDigits() function converts


void printDigits(int digits) number into 2 digits display.
{
if(digits < 10) User can even display the specific
lcd.print('0'); details of past time or future time.
lcd.print(digits); For example:
}
time_t tim = now()+3600; //3600 seconds

printDigits(hour(tim));

User will find that the display time will be


1 hour past the current time.

Time Change Settings

Program Program d

void setup_Time() This


{ change
byte lcd_hpos[7]={0,3,6,11,14,14}; curren
byte lcd_vpos[7]={0,0,0,0,0,1}; the
int lcd_pos = 0; module
implem
int cur_time=millis(); functio
int prev_time=millis(); naviga
boolean display_stat; LCD_K
boolean time_update = 0;
int localKey; In thi
and r
Time_Display(); used
while(1) specific
{ month
int sec_update = second(); and A
int min_update = minute(); down
int hour_update = hour(); to cha
int day_update = day(); Select
int month_update = month(); update
int year_update = year(); RTC m
localKey = keypad.getKey();
Highlig
cur_time = millis(); blink t
if(cur_time-prev_time>400) curren
{ change
display_stat = !display_stat; indicat
prev_time = cur_time; pb_del
} set. H
200;
if(display_stat==true)
{
lcd.setCursor(lcd_hpos[lcd_pos],lcd_vpos[lcd_pos]);
lcd.print(" ");
}
https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 21/31
2/27/2018 Attendance Record System – Tutorial by Cytron

else
{
Time_Display();
}

if(localKey==Select)
{
if(time_update==true)
setTime(hour(),minute(),0,day(),month(),year());
RTC.set(now());
msg("UPDATING TIME");
}

else if(localKey==Left)
{
if(--lcd_pos<0) lcd_pos = 5;
delay(pb_delay);
}

else if(localKey==Right)
{
if(++lcd_pos>5) lcd_pos = 0;
delay(pb_delay);
}

else if(localKey==Up)
{
switch(lcd_pos)
{
case 0: day_update++; if(day_update>31) day_update=1;break;
case 1: month_update++; if(month_update>12) month_update =1;break;
case 2: year_update++; if(year_update>2100) year_update = 2013;break;
case 3: hour_update++;
if(isAM()==1){if(hour_update>11) hour_update =0;}
else if(isPM()==1){if(hour_update>23) hour_update =12;}
time_update = 1;break;
case 4: min_update++;if(min_update>59) min_update =0;
time_update = 1;break;
case 5: if(isAM()==1)hour_update+=12;else hour_update-=12;break;
}
setTime(hour_update,min_update,sec_update,day_update,
month_update,year_update);
Time_Display();
delay(pb_delay);
}

else if(localKey==Down)
{
switch(lcd_pos)
{
case 0: day_update--;if(day_update<1) day_update = 31;break;
case 1: month_update--;if(month_update<1) month_update = 12;break;
case 2: year_update--; if(year_update<2013) year_update = 2013;break;
case 3: hour_update--;
if(isAM()==1){if(hour_update<0) hour_update =11;}
else if(isPM()==1) {if(hour_update<12) hour_update =23;}
time_update = 1;break;
https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 22/31
2/27/2018 Attendance Record System – Tutorial by Cytron

case 4: min_update--;if(min_update<0) min_update =59;time_update = 1;break;


case 5: if(isAM()==1) hour_update+=12; else hour_update-=12;break;
}
setTime(hour_update,min_update,second(),day_update,
month_update,year_update);
Time_Display();
delay(pb_delay);
}
}
}

iv) MENU INTERFACE

In this project we also create a menu interface for fingerprint teaching process and time setup and
Below is the sample code of a simple interface.

Program Program description

//global variables for admin menu and interface To use this interfa
byte choice[2]; user just need to kn
byte page_no; how many options th
needed to be created
void admin() the menu. Let say if
{ options are neede
int category = 0; change the value
int page = 0; page_no in vo
int localKey; selection() to
Page_no determin
how many options y
selection(category,page);// display first page want to set in t
while(1) menu.
{
if(reset_)
{ In void menu(), it is
user to design the pa
category-=1; for each menu optio
page = choice[category]; The most common w
selection(category,page); is to display the title
reset_=false; the menu.
}
localKey = keypad.getKey(); In void selectio
under case 1, user c
switch(localKey) add extra functions th
{ dedicated
case Left: page--; choice[category], l
if(page<0) page = 0; “else
else if(page>page_no-1) page = page_no-1; if(choice[category]==
selection(category,page); {delay(pb_delay);//ad
delay(200); function here
break; choice[category] is t
menu option y
case Right: page++; selected, if you choo
if(page<0) page = 0; first menu optio
else if(page>page_no-1) page = page_no-1; choice[category] will
selection(category,page); 0, then you can execu
delay(200); whatever function y
want in this menu.
https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 23/31
2/27/2018 Attendance Record System – Tutorial by Cytron

break;

case Select:
choice[++category] = page;
choice[category-1] = choice[category];
lcd.clear();
selection(category,page);
delay(200);
break;

case Up: category--;


if(category<0)
{
lcd.clear();
return;
}
else
page = choice[category];
lcd.clear();
selection(category,page);
delay(200);
break;
}
}
}
void selection(int category,int page){
switch(category)
{
case 0:
page_no = 5;//set pages for first category
menu(page);
break;

case 1:
if(choice[category]==0){delay(pb_delay);//add function here}
else if(choice[category]==1){delay(pb_delay);//add function here}
else if(choice[category]==2){delay(pb_delay);//add function here}
else if(choice[category]==3){delay(pb_delay);//add function here}
else if(choice[category]==4){delay(pb_delay);//add function here}
//user can add more function here
reset_ = true;
break;
}
}
void menu(int page){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Menu ");
lcd.print(page+1);lcd.print(":");
switch(page)
{
case 0: //customise first page// break;
case 1: //customise second page// break;
case 2: //customise third page// break;
case 3: //customise forth page// break;
case 4: //customise fifth page// break;
//user can add more here
https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 24/31
2/27/2018 Attendance Record System – Tutorial by Cytron

}
}

All the codes above are just part of the full source code and are taken as guidance for user to learn

4.0 Nearly finish...

After you have finished programming and everything else, just plug in DC adapter (to DC plug you

If you are not sure whether the power system works, just use multimeter to measure the voltage a

If everything is on, you are not done yet. Fingerprint and RTC module are new and you need to do

Fingerprint module now is free of data (except for its own ID and logo). You can teach it to read an

If you are interested, you can make a container for the system. Nicer look and more 'professional'!

Now your attendance system is ready to serve!!!

5.0 Precautions
After you run the system for a while, you will find that the power system is quite warm. Don't worr

That's all! Hope you can enjoy it to develop your own attendance record system. There

Attachment:
- Attendance System

BUY

https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 25/31
2/27/2018 Attendance Record System – Tutorial by Cytron

 Fingerprint Reader

 SHIELD-LCD

 RTC Module

 Ethernet Shield

 Prototyping Shield

https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 26/31
2/27/2018 Attendance Record System – Tutorial by Cytron

 Arduino Mega

Arduino Attendance Fingerprint Real Time clock SM630

      

BENGCHET / ABOUT AUTHOR

 More posts by bengchet

 
 RELATED POSTS

PROJECT 8 – ANALOG DISTANCE How to Make your Line Following Meth


SENSOR TO LCD DISPLAY Robot Faster? and
Analog distance sensor, which are Introduction Introducing Line  Sens
13 Aug 2011  1 13 Oct 2016  5 11 Au

https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 27/31
2/27/2018 Attendance Record System – Tutorial by Cytron

 COMMENTS (12)

HANI
November 28, 2013 at 3:55 pm

hye! im doing the same project for my class subject project.


i had set up the same things but not using buzzer and ethernet and RTC ds1307. can i use the
same coding here? i have compiled but there are some errors

attsys:72: error: ‘Time_t’ was not declared in this scope


attsys:62: error: ‘LCD_Key’ does not name a type
attsys:67: error: ‘SdFat’ does not name a type
attsys:70: error: ‘LCD_Key’ does not name a type
attsys.ino: In function ‘void setup()’:
attsys:105: error: ‘RTC’ was not declared in this scope
attsys:105: error: ‘setSyncProvider’ was not declared in this scope
attsys:108: error: ‘now’ was not declared in this scope
attsys:111: error: ‘month’ was not declared in this scope
attsys:112: error: ‘year’ was not declared in this scope
attsys.ino: In function ‘void loop()’:
attsys:117: error: ‘keypad’ was not declared in this scope
attsys.ino: In function ‘boolean _respond(byte)’:
attsys:210: error: ‘keypad’ was not declared in this scope
attsys.ino: In function ‘void attendance()’:
attsys:430: error: ‘worker_stat’ was not declared in this scope
attsys:432: error: ‘now’ was not declared in this scope
attsys.ino: In function ‘void Time_Display()’:
attsys:448: error: ‘weekday’ was not declared in this scope
attsys:452: error: ‘day’ was not declared in this scope
attsys:454: error: ‘month’ was not declared in this scope
attsys:456: error: ‘year’ was not declared in this scope
attsys:460: error: ‘hourFormat12’ was not declared in this scope
attsys:462: error: ‘minute’ was not declared in this scope
attsys:467: error: ‘isAM’ was not declared in this scope
attsys.ino: In function ‘void setup_Time()’:
attsys:500: error: ‘second’ was not declared in this scope
attsys:501: error: ‘minute’ was not declared in this scope
attsys:502: error: ‘hour’ was not declared in this scope
attsys:503: error: ‘day’ was not declared in this scope
attsys:504: error: ‘month’ was not declared in this scope
attsys:505: error: ‘year’ was not declared in this scope
attsys:507: error: ‘keypad’ was not declared in this scope
attsys:528: error: ‘setTime’ was not declared in this scope
attsys:529: error: ‘RTC’ was not declared in this scope
attsys:529: error: ‘now’ was not declared in this scope
attsys:555: error: ‘isAM’ was not declared in this scope
attsys:556: error: ‘isPM’ was not declared in this scope
attsys:560: error: ‘isAM’ was not declared in this scope
attsys:563: error: ‘setTime’ was not declared in this scope
attsys:576: error: ‘isAM’ was not declared in this scope
attsys:577: error: ‘isPM’ was not declared in this scope
attsys:580: error: ‘isAM’ was not declared in this scope
attsys:583: error: ‘setTime’ was not declared in this scope
attsys.ino: At global scope:
https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 28/31
2/27/2018 Attendance Record System – Tutorial by Cytron
y g p
attsys:591: error: redefinition of ‘String showTime’
attsys:72: error: ‘String showTime’ previously declared here
attsys:591: error: ‘Time_t’ was not declared in this scope
attsys.ino: In function ‘void record(String)’:
attsys:624: error: ‘sd’ was not declared in this scope
attsys:634: error: ‘sd’ was not declared in this scope
attsys:642: error: no matching function for call to ‘SdFile::open(char [(((unsigned int)
((int)fileName.String::length())) + 1)], int)’
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:223: note: candidates are: uint8_t
SdFile::open(SdFile*, uint16_t, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:224: note: uint8_t
SdFile::open(SdFile*, const char*, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:331: note: uint8_t
SdFile::open(SdFile&, const char*, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:335: note: uint8_t
SdFile::open(SdFile&, const char*)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:341: note: uint8_t
SdFile::open(SdFile&, uint16_t, uint8_t)
attsys:647: error: no matching function for call to ‘SdFile::open(char [(((unsigned int)
((int)fileName.String::length())) + 1)], int)’
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:223: note: candidates are: uint8_t
SdFile::open(SdFile*, uint16_t, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:224: note: uint8_t
SdFile::open(SdFile*, const char*, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:331: note: uint8_t
SdFile::open(SdFile&, const char*, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:335: note: uint8_t
SdFile::open(SdFile&, const char*)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:341: note: uint8_t
SdFile::open(SdFile&, uint16_t, uint8_t)
attsys:670: error: ‘worker_stat’ was not declared in this scope
attsys.ino: In function ‘void wr_log(boolean)’:
attsys:681: error: ‘sd’ was not declared in this scope
attsys:691: error: ‘sd’ was not declared in this scope
attsys:699: error: no matching function for call to ‘SdFile::open(const char [8], int)’
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:223: note: candidates are: uint8_t
SdFile::open(SdFile*, uint16_t, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:224: note: uint8_t
SdFile::open(SdFile*, const char*, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:331: note: uint8_t
SdFile::open(SdFile&, const char*, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:335: note: uint8_t
SdFile::open(SdFile&, const char*)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:341: note: uint8_t
SdFile::open(SdFile&, uint16_t, uint8_t)
attsys:708: error: no matching function for call to ‘SdFile::open(const char [8], const
uint8_t&)’
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:223: note: candidates are: uint8_t
SdFile::open(SdFile*, uint16_t, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:224: note: uint8_t
SdFile::open(SdFile*, const char*, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:331: note: uint8_t
SdFile::open(SdFile&, const char*, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:335: note: uint8_t
SdFile::open(SdFile&, const char*)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:341: note: uint8_t
SdFile::open(SdFile&, uint16_t, uint8_t)
attsys:725: error: ‘class SdFile’ has no member named ‘fgets’
attsys:733: error: ‘now’ was not declared in this scope
attsys:738: error: ‘now’ was not declared in this scope
attsys.ino: In function ‘char* rd_log(boolean)’:
https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 29/31
2/27/2018 Attendance Record System – Tutorial by Cytron

attsys:755: error: ‘sd’ was not declared in this scope


attsys:766: error: no matching function for call to ‘SdFile::open(const char [8], const
uint8_t&)’
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:223: note: candidates are: uint8_t
SdFile::open(SdFile*, uint16_t, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:224: note: uint8_t
SdFile::open(SdFile*, const char*, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:331: note: uint8_t
SdFile::open(SdFile&, const char*, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:335: note: uint8_t
SdFile::open(SdFile&, const char*)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:341: note: uint8_t
SdFile::open(SdFile&, uint16_t, uint8_t)
attsys:779: error: ‘class SdFile’ has no member named ‘fgets’
attsys.ino: In function ‘void rdAdmin()’:
attsys:799: error: ‘sd’ was not declared in this scope
attsys:808: error: no matching function for call to ‘SdFile::open(const char [10], const
uint8_t&)’
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:223: note: candidates are: uint8_t
SdFile::open(SdFile*, uint16_t, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:224: note: uint8_t
SdFile::open(SdFile*, const char*, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:331: note: uint8_t
SdFile::open(SdFile&, const char*, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:335: note: uint8_t
SdFile::open(SdFile&, const char*)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:341: note: uint8_t
SdFile::open(SdFile&, uint16_t, uint8_t)
attsys:808: error: no matching function for call to ‘SdFile::open(const char [12], const
uint8_t&)’
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:223: note: candidates are: uint8_t
SdFile::open(SdFile*, uint16_t, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:224: note: uint8_t
SdFile::open(SdFile*, const char*, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:331: note: uint8_t
SdFile::open(SdFile&, const char*, uint8_t)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:335: note: uint8_t
SdFile::open(SdFile&, const char*)
C:\Program Files (x86)\Arduino\libraries\SD/utility/SdFat.h:341: note: uint8_t
SdFile::open(SdFile&, uint16_t, uint8_t)
attsys.ino: In function ‘boolean checkSDCard()’:
attsys:855: error: ‘class SdVolume’ has no member named ‘freeClusterCount’
attsys.ino: In function ‘void dateTime(uint16_t*, uint16_t*)’:
attsys:867: error: ‘year’ was not declared in this scope
attsys:867: error: ‘month’ was not declared in this scope
attsys:867: error: ‘day’ was not declared in this scope
attsys:869: error: ‘hour’ was not declared in this scope
attsys:869: error: ‘minute’ was not declared in this scope
attsys:869: error: ‘second’ was not declared in this scope
attsys.ino: In function ‘void admin()’:
attsys:893: error: ‘keypad’ was not declared in this scope
attsys.ino: In function ‘void add_fprint()’:
attsys:992: error: ‘keypad’ was not declared in this scope
attsys.ino: In function ‘void del_fprint()’:
attsys:1097: error: ‘keypad’ was not declared in this scope
attsys.ino: In function ‘void empty_database()’:
attsys:1155: error: ‘keypad’ was not declared in this scope
attsys.ino: In function ‘boolean password_check()’:
attsys:1232: error: ‘keypad’ was not declared in this scope

can you help me? thanks!


https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 30/31
2/27/2018 Attendance Record System – Tutorial by Cytron

SALEH
February 28, 2014 at 5:34 am

how to retrieve the fingers IDs and it’s time to be used in other application on PC

MANUAKKU
September 11, 2014 at 2:30 pm

i’m using arduino due and finger print module FPS_GT511C3,,can i use this code.what else i
have to do?

SHAILESH KUKANA
September 15, 2014 at 4:45 pm

Shall we complete same project and some modification in the code with AT89S51

IRFAN JUNAID
February 7, 2015 at 11:04 pm

Can someone help with these kindly???

Read flash
Write flash

https://tutorial.cytron.io/2013/09/02/attendance-record-system/ 31/31

You might also like