Rfid arduino seconda parte

Nel corso del precedente articolo dedicato all’Rfid arduino ho iniziato ad analizzare il codice di esempio rilasciato dal produttore della scheda.

RFID shield ID-12

Se vorrai utilizzare questa shield per i tuoi progetti di controllo accessi, contapersone, allarme o attivazione dell’impianto domotico è necessario comprendere tutto il codice di riconoscimento delle chiavi dotate di tag rfid.

Lo sketch base dell’Rfid Arduino

Ricominciamo l’analisi delle righe che consentono all’Rfid arduino shield di riconoscere le tessere ed i tag.

  do{                                                                //inizio un ciclo che finirà solo quando verrà premuto nuovamente il pulsante

   val = 0;
   checksum = 0;                                                     //azzero le variabili precedentemente dichiarate
   bytesread = 0;
   tempbyte = 0;

  if(mySerial.available() > 0) {                                     //controllo se sulla mia seriale è presente qualche dato
    if((val = mySerial.read()) == 2) {                               //se così è leggo da essa il valore
      bytesread = 0;                                                 //e se è uguale a 2 (carattere di controllo) pongo a 0 la variabile bytesread
      while (bytesread < 12) {                                       //mando in esecuzione un ciclo per 12 volte, in modo da poter leggere tutti i 12 caratteri della tessera (5 byte del codice + 1 del cehcksum
      if( mySerial.available() > 0) {                                //controllo se i dati sono disponibili ad essere letti
          val = mySerial.read();                                     //quindi assegno a 'val' il valore dell'i-esimo carattere
          if((val == 0x0D)||(val == 0x0A)||(val == 0x03)||(val == 0x02)) {     //se leggo un carattere 'header' o un carattere di stop
            break;                                                             // fermo la lettura
          }

          if ((val >= '0') && (val <= '9')) {
            val -= '0';
          }                                                                    //traduco in esadecimale il carattere appena letto
          else if ((val >= 'A') && (val <= 'F')) {
            val = 10 + val - 'A';
          }

          //ogni 2 caratteri letti, aggiungo il byte così creato al vettore 'code'

          if (bytesread & 1 == 1) {                                            //se ho letto un solo carattere fin'ora
            code[bytesread >> 1] = (val | (tempbyte << 4));                        //assegno alla seconda parte del byte in posizione bytesread-esima il valore esadecimale del carattere letto

            if (bytesread >> 1 != 5) {                                             //se ho letto l'ultimo byte della scheda calcolo il checksum
              checksum ^= code[bytesread >> 1];                                    //facendo la XOR sull'ultimo byte letto
            };
          } else {
            tempbyte = val;                                                    //altrimenti assegno il valore letto alla variabile tempbyte
          };

          bytesread++;                                                        //mi preparo a leggere il prossimo byte
        }
      }

     if (bytesread == 12) {                                                   //se ho letto tutti i 6 byte
        (code[5]==checksum) ? check = true : check = false ;                  //controllo che il checksum sia corretto
        if(check){                                                            //se lo è passo a controllare se devo salvare o cancellare
            check=false;                                                      //rimetto a false la variabile check per successivi utilizzi
            if(scrivere&&!controllo){                                         //controllo se devo scrivere
                  for(int i=0;i<1021;i+=5){                                   //in caso affermativo eseguo un ciclo che controlla tutta la EEPROM
                        if((EEPROM.read(i)==code[0])&&(EEPROM.read(i+1)==code[1])&&(EEPROM.read(i+2)==code[2])&&(EEPROM.read(i+3)==code[3])&&(EEPROM.read(i+4)==code[4])){
                            check=true;                                        //se trovo il codice della tessera letta già salvato nella EEPROM metto a true la variabile 'check'
                            break;                                             //ed esco dal ciclo
                        }
                  }
                  if(check){                                                   //quindi controllo il valore della variabile check, se è vero, significa che la tessera è già stata registrata
                        Serial.print("Tessera già registrata!");               //quindi lo comunico su seriale
                        stampa_code(code);
                      if(LED)
                        digitalWrite(RED_LED_PIN,HIGH);
                        delay(50);
                      if(BUZZER)
                        analogWrite(BUZZ_PIN,50);                              //e mando un segnale di errore luminoso e/o sonoro in sempre in base al fatto che l'utente abbia specificato led e buzzer
                        delay(50);
                      if(BUZZER)
                        digitalWrite(BUZZ_PIN,LOW);
                      if(LED)
                        digitalWrite(RED_LED_PIN,LOW);
                  }

                  else{                                                        //se la tessera non è stata trovata
                      check=false;                                             //rimetto a false la variabile check per successivi utilizzi
                      for(int i=0;i<1021;i+=5){                                //quindi eseguo un ciclo che controlla tutta la EEPROM in cerca di 5 byte successivi liberi
                        if((EEPROM.read(i)==0xff)&&(EEPROM.read(i+1)==0xff)&&(EEPROM.read(i+2)==0xff)&&(EEPROM.read(i+3)==0xff)&&(EEPROM.read(i+4)==0xff)){
                          for(int j=i;j<i+5;j++)                               //una volta trovati, partendo dal primo, fino al quinto, ci salvo il valore della tessera
                              EEPROM.write(j,code[j-i]);                             //eseguendo un ciclo 5 volte
                          check=true;                                                //pongo a true la variabile check
                          break;                                               //ed esco dal ciclo
                        }
                      }
                      if(check){                                               //se la variabile check è vera, significa che ho salvato con successo, quindi
                          Serial.print("Tessera Salvata");                     //lo stampo su seriale
                          stampa_code(code);
                        if(BUZZER){
                          analogWrite(BUZZ_PIN,50);
                          delay(100);
                          digitalWrite(BUZZ_PIN,LOW);
                        }
                        if(LED){
                          for(int i=0;i<5;i++){
                           digitalWrite(GREEN_LED_PIN,HIGH);                   //e mando un segnale luminoso e/o sonoro in sempre in base al fatto che l'utente abbia specificato led e buzzer
                           delay(50);
                           digitalWrite(GREEN_LED_PIN,LOW);
                           delay(50);
                          }
                          digitalWrite(GREEN_LED_PIN,HIGH);
                        }
                      }
                      else{                                                    //se la variabile check non è vera, significa che ho controllato tutta la memoria senza trovare 5 byte sequenziali liberi
                           Serial.println("Memoria piena");                    //quindi spamo su seriale che la memoria è piena
                           for(int i=0;i<5;i++){
                           if(LED)
                             digitalWrite(RED_LED_PIN,HIGH);
                           if(BUZZER)
                             analogWrite(BUZZ_PIN,50);
                           delay(50);                                          //e mando un segnale di errore luminoso e/o sonoro in sempre in base al fatto che l'utente abbia specificato led e buzzer
                           if(LED)
                             digitalWrite(RED_LED_PIN,LOW);
                           if(BUZZER)
                             digitalWrite(BUZZ_PIN,LOW);
                           delay(50);
                          }
                    }
                }
            }
            else if(scrivere&&controllo){                                      //se non bisogna salvare, controllo se bisogna eliminare una tessera
                  int posizione=-1;                                            //quindi inizializzo a -1 la variabile posizione, che mi servirà per salvare la posizione nella EEPROM della tessera
                  for(int i=0;i<1021;i+=5){                                    //ed eseguo un ciclo che controlla tutta la EEPROM per cercare il codice corrispondente
                        if((EEPROM.read(i)==code[0])&&(EEPROM.read(i+1)==code[1])&&(EEPROM.read(i+2)==code[2])&&(EEPROM.read(i+3)==code[3])&&(EEPROM.read(i+4)==code[4])){
                            posizione=i;                                       //se viene trovato salvo la posizione del primo byte nella variabile posizione
                        break;                                                 //ed esco dal ciclo
                        }
                  }
                  if(posizione!=-1){                                           //quindi controllo che la variabile posizione sia diversa da -1 così da sapere se è stato trovato o meno il codice
                      for(int j=posizione;j<posizione+5;j++)                   //eseguo quindi un ciclo partendo dalla posizione 'posizione' nella EEPROM
                              EEPROM.write(j,0xff);                            //sovrascrivendo i 5 byte corrispondenti alla tessera, con il byte di default '0xff'
                      Serial.print("Scheda cancellata");                       //una volta fatto ciò, stampo su seriale l'avvenuta cancellazione
                      stampa_code(code);
                      if(LED){
                        digitalWrite(GREEN_LED_PIN,HIGH);
                        digitalWrite(RED_LED_PIN,HIGH);
                      }
                      if(BUZZER)
                        analogWrite(BUZZ_PIN,50);                              //e mando un segnale luminoso e/o sonoro in sempre in base al fatto che l'utente abbia specificato led e buzzer
                      delay(250);
                      if(LED)
                        digitalWrite(GREEN_LED_PIN,LOW);
                      if(BUZZER)
                        digitalWrite(BUZZ_PIN,LOW);
                  }
                  else{                                                        //se la variabile posizione vale -1 significa che non ha trovato in memoria la tessera letta
                      Serial.print("Impossibile cancellare la scheda, non è salvata");  //quindi lo comunico su seriale
                      stampa_code(code);
                      for(int x=0;x<10;x++){
                        if(LED)
                          digitalWrite(RED_LED_PIN,HIGH);
                        if(BUZZER)
                          analogWrite(BUZZ_PIN,50);
                        delay(25);                                             //e mando un segnale di errore luminoso e/o sonoro in sempre in base al fatto che l'utente abbia specificato led e buzzer
                        if(LED)
                          digitalWrite(RED_LED_PIN,LOW);
                        if(BUZZER)
                          digitalWrite(BUZZ_PIN,LOW);
                        delay(25);
                      }
                      if(LED)
                        digitalWrite(RED_LED_PIN,HIGH);
                    }

            }

            check=true;                                                        //rimetto a vero il valore della variabile check siccome il checksum è corretto
            }
            else{                                                              //se il checksum fosse incorretto
                 Serial.print("Checksum incorretto");                          //lo comunico su seriale
                 for(int i=0;i<3;i++){
                    if(LED)
                      digitalWrite(RED_LED_PIN,HIGH);
                    if(BUZZER)
                      analogWrite(BUZZ_PIN,50);
                    delay(30);                                                 //e mando un segnale di errore luminoso e/o sonoro in sempre in base al fatto che l'utente abbia specificato led e buzzer
                    if(LED)
                      digitalWrite(RED_LED_PIN,LOW);
                    if(BUZZER)
                      digitalWrite(BUZZ_PIN,LOW);
                 }
                 if(LED)
                    digitalWrite(RED_LED_PIN,HIGH);
            }

     }
    }
  }
  }
  while((digitalRead(PULSANTE)==HIGH)&&(controllo||scrivere));

