Salvare tessere rfid nella EEPROM

Salve,
Nella EEPROM dell'arduino uno voglio salvare i codici di alcune tessere rfid. In pratica daĺlo sketch voglio indicare un'unica chiave master che quando avvicinata vicino al sensore permette di entrare in una sorta di modalità di programmazione dove è possibile salvare altre tessere rfid. Mi date delle linee guida su come posso procedere?
Nb. Ipotizziamo che i codici delle tessere sono delle stringhe.

1 Like

ti conviene ipotizzare che i codici delle tessere siano 4 (o 6 non ricordo) byte e quindi ogni 4 (o 6 letture) hai un codice memorizzato.
per il programma quando il lettore ti da un codice prestabilito (quello del master) chiedi la nuova tessera e poi vai a memorizzarla nel posto che tu sai essere quello giusto sulla eeprom :smiley:
come lo sai qual'è il posto giusto?, semplice :slight_smile: nella prima posizione memorizzi qual'è l'ultimo indirizzo scritto, per cui leggi il primo byte della eeprom al valore letto sommi la lunghezza del codice e ottieni la nuova posizione di scrittura, salvi questo numero nella locazione zero e scrivi i 4/6 bytes nella nuova posizione

...qualcosa del genere insomma :smiley:

Patrick_M:
ti conviene ipotizzare che i codici delle tessere siano 4 (o 6 non ricordo) byte e quindi ogni 4 (o 6 letture) hai un codice memorizzato.
per il programma quando il lettore ti da un codice prestabilito (quello del master) chiedi la nuova tessera e poi vai a memorizzarla nel posto che tu sai essere quello giusto sulla eeprom :smiley:
come lo sai qual'è il posto giusto?, semplice :slight_smile: nella prima posizione memorizzi qual'è l'ultimo indirizzo scritto, per cui leggi il primo byte della eeprom al valore letto sommi la lunghezza del codice e ottieni la nuova posizione di scrittura, salvi questo numero nella locazione zero e scrivi i 4/6 bytes nella nuova posizione

...qualcosa del genere insomma :smiley:

grazie per i consigli ..ho iniziato a scrivere un po di codice:

#include <EEPROM.h>
#include <MFRC522.h>


#define resetUID 5 //pulsante per il reset delle tessere memorizzate nella EEPROM

// Create MFRC522 instance.
#define SS_PIN 10
#define RST_PIN 9
MFRC522 rfid(SS_PIN, RST_PIN);

byte cardMaster [] { 9, 221, 218, 43};
byte readCard[4];   // Stores scanned ID read from RFID Module
//byte readEEPROM[4]; // contiene l'UID della tessera contenuta nella EEPROM

void setup(){
  Serial.begin(9600);
  SPI.begin();
  rfid.PCD_Init();
  pinMode (resetUID, INPUT_PULLUP);
  Serial.print("Codice UID della card Master:\t");
  for(int i = 0; i < 4; i++){        
    Serial.print(cardMaster[i]);
  }
  Serial.println();
  Serial.println("_________________________");
}

void loop(){
  int buttonState= digitalRead(resetUID);
  if (buttonState == LOW)
    resetEEPROM();
    
  if (getUID() && !letturaCard())
    addCard ();
  delay(10);
}

bool getUID()
{
  if(rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()){
      Serial.print("Letta tessera con codice UID:\t");
      for(int i = 0; i < 4; i++){
        readCard[i] = rfid.uid.uidByte[i]; // vado a memorizzare l'UID letto in un array
        Serial.print(readCard[i]);
      }
      Serial.println();
      rfid.PICC_HaltA();
      return true;
  }
}


/****   Questa routine viene richiamata per scrivere gli UID delle tessere lette nella EEPROM   ****/
void addCard ()
{
  int start= EEPROM.read(0); // vado a vedere l'ultima cella memorizzata, inizialmente vale 0
  for (int i=0; i < 4; i++) {
    EEPROM.write (start += 1, readCard[i]); // vado a memorizzare l'UID a partire dalla cella successiva all'ultima memorizzata
    EEPROM.write (0, start);
  }
}

bool letturaCard () // vado a leggere UID tessere dalla EEPROM
{
  int i=1;
  //bool flag = false;
  while (false) {
    for (int j=0; j < 4; j++) {
      if (readCard[j] = EEPROM.read(i + j)){
        Serial.println("Tessera presente nella EEPROM");
        return true;
      }
    }
    i = i + 4;
  } 
}


/*bool letturaCard () // vado a leggere UID tessere dalla EEPROM
{
  int num= EEPROM.read(0);
  for (int i = 1; i < num; i++) {
    for (int j=0; j < 4; j++) {
      if (readCard[j] = EEPROM.read(i + j)){
        //azioni..
        Serial.println("Tessera presente nella EEPROM");
        return true;
      }
    }
  }
}*/

void resetEEPROM()
{
  for (int i=0; i < EEPROM.length(); i++) {
    EEPROM.write(i, 0);
  }
  Serial.println("EEPROM svuotata!!");
  Serial.println("__________________");
}

