#include <SPI.h>
#include <EEPROM.h>
#include <MFRC522.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#define motionSensor 6
#define buzzer 7
#define pushButtonGreen 8
#define pushButtonPurple 9
#define ledGreen 10
#define ledRed 11
// SPI
#define RST_PIN 5
#define SS_PIN 53
MFRC522 mfrc522(SS_PIN, RST_PIN);
byte readCard[4];
String MasterTag = "EBEE4BC";
String tagID = "";
String nameID = "";
// States
enum State { WAITING, DETECTING, GRANTED, DENIED, TIMEOUT, ADD, DELETE };
State state = WAITING;
unsigned long previousMillis = 0;
const long interval = 1000;
int time = 0;
bool deniedValue = false;
// alarm utils
long long alarmLastRead = millis();
long long alarmInterval = 200;
int alarmTone = 0;
int alarmTones[] = {622, 587, 554};
// rfid - related vars
int items_counter = 0;
int lookup_table_ini_pos = EEPROM.length() - 256;
int REG_SIZE = 16;
int REGID_SIZE = 7;
void setup() {
lcd.init();
lcd.backlight();
SPI.begin();
mfrc522.PCD_Init();
pinMode(motionSensor, INPUT);
pinMode(buzzer, OUTPUT);
pinMode(pushButtonGreen, INPUT);
pinMode(pushButtonPurple, INPUT);
pinMode(ledGreen, OUTPUT);
pinMode(ledRed, OUTPUT);
Serial.begin(9600);
while(!Serial);
// clean eeprom-card-registers lookup table
for (int i = 1; i <= 256; i++)
if (i <= 16)
EEPROM.write( (EEPROM.length() - i) , 1);
else {
EEPROM.write( (EEPROM.length() - i) , 0);
Serial.print((EEPROM.length() - i));
}
}
void loop()
{
handleState();
}
void handleState() {
switch (state) {
case WAITING:
waiting();
break;
case DETECTING:
detecting();
break;
case GRANTED:
granted();
break;
case DENIED:
denied();
break;
case TIMEOUT:
timeout();
break;
case ADD:
add();
break;
case DELETE:
del();
break;
}
}
void waiting() {
if(digitalRead(motionSensor) == HIGH) state = DETECTING;
time = 30;
lcd.clear();
}
void detecting() {
lcd.setCursor(0,0);
lcd.print("Welcome!");
lcd.setCursor(0,1);
lcd.print("Scan card");
/* BEG alarm */
if(deniedValue) {
if (millis() - alarmLastRead > alarmInterval) {
alarmLastRead = millis();
tone(buzzer, alarmTones[alarmTone]);
alarmTone = (alarmTone + 1) % (sizeof(alarmTones)/sizeof(int));
}
}
/* END alarm */
unsigned long currentMillis = millis();
if ((currentMillis - previousMillis >= interval) && time >= -1) {
previousMillis = currentMillis;
time = printTime(time);
}
if (time == -2) state = TIMEOUT;
while (getID()) {
// register new tag
if (digitalRead(pushButtonGreen) == HIGH) {
Serial.print("add new Card: ");
Serial.println(tagID);
state = ADD;
continue;
}
// delete tag
if (digitalRead(pushButtonPurple) == HIGH) {
Serial.print("remove a Card: ");
Serial.println(tagID);
state = DELETE;
continue;
}
// reading and accepting tag
int reg_pos = capture_string_position(tagID);
if (reg_pos != -1) {
noTone(buzzer);
deniedValue = false;
state = GRANTED;
} else
state = DENIED;
}
}
int printTime(int time) {
lcd.setCursor(14, 1);
if(time<10) lcd.print("0");
lcd.print(time);
return --time;
}
void granted() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Access Granted!");
lcd.setCursor(0,1);
lcd.print("CardUID: ");
lcd.print(tagID);
digitalWrite(ledGreen, HIGH);
delay(3000);
digitalWrite(ledGreen, LOW);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Welcome");
lcd.setCursor(0,1);
lcd.print("Name");
lcd.print(nameID);
delay(3000);
lcd.clear();
state = WAITING;
}
void denied() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Access Denied!");
lcd.setCursor(0,1);
lcd.print("CardUID: ");
lcd.print(tagID);
digitalWrite(ledRed, HIGH);
delay(3000);
digitalWrite(ledRed, LOW);
lcd.clear();
deniedValue = true;
time = 30;
state = DETECTING;
}
void timeout() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Potential");
lcd.setCursor(0,1);
lcd.print("Intruder");
lcd.clear();
deniedValue = true;
state = DETECTING;
}
boolean getID() {
if (!mfrc522.PICC_IsNewCardPresent()) return false;
if (!mfrc522.PICC_ReadCardSerial()) return false;
tagID = "";
for(uint8_t i = 0; i < 4; i++) {
//readCard[i] = mfrc522.uid.uidByte[i];
tagID.concat(String(mfrc522.uid.uidByte[i], HEX));
}
tagID.toUpperCase();
mfrc522.PICC_HaltA();
return true;
}
/* BEG funcoes uteis rfid */
String read_name() {
String name = "";
while (name.length() < 9) {
if(Serial.available()){
char data_in = Serial.read();
name += (data_in);
Serial.println(data_in);
}
}
Serial.flush();
return name;
}
String read_string_from_eeprom(int addrOffset, int ssize)
{
char data[ssize + 1];
for (int i = 0; i < ssize; i++)
{
data[i] = EEPROM.read(addrOffset + i);
}
data[ssize] = '\0';
return String(data);
}
int capture_string_position(const String &s) {
for (int i = 0; i <= 240; i++) {
int has_s = EEPROM.read(lookup_table_ini_pos + i);
if (has_s) {
String aux = read_string_from_eeprom(i * REG_SIZE, s.length());
if (aux == s)
return i * REG_SIZE;
}
}
return -1;
}
bool update_items_counter(byte n) {
if (items_counter == 0 && n < 0) {
Serial.println("memory is already empty");
return false;
}
if (items_counter == 240 && n > 0) {
Serial.println("full memory!");
return false;
}
items_counter += n;
return true;
}
int delete_string_from_eeprom(const String &s) {
int s_pos = capture_string_position(s) / REG_SIZE;
if (s_pos == -1) {
Serial.println("item not found");
return s_pos;
}
update_items_counter(-1);
EEPROM.write(lookup_table_ini_pos + s_pos, 0);
return s_pos;
}
int capture_and_use_first_clean_pos() {
for (int i = 0; i <= 240; i++) {
if (EEPROM.read(lookup_table_ini_pos + i) == 0) {
EEPROM.write(lookup_table_ini_pos + i, 1);
return i * REG_SIZE;
}
}
}
void write_string_to_eeprom(const String &strToWrite) {
if (!update_items_counter(1)) {
Serial.println("item cannot be added!");
return;
}
int clean_pos = capture_and_use_first_clean_pos();
for (int i = 0; i < REG_SIZE; i++)
EEPROM.write(clean_pos + i, strToWrite[i]);
}
/* END funcoes uteis rfid */
void add() {
// check if already exists
int tagID_pos = capture_string_position(tagID);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("CardUID: ");
lcd.print(tagID);
lcd.setCursor(0,1);
if (tagID_pos != -1) {
Serial.println("tag already exists, continue to change your username: ");
delete_string_from_eeprom(tagID);
lcd.print("Already Exists!");
} else
lcd.print("Added");
delay(3000);
// read username
lcd.clear();
lcd.setCursor(0,0);
if (tagID_pos != -1)
lcd.print("Update Card's");
else
lcd.print("Insert Card's");
lcd.setCursor(0,1);
lcd.print("username:");
nameID = read_name();
// add tag to registers
write_string_to_eeprom(tagID + nameID);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Card regist.");
lcd.setCursor(0,1);
lcd.print("accepted!");
delay(3000);
state = WAITING;
}
void del() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("CardUID: ");
lcd.print(tagID);
lcd.setCursor(0,1);
lcd.print("to be deleted!");
delay(3000);
// try to delete
int pos = delete_string_from_eeprom(tagID);
// final message
lcd.clear();
lcd.setCursor(0,0);
if (pos != -1) {
// capture username
String reg = read_string_from_eeprom()
nameID = "";
for (int l = REGID_SIZE - 1; l < REG_SIZE; l++)
nameID += reg[l];
lcd.print("Bye bye,");
lcd.setCursor(0,1);
lcd.print(nameID);
} else {
lcd.print("Card Info not");
lcd.setCursor(0,1);
lcd.print("found on mem.");
}
delay(3000);
state = WAITING;
}