linea 127: inizia un ciclo di tipo while…do, la sintassi utilizzata per questo sketch non pone il while, con la condizione di verifica in testa ma alla conclusione del ciclo, linea 307;

linee 129-132: azzera le variabili val,checksum,byteread,tempbyte prima di procedere al loro utilizzo;

linea 134: verifica che la comunicazione seriale verso l’rfid shield sia attiva ed esegue le righe contenute dopo la parentesi graffa solo quando riceve dei byte di comunicazione da questa seriale virtuale;

linea 135: leggi dalla seriale con il metodo read() e confronta il valore letto con il carattere di controllo 2;

linea 136: se il carattere di controllo è verificato imposta a 0 la variabile byteread;

linea 137: inizia un ciclo while la cui condizione è specificata tra parentesi, ossia fino a che il valore di byteread è inferiore a 12, questo perchè l’rfid arduino ID-12 ( vedi figura in alto ) presenta in tag id di 12 byte per cui alla lettura di ciascun byte incrementerai il valore di byteread e sarai certo di aver letto tutto il tag al suo raggiungimento;

linea 138: verifica che sulla seriale virtuale stiano ancora arrivando byte;

linea 139: imposta il valore della variabile val con quello letto sulla porta seriale;

linee 140-142: confronta il carattere letto con i codici 0x0D, 0x0A, 0x03,0x02 valori di stop nella codifica Rfid, in tal caso ferma il ciclo while con il comando break;

