/*

-------------------------------------------
Controllo Armadietto con Passepartout Card
-------------------------------------------
Mappa della EEPROM:
00 Flag Passepartout card: AA = Passepartout card definita
01 Flag User card (armadietto occupato anche al reset): AA = User card definita
02-05 Memorizzazione Passepartout card
06-09 Memorizzazione User card
*/
#include <EEPROM.h> // Libreria di gestione EEPROM
#include <SPI.h> // Protocollo SPI
#include <MFRC522.h> // Libreria per il dispositivo Mifare RC522
constexpr uint8_t Consenso = 7; // Pin dei LED rosso
constexpr uint8_t Led_Rosso = 4; // Pin dei LED rosso
constexpr uint8_t Led_Verde = 3; // Pin dei LED verde
constexpr uint8_t progBtn = 2; // Tasto di programmazione
boolean match = false; // initializza card match a falso
boolean statusFlag; // vero se l'armadietto è libero; falso se occupato
boolean userCardSelect = false; // initializza userCardSelect a falso
boolean replaceMaster = false;
uint8_t successRead; // Variabile per Lettura corretta dal Lettore RFID
byte passCard[4]; // ID Pass Card
byte userCard[4]; // ID utente corrente
// Inizializza Lettore RFID MFRC522
MFRC522 mfrc522(10, 9);
void setup() {
delay(500);
//Configurazione del microcontrollore
pinMode(Led_Rosso, OUTPUT);
pinMode(Led_Verde, OUTPUT);
pinMode(Consenso, OUTPUT);
pinMode(progBtn, INPUT_PULLUP); // Abilita pull-up
digitalWrite(Led_Rosso, HIGH);
digitalWrite(Led_Verde, HIGH);
//Guadagno Antenna al massimo aumenta la distanza di lettura
mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max);
digitalWrite(Consenso, LOW);// Consenso negato
// Controlla che una passCard sia stata definita
if (EEPROM.read(0) == 170){
IDCardRead(2, passCard); // memorizza ID nel vettore passCard
}
// Controlla che al reset una User Card non sia già definita
// L'indirizzo 1 della EEPROM contiene il flag '170' = AA se User card definita
if (EEPROM.read(1) == 170){
// Armadietto occupato
digitalWrite(Led_Rosso, LOW); // Led Rosso acceso
digitalWrite(Led_Verde, HIGH); // Led Verde spento
statusFlag = false;
IDCardRead(6, userCard); // memorizza l'ID nel vettore userCard
}
else {
// Armadietto libero
digitalWrite(Led_Rosso, HIGH); // Led Rosso spento
digitalWrite(Led_Verde, LOW); // Led Verde acceso
statusFlag = true;
}
}
void loop() {
SPI.begin();
mfrc522.PCD_Init();
// se viene premuto il tasto programmazione per più di 5 secondi,
// si comanda la programmazione della ID di Pass Card
if (digitalRead(progBtn) == LOW) { // Controlla che il tasto prog sia premuto
// In caso di tasto premuto
digitalWrite(Led_Rosso, LOW); // accende il Led Rosso: inizio programmazione Pass Card
digitalWrite(Led_Verde, HIGH); // spegne il Led Verde
bool buttonState = monitorProgButton(5000); // Attesa dei 5 secondi
if (buttonState == true && digitalRead(progBtn) == LOW) {
// se il Tasto è ancora premuto, cancella la flag della Pass Card
EEPROM.write(0, 0); // Cancella flag di Pass Card all'indirizzo 0 EEPROM
// Pass Card
do {
successRead = getID();//se lettura corretta successRead = 1 altrimenti = 0
// Lampeggio del Led Rosso in attesa della lettura della Pass Card
digitalWrite(Led_Rosso, LOW); // accende il Led Rosso
delay(200);
digitalWrite(Led_Rosso, HIGH); // spegne il Led Rosso
delay(200);
}
// il programma non va avanti fino a che non viene letta la Pass Card correttamente
while (!successRead);
// Memorizzazione della Pass Card ID, contenuto nel vettore readCard,
// nella EEPROM a partire dall'indirizzo 2
EEPROM.write(0, 170); // configura il flag Pass Card definita
for ( uint8_t j = 0; j < 4; j++ ) {
EEPROM.write( 2 + j, mfrc522.uid.uidByte[j] );
passCard[j] = mfrc522.uid.uidByte[j];
}
digitalWrite(Led_Verde, LOW); // accende il Led Verde
}
}
// Verifica se una Card è stata rilevata
if (mfrc522.PICC_IsNewCardPresent()){
if (mfrc522.PICC_ReadCardSerial()) {
// Lettura effettuata
boolean contr_flg = true; // initializza contr_flg a vero
if(EEPROM.read(0) == 170){
// Una Passpartout Card e' stata definita
if(CompareVector(mfrc522.uid.uidByte, passCard, 0, 4)) {
// La card letta e' la Passpartout
granted(500); // consenso all'apertura per 500 ms in ogni caso
freeMode();
EEPROM.write( 1, 0);
statusFlag = true;
contr_flg = false; // elimina altri controlli successivi
}
}
if(contr_flg){
// La card letta e' una User Card
if (statusFlag) {
// Armadietto libero
granted(500); // consenso all'apertura per 500 ms in ogni caso
// Perciò deve diventare occupato
// Memorizzazione del currCard ID, contenuto nel vettore readCard,
// nella EEPROM a partire dall'indirizzo 6
for ( uint8_t j = 0; j < 4; j++ ) {
EEPROM.write( 6 + j, mfrc522.uid.uidByte[j] );
userCard[j] = mfrc522.uid.uidByte[j];
}
statusFlag = false;
EEPROM.write( 1, 170);
occupiedMode();
}
else {
// Armadietto occupato
// Controlla se la card letta è quella corrente
if (CompareVector(mfrc522.uid.uidByte, userCard, 0, 4)) {
// La card letta è quella corrente
granted(500); // da'  il consenso all'apertura per 500 ms
statusFlag = true; // libera l'armadietto
freeMode();
EEPROM.write( 1, 0);
}
else {
// La card letta NON è nella lista memorizzata
denied();
}
}
}
}
}
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
//////////// Controlla i bytes di due vettori ////////////
boolean CompareVector(byte *x, byte *z, byte inz, byte dv) {
byte j;
boolean flg = true;
for (j = inz; j if(x[j] != z[j]) flg = false;
}
return flg;
}
//////////// Accesso concesso ////////////
void granted ( uint16_t setDelay) {
digitalWrite(Consenso, HIGH); // Consenso abilitato
delay(setDelay); // Tieni il consenso per il tempo selezionato
digitalWrite(Consenso, LOW); // Consenso negato
delay(1000); // aspetta un secondo
}
//////////// Accesso negato ////////////
void denied() {
digitalWrite(Led_Verde, HIGH); // spegni il Led Verde
digitalWrite(Led_Rosso, HIGH); // spegni il Led Rosso
delay(500); // aspetta mezzo secondo
digitalWrite(Led_Rosso, LOW); // accendi il Led Rosso
delay(500); // aspetta mezzo secondo
digitalWrite(Led_Rosso, HIGH); // spegni il Led Rosso
delay(500); // aspetta mezzo secondo
digitalWrite(Led_Rosso, LOW); // accendi il Led Rosso
delay(3000); // attende la rimozione della Card per evitare una ripetizione immediata del segnale di diniego
}
//////////// Acquisisci l'ID di una card ////////////
uint8_t getID() {
// Prepara la lettura di un ID
if ( ! mfrc522.PICC_IsNewCardPresent()) { // se non c'è una card esci
return 0; // segnala lettura non eseguita
}
//fino a che la lettura non è terminata correttamente esci
if ( ! mfrc522.PICC_ReadCardSerial()) {
return 0; // segnala lettura non esguita
}
// Si legge la card a 4 bytes
// Non supporta la lettura della card a 7 bytes
mfrc522.PICC_HaltA(); // termina lettura
return 1; // segnala lettura eseguita
}
//////////// Read an ID from EEPROM ////////////
void IDCardRead(uint8_t iin, byte IDCard[4]){
for ( uint8_t i = 0; i < 4; i++ ) { // Leggi l'ID Card dalla EEPROM
IDCard[i] = EEPROM.read(iin + i); // salva l'ID nel vettore IDCard
}
}
//////////// Led in Modo Occupato ////////////
void occupiedMode () {
digitalWrite(Led_Rosso, LOW); // accende il Led Rosso
digitalWrite(Led_Verde, HIGH); // spegni il Led Verde
digitalWrite(Consenso, LOW); // Consenso negato
// attende la rimozione della Card per evitare lo sblocco immediato
delay(3000);
}
//////////// Led in Modo Libero ////////////
void freeMode () {
digitalWrite(Led_Rosso, HIGH); // spegne il Led Rosso
digitalWrite(Led_Verde, LOW); // accende il Led Verde
digitalWrite(Consenso, LOW); // Consenso negato
// attende la rimozione della Card per evitare il blocco immediato
delay(3000);
}
//////////// Test del Tasto di Programmazione ////////////
bool monitorProgButton(uint32_t interval) {
uint32_t now = (uint32_t)millis();
while ((uint32_t)millis() - now < interval) {
// check on every half a second
if (((uint32_t)millis() % 500) == 0) {
if (digitalRead(progBtn) != LOW)
return false;
}
}
return true;
}