/*
|
-------------------------------------------
|
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;
|
} |