linee 144-149: i tag rfid sono esadecimali ossia con numeri da 0 a 9 e lettere A,B,C,D,E ed F per i numeri 10,11,12,13,14 e 15 per cui queste righe controllano che val sia compreso tra 0 e 9 sottraendo a val il valore “0” ed aggiungendo a val 10 per i valori tra A ed F;

linee 153-161: verifica quanti valori hai letto dall’rfid arduino ed in funzione del numero di byteread assegna il code (154 ) o il valore letto al tempbyte( 160 ), alla fine della lettura di tutto il tag rfid calcoli il checksum ( 157 );

linea 163: ad ogni ciclo del while aperto alla linea 137 incrementi il valore di byteread di 1, così dopo 12 cicli avrai letto tutto il tag rfid;

linea 167: controlla di aver letto tutti i byte del tag rfid arduino dalla comunicazione seriale;

linea 168: confronta il 5 byte con il valore di checksum calcolato alla linea 157 ed imposta il valore della variabile check a true o false;

linea 169: se il chek è andato bene esegui le istruzioni contenute tra le parentesi graffe;

linea 170: imposta il valore di check a false;

linea 171: controlla che sia impostata la variabile di scrittura e che sia differente dal valore della variabile di controllo;

linee 172-177: inizia un ciclo per tutti le celle del della EEPROM alla ricerca del codice id già salvato, alla linea 173 leggi per ciascun valore di i il contenuto delle 5 posizioni EEPROM successive in modo che ad ogni ciclo for e valore di i avrai letto l’intero codice e lo confronti con il codice presente nell’array code. Quando incontri la corrispondenza tra i codice sai che la scheda è già stata memorizzata e puoi impostare il valore di check a true ed uscire dal ciclo for;

