Cercare un valore HEX all'interno di una tabella

Ciao a tutti,
sto realizzando un lettore rfid che mi confronti il valore letto da una tessera (esadecimale) con una tabella, per validare il valore e consentire l'attivazione di un relè.
Fin'ora l'ho fatto con pochi valori, ma il mio obiettivo è di arrivare a confrontare 100 valori. Ho provato una metodologia, ma ho esaurito la memoria di arduino uno.
Il metodo era questo:

...
String codice1 = "AABBCCDD";
String codice2 = "BBCCDDEE";
String codice3 = "CCDDEEFF";
....
{
     tessera+= String (RC522.serNum[i],HEX);
    tessera.toUpperCase();
   }
   Serial.println(codiceLetto);
   if(verifica(tessera,codice1)||verifica(tessera,codice1)||verifica(tessera,codice1)){
 Serial.println("Tessera autorizzata");
     digitalWrite (rele, HIGH);
     delay (1000);
     digitalWrite (rele, LOW);
   }else{
     Serial.println("Tessera non autorizzata");

ma capite bene che fare un if con 100 condizioni, fa crashare arduino.
Avete qualche suggerimento da darmi per permettermi di ricercare, un valore ricavato dalla lettura di una scheda, in un elenco?
Grazie.

Metti un singolo if all'interno di un ciclo for reiterato tante volte quanti sono gli elementi da confrontare.

Edita il post e metti il codice nei tag code.

Eviterei l'uso delle string...
Con le stringhe C una cosa così dovrebbe funzionare

#define MAX_ELENCO 5
char *elenco[MAX_ELENCO] = {"AABBCCDD",
                            "EEFFGGHH",
                            "IILLMMNN",
                            "OOPPQQRR",
                            "SSTTUUVV"};
                     
byte i;
bool trovato;
char codice[9];

  trovato = false;
  i = 0;
  while (!trovato && (i < MAX_ELENCO)) {
    if (strcmp(elenco[i],codice) == 0) {
      trovato = true;
    }
    i++;
  }
  if (trovato) {
    // ho trovato il codice nell'elenco
  }

ho messo i tag code :slight_smile:

fratt:
Edita il post e metti il codice nei tag code.

Funziona...
ma se metto 100 valori, non corro il rischio di mandare in palla Arduino ?

e perché dovrebbe?

>caligolas: Quando si quota un post, NON è necessario riportarlo (inutilmente) tutto; bastano poche righe per far capire di cosa si parla ed a cosa ci si riferisce, inoltre, se si risponde al post immediatamente precedente, normalmente NON è necessario alcun "quote" dato che è sottinteso. :slight_smile:

Gli utenti da device "mobile" (piccoli schermi) ringrazieranno per la cortesia :wink:

Guglielmo

P.S.: Ho troncato io il "quote" dal tuo post più sopra :wink:

Dove sbaglio :confused:
Mi dice sempre che la tessera che inserisco è valida.

#include <SPI.h>
#include <RFID.h>
#define SDA_PIN 15
#define RESET_PIN 9
#define delayRead 1000
#define rele 2
RFID RC522(SDA_PIN, RESET_PIN); 
#define MAX_ELENCO 3 
char *elenco[MAX_ELENCO] = {"FCA2333B56",
                            "BAF1A51AF4",
                            "0000000000"};
void setup()
{ 
  Serial.begin(9600);
  SPI.begin();  
  RC522.init(); 
  Serial.println("inizio");
  pinMode(rele,OUTPUT);
}
  
void loop() 
{
   byte i;
   if (RC522.isCard()) 
      {
      RC522.readCardSerial();
      String codiceLetto ="";
      Serial.println("Codice delle tessera letto:");
      for(i = 0; i <= 4; i++)
      {
      codiceLetto+= String (RC522.serNum[i],HEX);
      codiceLetto.toUpperCase();
      }
      Serial.println(codiceLetto);
      bool trovato;
      char codice[9];

  trovato = false;
 i = 0;
  while (!codiceLetto && (i < MAX_ELENCO)) {
    if (strcmp(elenco[i],codice) == 0) {
      codiceLetto = true;
    }
    i++;
  }
     if  (trovato == 0){
            Serial.println("Tessera autorizzata");
            digitalWrite (rele, HIGH);
            delay (1000);    
            digitalWrite (rele, LOW);
 } 
    else
  {
            Serial.println("Tessera non autorizzata");
    }
            delay(delayRead);  
  } }

Hai mescolato le cose... ed è normale che non funzioni...
Nel while la tua variabile codiceLetto non centra nulla.
La variabile codice che ho usato per il confronto devi anche inizializzarla oltre che dichiararla.

Non conosco la libreria RFID ma sei sicuro che non si riescano a gestire i codici con delle variabili numeriche? Ti semplificheresti la vita...

EDIT: se i valori HEX che leggi li tratti come numero dovresti starci con degli unsigned long. A quel punto usi == e passa la paura.

caligolas:
Dove sbaglio :confused:
Mi dice sempre che la tessera che inserisco è valida.

Te lo spiegherò meglio qui sotto, ma, anche in questo caso, hai mescolato le cose soprattutto per quanto riguarda il discorso "String" contro "stringhe C" quindi per prima cosa ti conviene approfondire meglio (cercando in rete, ci sono parecchie pagine e tutorial) il discorso "stringhe C" ed EVITARE del tutto di usare gli oggetti String che, seppur "comodi" da usare, su Arduino sono fortemente sconsigliati.

Poi per aiutarti a comprendere meglio i tuoi stessi programmi, dovresti indentare correttamente il codice (per farlo fare un automatico dall'IDE premi Ctrl-T, e poi cerca di mantenere quello stile, e possibilmente imposta 2 caratteri per l''indentazione), cosa che aiuta anche noi a leggerli meglio visto che nel codice che hai postato ci sono "fisarmoniche" di linee di codice e graffe... :wink:

Detto questo, veniamo al tuo codice.
Tu hai quindi sostituito le variabili String iniziali con l'array che ti ha correttamente consigliato @fratt ma poi tu dal lettore leggi in una variabile "String codiceLetto" (anche questa è da eliminare) e cerchi di confrontare queste due usando la funzione C "strcmp()" che invece serve per confrontare due stringhe "C" non oggetti della classe "String".

Poi, altro consiglio, anche se prendi codice trovato in rete non dare mai per scontato che sia perfetto al 100% e cerca di capire cosa fa e magari anche COME lo fa. Per dire, quel codice che stai cercando di creare mi pare chiaramente "derivato" da alcuni piccoli esempi postato in giro su varie pagine, ma per quelli l'uso di "String" è stato fatto esclusivamente per semplificare l'esempio, non per farne un codice realmente affidabile e/o utilizzabile.
E, infine, quando devi capire come fare qualcosa, cerca di SEPARARE i problemi e sperimentarli uno per volta. Quindi PRIMA vedi come acquisire correttamente le informazioni della card, e DOPO usare questa informazione per verificarne l'abilitazione.

Veniamo quindi a come stai leggendo il codice della card:

    String codiceLetto ="";
    Serial.println("Codice delle tessera letto:");
    for(i = 0; i <= 4; i++)
    {
      codiceLetto+= String (RC522.serNum[i],HEX);
      codiceLetto.toUpperCase();
    }
    Serial.println(codiceLetto);

L'array "serNum[]" contiene i byte ricevuti dalla card, tu qui li converti in esadecimale e alla fine li confronti con le chiavi abilitate. Teoricamente va bene, ma oltre al discorso di non mischiare "String" con "stringhe C" ossia in questo caso devi leggere il dato in una "stringa C", c'è anche il discorso che convertendo in stringa esadecimale con quel metodo non garantisci che il dato sia composto sempre esattamente da 2 caratteri esadecimali ad esempio "String(5,HEX)" restituisce "5" non "05". E tra l'altro devi pure convertire tutto in maiuscolo...

Quindi visto che i codici delle card abilitate li imposti come stringa C, dovresti usare anche come buffer una "stringa C", ossia "char []", con dimensione pari alla dimensione massima del codice (nel tuo caso 10 caratteri ovvero 5 byte) più uno, ed accumulare lì la stringa esadecimale.

Ma non è la soluzione più pratica, visto che la libreria della card usa un array di byte, per cui per il principio che è inutile fare conversioni non necessarie o non semplicissime "complicando" inutilmente il codice, dovresti ad esempio impostare i codici abilitati non come stringa, ma anche questi come byte.
In tal caso non serve più "leggere" il codice corrente dentro ad una variabile (puoi lasciare un ciclo per la sola visualizzazione su seriale del codice letto) e tutte le relative conversioni, ma ti basta confrontarlo con quelli abilitati che imposterai come:

...
#define MAX_ELENCO 3
#define DIM_CODICE 5
byte elenco[MAX_ELENCO][DIM_CODICE] = {
  {0xFC, 0xA2, 0x33, 0x3B, 0x56},
  {0xBA, 0xF1, 0xA5, 0x1A, 0xF4},
  {0x00, 0x00, 0x00, 0x00, 0x00}
};
...

Quindi per mostrare sulla seriale il codice della tessera ti basta fare:

    // Visualizza il codice della tessera
    Serial.println("Tessera:");
    for(byte i = 0; i <= 4; i++) {
      // Se servono due caratteri aggiungo lo zero iniziale
      if (RC522.serNum[i] < 16 ) Serial.print("0");
      Serial.print(RC522.serNum[i], HEX);
      Serial.print(" ");
    }
    Serial.println();

Per confrontare i codici ora ti basta "contare" quanti byte di una stessa card corrispondono al valore letto (vedi anche i commenti che ti ho messo, e ti consiglio sempre di metterli anche tu):

...
    byte ok; // Indica quanti byte corrispondono
    // Ciclo le card abilitate
    for (byte card=0; card<MAX_ELENCO; ++card) {
      // Conto quanti byte coincidono
      ok = 0;
      for(byte i=0; i<DIM_CODICE; i++) {
        // Confronto i byte
        if (RC522.serNum[i] != elenco[card][i]) 
          break; // Se non corrisponde, passa alla card successiva
        // Contiamo il byte giusto
        ++ok;
      }
      // Se l'ho trovata, esco
      if (ok == DIM_CODICE)
        break;
    }
    if (ok == DIM_CODICE){
      Serial.println("autorizzata");
...

PS non ti assicuro che funzioni tutto, sta a te iniziare a capire il codice, come funziona, e se il caso anche come correggerlo.. :wink:

Grazie @fratt e @docdoc per il tempo dedicatomi alla spiegazione. Metto in pratica tutto quello che mi avete illustrato. Grazie ancora..

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.