Apriporta RFID Arduino con salvataggio in EEPROM

Questo articolo è la continuazione di una idea già pubblicata da Nicola Pison e presentata il 26 gennaio 2014, che utilizza come chiave un trasponder.
Nell’idea di utilizzare questo dispositivo come apriporta ho trovato scomodo dover inserire preventivamente i codici dei token direttamente nel programma di Arduino anche se la soluzione adottata è decisamente rapida ed efficace.
Modificando lo sketch ho introdotto un unico token nel listato chiamato MASTER. Con questa chiave, è possibile programmare le chiavi desiderate che così saranno abilitate all’apertura. I codici così inseriti per non essere “dimenticati” sono scritti nell’ EEPROM di Arduino.

E’ stato aggiunto un reset generale in caso di cancellazione forzata di tutti i codici utilizzati eccetto per il codice del MASTER.

Attualmente è stata dichiarata una array di 50 elementi (n. chiavi). Il numero è ipotetico e comunque innalzabile calcolando 8 byte per codice chiave per 1Kbyte di capacità in EEPROM su Atmel 328, esiste capienza teorica di almeno 125 numeri registrabili. La RAM libera risulta maggiore quindi il problema è la capienza della memoria non volatile. E’ sufficiente modificare la dimensione dell’array nella riga 68 –> uidRFID[50]; e innalzare il numero dei token registrabili.  Attenzione a non esagerare. Il compilatore accetta tutto. Non è detto che le risorse ci siano.

La scelta dei regolatori verssione “L” – 78L05 e LM317LZ è dovuta dal basso assorbimento del circuito che si attesta intorno ai 50 mA di punta; consumo di: processore, RFID e led acceso (escluso consumo relay).
Funzionamento:
Facendo riconoscere al lettore il Master il led effettua 8 lampeggi alla fine dei quali si può presentare un nuovo token. La procedura termina avvicinando nuovamente il Master. Se entro 10 secondi questa sequenza non viene portata a termine, il processo viene annullato.
Alla presenza di un codice valido si attiva un relay che rimane eccitato per un tempo dichiarato nella definizione   “attiva_temporele” riga 49  espresso in millisecondi. Al fine di evitare ripetute rilevazioni, una volta che è stato riconosciuto il codice, un nuovo azionamento viene inibito per 3,5 secondi.
L’alimentazione viene prelevata direttamente dai 12 VAC normalmente disponibili come tensione per l’elettrocalamita dell’apriporta.
L’antenna RFID funziona con una tensione di 3,3V. Abbinando un Arduino da 5V si può prelevare la tensione per il funzionamento direttamente dal piedino 3,3V. I segnali di uscita da ARDUINO rimangono però a 5V. E’opportuno abbassare il livello di tensione almeno per gli ingressi del lettore. (vedi schema con partitore)
Nel caso dei due dispositivi che attualmente stanno funzionando, sono stati utilizzati due arduini MINI a 3,3V 8MHz.

L’utilizzo della versione MINI di arduino è dettata innanzitutto dalle dimensioni ridotte. In una scatola comune da incasso per frutti elettrici sta comodamente tutto il circuito. Inoltre la versione MINI è meno costosa perchè non ha il convertitore seriale-usb che viene collegato solo per la programmazione.

mini

Scatola_off Scatola_on

 

 

 

 

 

SKETCH:

 

 

Schema_3V

Versione a 3,3 Volt

Schema_5V

Versione a 5V

 

Allegata libreria RFID e datasheet dei regolatori di tensione

Roberto