ho un problema nella funzione bool letturaCard (), ovvero qui vado a verificare se l'UID letto è già presente nella EEPROM prima di andarlo a memorizzare, ebbene l'UID risulta sempre memorizzato nella EEPROM e di conseguenza non lo va a memorizzare. Se vado a richiamare solamente la funzione che accoda i codici UID nella EEPROM funziona correttamente, chiaramente ci saranno dei duplicati. Come posso correggere l'errore?

Innanzitutto ripassa la differenza tra = e == in C ;).

E poi tieni conto che perché la card sia già memorizzata, TUTTI i 4 byte dello UID devono corrispindere. Per come l'hai scritto tu, appena viene verificato che il primo byte corrisponde, la funzione ritorna subito.

SukkoPera:
Innanzitutto ripassa la differenza tra = e == in C ;).

hai ragione, sarà stato un errore di distrazione.

SukkoPera:
E poi tieni conto che perché la card sia già memorizzata, TUTTI i 4 byte dello UID devono corrispindere. Per come l'hai scritto tu, appena viene verificato che il primo byte corrisponde, la funzione ritorna subito.

in effetti rileggendo bene il codice è come dici tu, ovvero verificato il primo byte esce dal ciclo per condizione vera, senza verificare gli altri tre byte. Ho quindi riscritto così il codice:

bool letturaCard () // vado a leggere UID tessere dalla EEPROM
{
  int i=1;
  int uguale = 0;
  while (false) {
    for (int j=0; j < 4; j++) {
      if (readCard[j] == EEPROM.read(i + j)){
        uguale += 1;
      }
    }
    if (uguale == 4) {
      Serial.println("Tessera presente nella EEPROM");
      return true;
    }
    i = i + 4;
  } 
}

ma nemmeno sembra funzionare, mi suggerisci come posso modificare? Grazie mille in anticipo.

Secondo te, quante volte verrà eseguito un while (false)?

SukkoPera:
Secondo te, quante volte verrà eseguito un while (false)?

Ho messo while (false) con la speranza che il ciclo continuasse fin quando non ritorno true. Questo ciclo while esterno mi serve per ciclare la EEPROM, ma penso che già l'hai intuito.
Comunque ho messo while (true) oppure while (1) e nel monitor seriale mi stampa sempre: "Tessera presente nella EEPROM" in loop, senza che io avvicini una tessera al sensore, come se la variabile "int uguale" fosse uguale a 4, ma in realtà dovrebbe stare a 0.

while (false) non entra nemmeno nel ciclo, di fatto è come togliere dallo sketch tutto quel che ci hai messo dentro. Cerca di capire bene questa cosa.

Perché non lo sostituisci con un altro for, se l'intenzione è ciclare tutta la EEPROM? Così puoi inglobarci anche l'i = i + 4 finale.

Poi, uguale andrà rimesso a 0 a ogni iterazione di questo for esterno, pensaci.

Infine, readCard conviene passarlo come parametro.

SukkoPera:
while (false) non entra nemmeno nel ciclo, di fatto è come togliere dallo sketch tutto quel che ci hai messo dentro. Cerca di capire bene questa cosa.

Perché non lo sostituisci con un altro for, se l'intenzione è ciclare tutta la EEPROM? Così puoi inglobarci anche l'i = i + 4 finale.

Poi, uguale andrà rimesso a 0 a ogni iterazione di questo for esterno, pensaci.

Infine, readCard conviene passarlo come parametro.

ho seguito i tuoi suggerimenti, modificando in questo modo la funzione:

bool letturaCard () // vado a leggere UID tessere dalla EEPROM
{
  //int i=1;
  //int uguale = 0;
  for (int i=1; i < EEPROM.length(); i+=4) {
    int uguale = 0;
    for (int j=0; j < 4; j++) {
      if (readCard[j] == EEPROM.read(i + j)){
        uguale += 1;
      }
    if (uguale == 4) {
      Serial.println("Tessera presente nella EEPROM");
      return true;
    }
      
    }
    /*if (uguale == 4) {
      Serial.println("Tessera presente nella EEPROM");
      return true;
    }*/
    //i = i + 4;
  } 
}

l'unica modifica che non ho fatto è stata passare l'array come parametro, perchè sinceramente non capisco a cosa può servire.
Tuttavia nonostante le modifiche fatte, continua a looppare sulla print "Tessera presente nella EEPROM", senza che io avvicino una tessera vicino al sensore.

OK, ora devi sistemare la funzione getUID(), che deve ritornare FALSE se non c'è alcuna scheda appoggiata al lettore.

SukkoPera:
OK, ora devi sistemare la funzione getUID(), che deve ritornare FALSE se non c'è alcuna scheda appoggiata al lettore.

ok.. seguendo questo consiglio e facendo un altro paio di modifiche, finalmente funziona ...grazie mille. Curiosità mia perchè dicevi che l'array readCard[] conviene passarlo come parametro?

Perché non c'è alcuna ragione per cui debba essere una variabile globale, concettualmente lo vedo meglio come parametro da passare alle varie funzioni.

In generale non è buona pratica di programmazione avere troppe variabili globali, porta a confusione e ad interazioni non volute. Poi vabbeh, nella programmazione embedded spesso si tende ad essere un po' più pratici e meno puristi, ma è comunque una cosa da evitare quando possibile. In questo caso non vedo motivi per mantenere readcard globale.