linee 178-191: se la tessera è già stata registrata

  • scrivi sul monitor seriale la frase “Tessera già registrata!”
  • richiama la funzione stampa_code() per stampare sul monitor seriale il codice letto
  • accendi il led rosso per 50 milisecondi, se hai impostato le segnalazioni con i led
  • invia un suono al BUZZER con un PWM 50 se hai impostato il funzionamento del BUZZER
  • spegni il led rosso, se lo avevi acceso prima;

linea 193: se la tessera non è registrata il valore di check sarà false ed esegui il codice contenuto nell’else;

linea 194: imposta la variabile check a false;

linee 195-1202: esegui un ciclo for per tutta la EEPROM alla ricerca di 5 posizioni successive libere, per trovarle utilizza lo stesso metodo visto per la ricerca del codice id memorizzato, per ciascun valore di i leggi le 5 celle successive e confronta il valore con 0xff ossia cella vuota. Quando trovi la posizione libera in cui scrivere inizia un nuovo ciclo for ( 197 ) e scrivi sulla EEPROM il valore del codice letto dal tag rfid arduino. Infine imposta a true il valore di check per indicare che il salvataggio è avvenuto correttamente;

linee 203-220: se il salvataggio del codice è andato a buon fine ( 203 )

  • scrivi sul monitor seriale la frase “Tessera Salvata”
  • invia un segnale al BUZZER di 100 millisecondi a PWM 50, se hai impostato la modalità BUZZER
  • accendi e spegni il led verde con un intervallo di 50 millisecondi, se hai impostato le segnalazioni con il led

linee 221-235: se il salvataggio non è avvenuto in modo corretto

  • scrivi sulla seriale “Memoria Piena”
  • esegui il ciclo for per 5 volte accendendo il led rosso e facendo suonare il buzzer se impostati come segnalazioni

linea 238: se il valore della variabile scrivere e quello della variabile controllo indicano che non devi salvare alcun dato ma solo controllare che la scheda esista procedi con le linee successive;

linea 239: imposta a -1 il valore della variabile posizione questa variabile la userai per memorizzare la posizione della tessera nella EEPROM se presente;