Allegati

  • Fabio

    Ciao,

    la tua guida è molto interessante.

    Avendo seguito anche la precedente guida da te descritta ho provato a realizzare anche questa.

    Sono sempre novello di Arduino e sto cercando di realizzare questo progetto.

    Ho seguito tutto correttamente. Sto procedendo alla programmazione di arduino mini pro tramite la guida http://www.giuseppecaccavale.it/arduino/programmare-arduino-pro-mini-con-arduino-uno/ utilizzando la scheda di arduino uno senza microprocessore.

    Tutto ok, ho seguito la guida e caricato lo sketch di fade per vedere se effettivamente funzionava la comunicazione con arduino mini pro. Funziona tutto perfettamente.

    Ho provato a caricare lo sketch sopra ma a circa il 90% del caricamento si blocca generando questo errore: avrdude: stk500_recv(): programmer is not responding.

    Ho sbagliato qualcosa?Sapresti aiutarmi?

    Ti ringrazio
    Fabio

    • roberto

      Ciao Fabio, l’errore che ti da sembra proprio un errore di mancata comunicazione verso l’arduino mini da parte della seriale. Ho dato un’occhiata al sito di Giuseppe Caccavale e mi sembra interessante, Ho notato però delle incongruenze con i collegamenti. Ad esempio arduino mini ha già la connessione del reset con il condensatore direttamente sullo stampato sul pettine di collegamento alla seriale.
      Trovo inutile reinserirlo e adottare il piedino di reset.
      Dovrei provare con un arduino UNO anche se, comprando la versione mini pro ho anche aquistato un convertitore usb – seriale TTL che si interfaccia direttamente con il connettore a 6 pin. Per quello che costa e la spedizione gratuita direi che questa è la soluzione migliore. Prova a cercare “usb seriale FT232RL for arduino”. Siamo a cifre di qualche € senza toccare un arduino UNO con il pericolo di fare qualche cosa di sbagliato. Consiglierei anche di acquistare un arduino nano che costa un po’ di più del mini ma ha il collegamento seriale a bordo. Con il NANO provo gli sketch che alla fine riverso sul mini. Anche la piedinatura è simile. Trovo la versione con arduino UNO originale, ma perchè non ti fai un circuito con un max232 e pochi componenti e lo colleghi direttamente alla seriale di un computer. Provato e funziona perfettamente. Se ti va di cimentarti cerca qualche schema sul web. Se non trovi magari vedo di fartene uno io. Il MAX 232 lo trovi nei negozi di elettronica.
      Roberto

  • Yoda

    Salve,
    molto interessante il suo articolo ho preso spunto per il mio codice con il quale avevo alcuni dubbi sulla sintassi di alcune serie di funzioni, sto cercando di introdurre un eliminazione della card se già presente in eeprom, ho qualche problema nel confrontare il seriale della lettura con quelli memorizzati e cancellare il seriale di conseguenza, mi può aiutare?
    Saluti.

    • roberto

      Immagino si voglia poter rimuovere un codice senza azzerare tutta la sequenza.
      Suppongo, inoltre, che si voglia legittimare la rimozione con il passaggio del Master prima e dopo. In pratica se il Master è stato riconosciuto e il codice della card a seguire non esiste in database, deve venire aggiunto, altrimenti (se esiste) deve essere rimosso.
      Ho modificato lo sketch. Purtroppo per ragioni di tempo le modifiche sono teoriche perchè non sono state testate. Se effettivamente esiste una certa dimestichezza, da parte sua, valuti e corregga eventuali imprecisioni.
      Conto sulla sua competenza e mi faccia sapere gli errori e le sviste che sono riuscito a introdurre “al buio”.
      Cosa è stato modificato:
      Introdotta la variabile P_indice in linea 66
      Introdotta la casistica case 3: nella zona di programmazione
      appena qualche riga sotto l’attivazione (se trovato il codice e programmazione attiva) delle operazioni di cancellazione
      Roberto
      /*
      * MFRC522 – Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT.
      * The library file MFRC522.h has a wealth of useful info. Please read it.
      * The functions are documented in MFRC522.cpp.
      *
      * Based on code Dr.Leong ( http://WWW.B2CQSHOP.COM )
      * Created by Nicola Pison (webingenerale.com), Jen 2014.
      * Modify by Roberto Contessi, january 2014
      * Released into the public domain.
      *
      * Sample program showing how to read data from a PICC using a MFRC522 reader on the Arduino SPI interface.
      *—————————————————————————– empty_skull
      * add pin configuration for arduino mega
      * http://www.webingenerale.com
      —————————————————————————– Nicola Pison
      * Pin layout should be as follows:
      * Signal Pin Pin Pin
      * Arduino Uno Arduino Mega MFRC522 board
      * ————————————————————
      * Reset 7 5 RST
      * SPI SS 6 53 SDA
      * SPI MOSI 11 52 MOSI
      * SPI MISO 12 51 MISO
      * SPI SCK 13 50 SCK
      *
      * The reader can be found on eBay for around 5 dollars. Search for “mf-rc522” on ebay.com.
      * ———————————————————————————————————- aggiunta da RC
      * funzionamento per l’uso con una card denominata “master” e la registrazione in EEPROM di carte nuove (ora impostato fino 50)
      * Per semplicità il codice di questa carta verrà inserita nella variabile CardMaster=”abcdefgh”
      * Con la master card si possono abilitare nuove card.
      * è stata aggiunta una uscita su cui collegare un led o un buzzer per capire le sequenze senza utilizzare la seriale
      * Per registrare una CARD : rilevare la MASTER CARD quindi entro 6 secondi rilevare la NUOVA CARD e terminare ancora con la MASTER CARD
      * per reset generale : tenere premuto il pulsante sul piedino A0 per 10 sec. Il reset non influisce sul codice della MASTER CARD
      * ——————————————
      * sequenza prevista in EEPROM
      * BYTE (se è già stato inizializzato deve avere il valore dec 123 altrimenti segue inizializzazione)
      * BYTE card registrate
      * 8 BYTE n. della MASTER CARD
      * 8 BYTE – 8 BYTE …. n8BYTE (codici delle card registrate)
      */

      #include
      #include
      #include

      #define SS_PIN 6
      #define RST_PIN 7
      #define attiva_rele 5 // pin relè
      #define attiva_temporele 1500 //tempo in millisecondi attuazione rele
      #define attiva_led 4 // pin led o buzzer
      #define reset_gen A0 //pulsante da premere per 10 sec per azzerare i codici in memoria

      MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.

      // ————————————————————— master
      String CardMaster=”1a2b3c4d”; // INSERIRE QUI IL CODICE DELLA CARTA MASTER
      // ———————————————————————–
      long previousMillis = 0;
      long previousMillis1 = 0;
      long interval = 10; // intervallo lettura RFID
      long interval1 = 10000; // intervallo oltre al quale si esce dalla programmazione (modificabile in mills)
      unsigned long tempo_rst = 800000; // intervallo prima reset generale (modificabile)
      unsigned long cnt=0;
      int Programmazione=0;
      byte pch = 0; // puntatore card registrate
      byte P_indice = 0; // puntatore codice da rimuovere
      String uid_s1;

      String uidRFID[50];

      void setup() {

      Serial.begin(9600); // Initialize serial communications with the PC
      SPI.begin(); // Init SPI bus
      mfrc522.PCD_Init(); // Init MFRC522 card
      pinMode(attiva_rele, OUTPUT);
      pinMode(attiva_led, OUTPUT);
      pinMode(reset_gen,INPUT);

      // lettura da EEPROM ———————————————————————————————————–

      pch=EEPROM.read(0);

      if (pch == 123) { // leggo valori
      pch=EEPROM.read(1);

      Serial.println(pch);

      int i=1;
      while(i<=pch) {
      uidRFID[i-1]="";
      for (int p=i*8-8+2;p “+pch); // String(sizeof(uidRFID)/sizeof(String)));
      Serial.println(“In attesa di lettura…”);
      }

      void loop() {

      // scansione lettore ogni “interval” in mS ———————
      unsigned long currentMillis = millis();
      // se premuto reset …
      while (!digitalRead(reset_gen)) {
      // conteggio 10 sec prima di resettare
      while (!digitalRead(reset_gen)) {
      cnt++;
      if (cnt>tempo_rst) {
      // reset confermato
      digitalWrite(attiva_led,HIGH);
      pch=0;
      EEPROM.write (1,0);
      cnt=0;
      for (int q=0;q 0 && currentMillis – previousMillis1 > interval1) {
      previousMillis1 = currentMillis;
      Programmazione = 0;
      digitalWrite(attiva_led,LOW);
      Serial.println(“azzerata programmazione”);
      }
      if(currentMillis – previousMillis > interval) {
      previousMillis = currentMillis;

      // i due if seguenti interrompono l’esecuzione se le condizioni di presenza card non è verificata velocizzando l’esecuzione
      // Look for new cards
      if ( ! mfrc522.PICC_IsNewCardPresent()) {
      return;
      }
      // Select one of the cards
      if ( ! mfrc522.PICC_ReadCardSerial()) {
      return;
      }

      // lettura codice card —————————————-
      String uid_s = “”;

      if (!mfrc522.PICC_IsNewCardPresent() && !mfrc522.PICC_ReadCardSerial()) {

      for (byte i = 0; i < mfrc522.uid.size; i++) {

      String uid_a = String(mfrc522.uid.uidByte[i] “);
      Serial.println(uid_s);
      Serial.println(“”);
      boolean controllo = false;

      // —————————————————- rilevazione codici
      if (uid_s==CardMaster) { // entra in programmazione
      digitalWrite(attiva_led, HIGH);
      delay(100);
      digitalWrite(attiva_led, LOW);
      previousMillis1 = millis();
      switch(Programmazione){
      case 0:
      Programmazione=1;
      Serial.println(“programmazione……”);
      for (int q=0;q<8;q++) {
      digitalWrite(attiva_led,HIGH);
      delay(100);
      digitalWrite(attiva_led,LOW);
      delay(100);
      }
      digitalWrite(attiva_led,HIGH);

      break;
      case 2:
      // Programmazione nuovo codice confermato
      // in uid_s1 il valore da scrivere
      uidRFID[pch]=uid_s1;
      // scrivi in EEPROM
      EEPROM.write (1,pch+1);
      for (int p=0;p<8;p++) {
      EEPROM.write(pch*8+2+p,byte(uid_s1.charAt(p)));
      }
      pch++;
      Programmazione=0;
      Serial.println("Codice aggiunto");
      digitalWrite(attiva_led,LOW);
      delay(1000);
      break;
      case 3:
      // Rimozione codice confermato
      // rimozione nell'array e riscrittura EEPROM
      pch–;
      EEPROM.write (1,pch); // registrazione del numero di card
      // P_indice contiene il puntatore array da cancellare
      // l'ultimo byte è dato da pch x 8 + 10 byte della Master card e 2 servizio
      // pch già decrementato
      for (int p=((P_indice*8)+11);p<(pch*8+11);p++) {
      EEPROM.write(p,EEPROM.read(p+8));
      }
      for (int p=P_indice;p<pch+1;p++) { // ridimensiono array
      uidRFID[p]=uidRFID[p+1];
      }
      Programmazione=0;
      Serial.println("Codice rimosso");
      digitalWrite(attiva_led,LOW);
      delay(1000);
      break;

      default: break;
      }
      }

      else { // valuta codici in memoria
      for (int i = 0; i Confermare con Master”);
      P_indice=i;
      Programmazione=3;
      }
      else {
      Serial.println(“Accesso consentito”);
      openDoor();
      controllo = true;
      break;
      }
      // modifica cancellazione card **********************************************

      }
      }

      if(!controllo){
      if (Programmazione==1) {
      for (int q=0;q confermare con Master”);
      uid_s1 = uid_s;
      Programmazione=2;
      delay(500);
      }
      else {
      Serial.println(“Accesso vietato”);
      delay(2000);
      }
      }
      }
      Serial.println();
      Serial.println(“In attesa di lettura…”);

      } // chiude attesa mills
      } // chiude loop

      // —————————————- Funzioni locali

      void openDoor(){

      digitalWrite(attiva_rele, HIGH);
      digitalWrite(attiva_led, HIGH);
      // Serial.println(“Rele ON”);
      delay(attiva_temporele);
      digitalWrite(attiva_rele, LOW);
      digitalWrite(attiva_led, LOW);
      // Serial.println(“Rele OFF”);
      delay(3500);
      }

  • Valter Bulanti

    salve dopo un pomeriggio passato a litigare con un Arduino Mega ho trovato che :

    I pin corretti per MEGA 2560 sono:

    * SPI SS 53 SDA
    * SPI MOSI 51 MOSI
    * SPI MISO 50 MISO
    * SPI SCK 52 SCK

    Condivido e grazie a tutti

    • Giuseppe

      Grazie Valter, mi hai veramente salvato da un incubo.

  • Francesco

    Salve, ho da poco ricevuto il RIFD-RC522 e mi sono imbattuto su questa vostra pagina, sulla quale mi complimento vivamente per la sua chiarezza. Prima di ciò il modulo l’ho provato con gli esempi delle librerie e poi utilizzando lo scetch di Nicola Pison ed il tutto è andato a buon fine e ne ho intuito anche (spero) il funzionamento. Volendo fare qualcosa in più, ho utilizzato il vs. schetch che però si ferma alla linea 102:”Serial.println(“In attesa di lettura…”);” ho controllato e ricontrollato ma non trovo alcun errore. Sto utilizzando un arduino uno r3, non ho inserito il pulsante reset perchè per ora non mi occorre…
    Ringrazio per la eventuale risposta chiarificatrice. Francesco

    • Nicola

      Ciao Francesco,

      il problema potrebbe essere il mancato inserimento della velocità della seriale nel “void setup()”. Per stampare in seriale i dati da arduino bisogna indicare con “Serial.begin(num);” la velocità con la quale si vuole comunicare con il PC (in questo caso). La classica velocità è di 9600. Quindi nel tuo caso la parte di codice all’interno del void setup sarà:

      void setup() {
      Serial.begin(9600);

      …………………………altro codice………………..

      }

      In questo modo potrai utilizzare la direttiva Serial.println(“testo”);

      Facci sapere!

      Buona serata

      • Francesco

        grazie per la risposta, riprendo subito dichiarando che aprendo la finestra del seriale esce scritto:
        0
        In attesa di lettura…

        quindi il seriale funziona ed è settato bene, ma avvicinando la carta al modulo non legge o quantomeno non esce altro sul seriale, dove sbaglio a capire? Rigrazie

      • Giuseppe

        Hai ragione, elimina tutto il codice dalla nota
        * // se premuto reset …
        che al momento crea un loop senza uscita.
        E’ ovviamente da correggere… a me al momento non serve quindi tutto ok.