linee 240-245: inizia un ciclo di lettura della EEPROM in cui confronti tutte le celle a 5 a 5 con il valore contenuto nell’array code e se trovi corrispondenza tra l’id letto ed uno degli ID presenti nella EEPROM memorizzi la posizione;

linee 246-262: se la variabiel posizione contiene un valore, ossia è diverso da -1 impostato alla linea 239 puoi procedere con la cancellazione della tessera memorizzata. Per cancellare la tessera inizia un ciclo di 5 posizioni partendo dal valore di posizione memorizzato nell’omonima variabile e scrivi 0xff in ciascuna delle 5 celle EEPROM. Quindi

  • stampa sul monitor seriale il testi “Scheda cancellata” ed il codice della scheda
  • accendi i led rosso e verde, se hai impostato questo tipo di segnalazione
  • invia un segnale PWM al Buzzer per 250 millisecondi
  • spegni il led verde
  • spegni il buzzer

linee 263-280: se la tessera non è presente nella EEPROM

  • scrivi sul monitor seriale “Impossibile cancellare la scheda, non è salvata” seguito dal codice letto
  • inizia un ciclo da 0 a 10 in cui accendi e spegni il led rosso e invii segnali acustici con il buzzer dell’rfid arduino
  • infine ( linea 279 ) lascia acceso il led rosso

linea 284: imposta a true il valore della variabile check;

linee 286-301: esegui queste linee se il controllo alla linea 169 è risultato errato ossia il cheksum non corrisponde ossia il checksum calcolato e quello letto non corrispondono. quindi

  • scrivi sul monitor seriale “Checksum incorretto”;
  • inizia un ciclo da 0 a 3 in cui fai lampeggiare il led rosso ed emetti un suono di avviso attraverso il buzzer;
  • infine ( linea 300 ) imposti il led rosso acceso;

linea 307: concludi il ciclo while iniziato alla linea 127 la cui condizione di verifica è basata sul confronto che il pulsante non venga premuto e che siano valide le variabili scrivere e controllo. Se una delle due condizioni non è verificata il ciclo si interrompe, per cui se vuoi fermare l’rfid arduino durante il suo funzionamento in modalità di lettura,scrittura o cancellazione puoi premere il pulsante P1.

Il video dell’rfid arduino shield

Ti riporto il video di test che ho realizzato con la mia Rfid arduino shield:

Buona sperimentazione !!!

  • Questo sito ed i suoi contenuti è fornito "così com'è" e Mauro Alfieri non rilascia alcuna dichiarazione o garanzia di alcun tipo, esplicita o implicita, riguardo alla completezza, accuratezza, affidabilità, idoneità o disponibilità del sito o delle informazioni, prodotti, servizi o grafiche correlate contenute sul sito per qualsiasi scopo.
  • Ti chiedo di leggere e rispettare il regolamento del sito prima di utilizzarlo
  • Ti chiedo di leggere i Termini e Condizioni d'uso del sito prima di utilizzarlo
  • In qualità di Affiliato Amazon io ricevo un guadagno dagli acquisti idonei qualora siano presenti link al suddetto sito.

Permalink link a questo articolo: https://www.mauroalfieri.it/elettronica/rfid-arduino-seconda-parte.html

15 commenti

Vai al modulo dei commenti

  1. Ciao Mauro ci eravamo sentiti un poco di tempo fa per un sistema onlide di log e comando x arduino

    guarda se il mio tutorial ma soprattutto tutto il sito ti puo interessare ancora per un articolo di presentazione ne sarei felice

    ciao

    1. Ciao Carmelo,
      hai realizzato un progetto davvero interessante e mi piacerebbe dedicarti un articolo di presentazione.
      Ti chiedo di inviarmi un po di materiale in italiano da pubblicare corredato di foto,sketch e codice per le pagine php.

      Inoltre ti chiedo se il sito pensi di permettere a tutti i visitatori di creare il proprio database o il database è unico.

      Mauro

  2. sono contento che ti piaccia
    ti preparo un poco di materiale in italiano

    il database è unico e fittiziamente attraverso il gestionale lo suddivido in tabelle fra i vari utenti

    • Michele il 29 Novembre 2013 alle 20:25
    • Rispondi

    Ciao Mauro, vorrei un aiutino sto impazzendo.
    Allora il progetto che ho creato mi serve per poter entrare in casa tramite i tag rfid io vorrei che al passaggio del tag mi apra il portone e fin qui ok poi a distanza di 3 secondi se ripasso il tag mi apre le tapparelle in caso contrario esso torna in standby cioè se lo ripasso dopo 10 secondi mi aprirà di nuovo il portone bene quest’ultima parte non so proprio come fare se per favore potresti aiutarmi grazie

    1. Ciao Michele,
      il sfrutterei la funzione millis() per verificare il tempo trascorso tra il primo passaggio ed il secondo.

      Se il secondo passaggio avviene entro i 3s apri le tapparelle, altrimenti ritorni ad attendere il primo passaggio.

      Ti consiglio di leggere gli articoli sull’uso di tale comando: millis() e di approfondire l’uso delle funzioni negli sketch, ti semplificherà la vita.

      Mauro

    • Michele il 30 Novembre 2013 alle 12:41
    • Rispondi

    OK grazie

    1. Ciao Michele,
      non incollare codice nei commenti non arriva leggibile. Inoltre io non sono in grado di verificare che un codice funzioni solo leggendolo.
      Infine non ho il tempo di provare tutto il codice che mi inviate, ognuno degli utenti del blog ha un progetto differente.

      La conferma se il tuo codice funziona te la darà Arduino quando lo avrai caricato.

      Mauro

    • michele il 1 Dicembre 2013 alle 10:30
    • Rispondi

    ok scusami per il disagio

  3. …ma ciao!
    ho trovato il tuo video tutorial su youtube riguardante l’RFID con arduino e siccome sto per cimentarmi in un applicazione con gli rfid, avrei una domanda pratica da farti.
    Io ho un ID20 già funzionante in un applicazione ma devo prendere delle nuove schedine rfid.
    Le nuove schede quando le prendi hanno già intrinseco il loro tag?
    L’ID20 è solo lettore o anche scrittore?
    Queste due domande per capire..come faccio a memorizzare le nuove schede? Devo ricompilare il programma per ogni nuova scheda?? Memorizzo nello sketch tutte le schede in mio possesso? oppure uso uno shield per SD?
    Tu che soluzione consigli?

    grazie mille

    1. Ciao Geppo, ogni scheda che acquisti ha il proprio Tag e che io sappia l’ID20 é solo in grado di leggere i Tag e non di scrivere. L’idea della scheda SD card mi sembra molto buona per memorizzare i Tag che ti interessano per non dover riscrivere lo sketch ad ogni cambio Tag.

      P.s.: interessante il tuo sito/blog io sono un estimatore dei prodotti Playjuggling 🙂

    • Giuseppe il 14 Ottobre 2014 alle 21:55
    • Rispondi

    A proposito della domanda di Geppo e risposta di Mauro, vorrei precisare che ID12 è un lettore mentre ID20 è anche in grado di scrivere

    1. Grazie Giuseppe !!!

    • Giovanni il 31 Ottobre 2016 alle 13:05
    • Rispondi

    Salve Mauro, ho comprato questa shield RFID ID12LA, volevo sapere se posso registrare anche 20 tag diversi su una shield oppure ha qualche limitazione?
    Inoltre i tag a 125 khz sono con odici univoci già di fabbrica e possibile sovrascrivere questi tag oppure no?
    Legge tag differenti?
    Grazie mille

    Giovanni

    1. Ciao Giovanni,
      i limiti sono legati alla memoria arduino che stai utilizzando, come leggi si tratta di una memorizzazione in EEPROM da 5 byte per ID che vorrà dire 204 codici circa.
      Sull’univocità delle chiavi devi chiedere al produttore la conferma.

    • Giovanni il 31 Ottobre 2016 alle 14:42
    • Rispondi

    Grazie mille Mauro, gentilissimo, penso allora che con Arduino uno a 30 tag ci posso arrivare.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.