2 arduino con un lettore rfid

Sono d'accordo con te nel non uso delle stringhe ma non avendo praticità con la libreria e essendo l'utente in difficoltà volevo fargli maneggiare dati con cui ha dimestichezza e poi virare sul numerico.

cotestatnt:
avevo pensato di abbandonare questa libreria ma l'ho ripresa e ho provato il tuo consiglio ma non trova uguaglianze tra le chiavi enabledCards e actualCode, rimane in loop dicendomi

num...05654.....

GateA Enabled = 1
GateB Enabled = 1
GateC Enabled = 1
actualCode  =6230955
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled
Card with id 6230955enabled

e l'id 6230955 c'è nelle enabledCards,

l'avevo trasformata in string perche cosi la rilevava

codiceLetto += String (wg.getCode(), DEC);

questo è il codice che ho provato su tuo consiglio ma rimane in loop sia che la chiave c'è sia che non c'è

#include <Wiegand.h>


#define FALSE 0
#define TRUE  1
int i = 0;

WIEGAND wg;

unsigned long enabledCards[] = { 1000001, 6170130, 6230955, 1000004, 1000005 };

void setup() {

  Serial.begin(9600);
  Serial.println("num...05654.....");
  // PIN assigment and declaration for Arduino Mega
  //GATE A
  wg.D0PinA = 2;
  wg.D1PinA = 3;
  delay(75);
  //GATE B
  //con arduino uno va solo con pin 2 e 3...
  //usare mega 2560 se si vogliono piu gate
  wg.D0PinB = 18; //18
  wg.D1PinB = 19;  //19
  delay(75);
  //GATE C
  wg.D0PinC = 20;
  wg.D1PinC = 21;
  delay(75);
  // Reader enable

  wg.begin(TRUE, TRUE, TRUE);  // wg.begin(GateA , GateB, GateC)
  //wg.begin(FALSE, FALSE, TRUE);  // wg.begin(GateA , GateB, GateC)

}
//void(* Riavvia)(void) = 0;
void loop() {


  if (wg.available())
  {
    // Salvo il codice della scheda in una variabile lcoale

    unsigned long actualCode = wg.getCode();


    Serial.print("actualCode  =" );
    Serial.print(actualCode  );

    int arrayLen = sizeof(enabledCards) / sizeof(unsigned long); // può essere messo direttamente nel for

    for (int i = 0; arrayLen;  i++) {

      // contronto l'elemento i dell'array con il codice letto
      if (actualCode == enabledCards[i]) { // NON SERVE ALTRO!
        Serial.print("Card with id ");
        Serial.print(actualCode);
        Serial.println( "enabled");

      }

    }
  }
}

sorry Guglielmo

>imdany: potresti porre attenzione quando fai QUOTE e rispondi ? ... guarda il tuo post qui sopra ... è un miscugio di quiote, risposte, codice ...

Ti prego di usare il bottone in basso a destra More -> Modify e di modificare/correggere il post in modo da renderlo leggibile, Grazie.

Guglielmo

@imdany, il confronto con il codice letto funziona ed infatti l'if dove esegui la stampa sul monitor seriale è vero ed ottieni il risultato che hai postato.

Se ho capito bene, continua a printare sul monitor seriale l'ultima card letta all'infinito?

In questo caso significa che la libreria è scritta un po' con i piedi e restituisce wg.available() == true in continuazione una volta che ha letto un codice.

Prova ad aggiunger un actualCode = 0; nell'if dopo aver stampato sul serial monitor.

Edit:

non cambia nulla temo, perché nel loop successivo riassegna il valore nuovamente se questo non viene resettato dalla libreria.
Edit dell' edit:
C'è un errore nello sketch che mi era sfuggito:

 for (int i = 0; arrayLen<i;  i++) {

Comunque, anche se cambi libreria con una che funziona un po' meglio, il discorso non cambia: il codice della card è comunque un numero e non una stringa.

cotestatnt:
@imdany, il confronto con il codice letto funziona ed infatti l'if dove esegui la stampa sul monitor seriale è vero ed ottieni il risultato che hai postato.

cotestatnt:

 for (int i = 0; arrayLen<i;  i++) {

, mi sono spiegato male ,ho provato sia con un codice abilitato e mi dice che è enable e è ok ma me lo diceva anche con un codice non autorizzato,
errore sistemato ma ho scritto

 for (int i = 0; i < arrayLen ;  i++) {

ora stampa

2:42:16.059 -> actualCode  =6230955arrayLen =6
12:42:16.093 -> carta non trovata
12:42:16.126 -> carta non trovata
12:42:16.126 -> carta non trovata
12:42:16.160 -> Card with id 6230955enabled
12:42:16.194 -> carta non trovata
12:42:16.194 -> carta non trovata

adesso provo a vedere aggiungendo carte se il tempo di ricerca è accettabile...

cotestatnt:
Scusate, ma a me sfugge proprio il senso dell'utilizzo di stringhe e di tutte le conversioni e i passaggi necessari per utilizzarle, quando il risultato della lettura di una tessera RFID è un unsigned long....

Perché lui vorrebbe poter creare e aggiornare un semplice file di testo su SD con la lista degli ID abilitati, quindi gli serve in formato stringa per confrontarli più comodamente.

Non stampa nulla o non stampa solo il contenuto del'if all'interno del for?

Almeno actualCode =6230955 dovrebbe stamparlo in ogni caso (codice abilitato o meno).

docdoc:
quindi gli serve in formato stringa per confrontarli più comodamente.

Questione di punti di vista, io troverei più comodo (oltre che più veloce) scorrere il file riga per riga ed importare nell'array i valori trasformati in unsigned long.

cotestatnt:
Non stampa nulla o non stampa solo il contenuto del'if all'interno del for?

dopo aver corretto stampa e trova la carta il problema è che se io metto 200 codici ora che arriva alla fine ci mette un pò

3:05:25.203 -> GateA Enabled = 1
13:05:25.237 -> GateB Enabled = 1
13:05:25.237 -> GateC Enabled = 1
13:05:29.963 -> actualCode  =6170130arrayLen =199
13:05:29.997 -> carta non trovata
13:05:29.997 -> carta non trovata
.........
13:05:33.868 -> carta non trovata
13:05:33.868 -> carta non trovata
13:05:33.902 -> Card with id 6170130enabled

circa 4 secondi per 200 id un pò lento... devo studiare quello che consigliava Guglielmo ricerca binaria (ho capito come dovrebbe funzionare la ricerca, va per esclusione però non mi torna 2 alla 14 = 16384 è esempio riportato ma io con il mio numero devo lavorare a 2 alla 20 o sbaglio) (il totale dei miei ID da cercare è max 1500 .ma il mio numero da trovare in binario è 10111110001001110101011 tot 23 cifre quindi 2 alla 23esima

so che il mio metodo presentava errori ma come mai fino a quando stavo sotto ai 350 id la lettura e ricerca chiave era istantanea o quasi

ok funziona e ci mette pochissimo ,ci metteva tempo perche facevo scrivere ogni volta su seriale "non trovato"

13:24:46.913 -> actualCode  =6170130arrayLen =551
13:24:46.947 -> Card with id 6170130enabled

imdany:
circa 4 secondi per 200 id un pò lento...

4 secondi per 200 iterazioni su degli unsigned long, non è un po' lento, è TROPPO lento!!!

Edit:
ah ecco... ti stavo rispondendo ed ho visto l'ultimo messaggio.

Se vuoi ora affrontiamo il discorso di come caricare la lista dei codici abilitati dalla SD.

cotestatnt:
Se vuoi ora affrontiamo il discorso di come caricare la lista dei codici abilitati dalla SD.

volentieri!! però adesso sto lavorando con una mega, qualcuno aveva consigliato di lavorare con una eeprom aggiuntiva e come idea non mi dispiaceva (ora sto caricando su mega 2560 e sono al 58 % ,sulla uno non ci sta )però userei la SD per caricare su eeprom così poi la sd la posso togliere... sbaglio?

imdany:
userei la SD per caricare su eeprom così poi la sd la posso togliere... sbaglio?

Puoi fare più o meno come preferisci: aggiungere una EEPROM, usare solo la SD, collegare il mega ad una rete ed usare un database etc etc
Ma hai già una previsione di quanti codici validi saranno da memorizzare?

Prova a rifare i conti dello spazio occupato per tutti gli id che vuoi gestire perché prima ogni id occupava un byte, quindi ogni codice 10 byte, adesso ogni codice ne occupa quattro, quindi ci sta che ti basti la EEPROM interna, anche se, alla luce delle attuali implementazioni credo che la SD sia la soluzione migliore, anziché dover riprogrammare arduino ad ogni cambio codice, si toglie la SD, si aggiorna e si rimette la SD

imdany:
dopo aver corretto stampa e trova la carta il problema è che se io metto 200 codici ora che arriva alla fine ci mette un pò circa 4 secondi per 200 id un pò lento...

Se la lentezza era dovuta ai tanti Serial.print() e magari avevi la seriale a 9600 baud, è normale.
Ci potresti postare il "nuovo" codice "corretto", così ti diamo indicazioni più precise su come ottimizzare ulteriormente la cosa?

cotestatnt:
io troverei più comodo (oltre che più veloce) scorrere il file riga per riga ed importare nell'array i valori trasformati in unsigned long.

Si ma saremmo daccapo per l'eventuale problema dell'occupazione di SRAM di centinaia di codici... :wink:

fabpolli:
anziché dover riprogrammare arduino ad ogni cambio codice, si toglie la SD, si aggiorna e si rimette la SD

Infatti è questa la soluzione migliore anche secondo me.
Tra l'altro lascerei comunque in pace la EEPROM e non gli confonderei le idee con ricerche binarie o altro...

docdoc:
Si ma saremmo daccapo per l'eventuale problema dell'occupazione di SRAM di centinaia di codici... :wink:

Se i codici dovessero essere davvero tanti si potrebbe ovviare leggendo l'elenco a blocchi dalla SD.
Certo si introdurrebbe un ritardo "variabile" in funzione della posizione nell'elenco, ma con gli 8Kb di SRAM del mega sarebbe sensato solo se superiamo i 1000/1500 codici in totale (cosi da lasciarsi comunque un po' di margine di memoria libera).

docdoc:
magari avevi la seriale a 9600 baud, è normale.

si lo era, il codice è spedito ora ,e ho inserito 1650 id piu di cosi non ne metterò, per aggiungere i codici validi potrei farlo con un tag add mentre per eliminarlo in caso di perdita chiavi passerei da sd ,ma penso che la eeprom mi serva perche senza i 1650 id siamo a 8 per % di memoria su arduino mega con gli id inseriti siamo a 58% per quello la eeprom era interessante ,dal codice qui sott oho dovuto toglere i 1650 id perche andava oltre i 9000 .

//3/02/2021
//
//

#include <Wiegand.h>


#define FALSE 0
#define TRUE  1
int i = 0;

WIEGAND wg;

unsigned long enabledCardsA[] = { 6170131, 6170131,  6170132 };
unsigned long enabledCardsB[] = { 6170131, 13781090,  6230955 };
unsigned long enabledCardsC[] = { 6170131, 6170131,  6170130 };



const int Releserratura = 8;       // rele
const long delayserr = 750;



void setup() {

  Serial.begin(9600);
  pinMode(Releserratura, OUTPUT);
  Serial.println("num...0600.....");
  // PIN assigment and declaration for Arduino Mega
  //GATE A
  wg.D0PinA = 2;
  wg.D1PinA = 3;
  delay(75);
  //GATE B
  //con arduino uno va solo con pin 2 e 3...
  //usare mega 2560 se si vogliono piu gate
  wg.D0PinB = 18; //18
  wg.D1PinB = 19;  //19
  delay(75);
  //GATE C
  wg.D0PinC = 20;
  wg.D1PinC = 21;
  delay(75);
  // Reader enable

  wg.begin(TRUE, TRUE, TRUE);  // wg.begin(GateA , GateB, GateC)
  //wg.begin(FALSE, FALSE, TRUE);  // wg.begin(GateA , GateB, GateC)

}
//void(* Riavvia)(void) = 0;
void loop() {


  if (wg.available())
  {
    // Salvo il codice della scheda in una variabile lcoale

    unsigned long actualCode = wg.getCode();


    Serial.print("actualCode  = " );
    Serial.println(actualCode  );

    int arrayLenA = sizeof(enabledCardsA) / sizeof(unsigned long); // può essere messo direttamente nel for
    int arrayLenB = sizeof(enabledCardsB) / sizeof(unsigned long); // può essere messo direttamente nel for
    int arrayLenC = sizeof(enabledCardsC) / sizeof(unsigned long); // può essere messo direttamente nel for




    Serial.print("arrayLenA =" );
    Serial.println(arrayLenA );
    Serial.print("arrayLenB =" );
    Serial.println(arrayLenB );
    Serial.print("arrayLenC =" );
    Serial.println(arrayLenC );


    for (int i = 0; i < arrayLenA ;  i++) {

      // contronto l'elemento i dell'array con il codice letto
      if (actualCode == enabledCardsA[i]) { // NON SERVE ALTRO!
        Apri();
        Serial.print("Card with id ");
        Serial.print(actualCode);
        Serial.print( " Accettata su");
        Serial.println( " enabledCardsA");
        break;
      }
    }
    /////////////////////////
    for (int i = 0; i < arrayLenB ;  i++) {

      // contronto l'elemento i dell'array con il codice letto
      if (actualCode == enabledCardsB[i]) { // NON SERVE ALTRO!
        Apri();
        Serial.print("Card with id ");
        Serial.print(actualCode);
        Serial.print( " Accettata su");
        Serial.println( " enabledCardsB");
        break;
      }
    }

    for (int i = 0; i < arrayLenC ;  i++) {

      // contronto l'elemento i dell'array con il codice letto
      if (actualCode == enabledCardsC[i]) { // NON SERVE ALTRO!
        Apri();
        Serial.print("Card with id ");
        Serial.print(actualCode);
        Serial.print( " Accettata su");
        Serial.println( " enabledCardsC");
        break;
      }
    }
    //  else {
    //  Serial.println( "carta non trovata");
    // }

  }
}



void Apri() {
  digitalWrite(Releserratura, HIGH );
  Serial.println("Releserratura, HIGH");

  delay(delayserr);
  digitalWrite(Releserratura, LOW );
  Serial.println("Releserratura, LOW");


}

Potresti anche fare tutto in RAM, ma non avresti un buon "margine" di memoria libera per il resto dello sketch.

Al posto di una EEPROM valuta anche l'utilizzo di una F-RAM i2c che presenta diversi vantaggi rispetto alle EEPROM (velocità, cicli di scrittura massimi, consumi etc etc).
Si trovano anche delle breakout board già pronte, il che facilita di molto le connessioni.

AT24C256 sto aspettando il corriere per ora provo a giocare con queste

buongirono a tutti , schedina eeprom supplementare arrivata ,ho le prime domande,

la scheda è 256K ,ho provato a caricare dati con uno sketch di esempio e ho fatto la lettura con un altro esempio.

ho visto che ci sono 1024 "righe"(**1024 bytes) ** e su una riga non riesco a mettere il mio id penso la mia domanda è : come faccio a farceli stare tutti (1500 id che variano di lunghezza tra gli 8 e i 10 numeri decimali?

fabpolli:
sono 32K x 8 (256 Kbit) quindi 32K se memorizzati come stringhe sono più di 2500 codici consideranto i caratteri CRLF di ogni riga, se ometti uno di questi o suddividi i codici con un solo carattere (Es. la virgola) aumenti ancora di più il numero di codici gestibili

Ho fatto un test per la lettura basandomi su 2 alla 30esima che è circa un decimale a dieci cifre, mi son basato sul calcolo del consiglio di Guglielmo e l'ho moltiplicato per 3 perché penso che mi servano almeno 3" righe "per memorizzare il mio dato, quindi ho provato a leggere 90 righe allocazioni di memoria e i tempi sono ragionevoli, tutto questo per vedere i tempi per la ricerca binaria. allego tempi di lettura.

15:26:28.475 -> ecco i dati   
15:26:28.475 -> 0	C6
15:26:28.475 -> 1	9
15:26:28.475 -> 2	C6
15:26:28.510 -> 3	65
15:26:28.510 -> 4	70
15:26:28.510 -> 5	6F
15:26:28.510 -> 6	6C
15:26:28.510 -> 7	6E
................
.......
5:26:29.049 -> 87	6C
15:26:29.049 -> 88	20
15:26:29.049 -> 89	20
15:26:29.083 -> 90	20
15:26:29.083 -> eepromlength1024

mezzo secondo penso sia ok. ho detto troppe cavolate ??
scrivo con questo

/*
 * EEPROM Write
 *
 * Stores values read from analog input 0 into the EEPROM.
 * These values will stay in the EEPROM when the board is
 * turned off and may be retrieved later by another sketch.
 */

#include <EEPROM.h>

/** the current address in the EEPROM (i.e. which byte we're going to write to next) **/
int addr = 0;
int ii = 0;

//5e2612                                        94,38, 18DEC
//unsigned long enabledCardsA[3] = { 94,38, 18 };//5e-26-12 HEX
int enabledCardsA[3] = {11111110,00000011, 11111110 };//5e-26-12 HEX
int eepromlength= 0;

void setup() {
  /** Empty setup. **/
  Serial.begin(9600);
  eepromlength=EEPROM.length();
  Serial.print("eepromlength");
  Serial.println(eepromlength);
  
  for (int i = 0; i < 1091 ;  i++) {
     scrivi();
  }
   
}

void loop() {
  
  }

  void scrivi(){
  /***
    Need to divide by 4 because analog inputs range from
    0 to 1023 and each byte of the EEPROM can only hold a
    value from 0 to 255.
  ***/

  //int val = analogRead(0) / 4;
 int val = enabledCardsA[ii];


  
  /***
    Write the value to the appropriate byte of the EEPROM.
    these values will remain there when the board is
    turned off.
  ***/

  EEPROM.write(addr, val);
Serial.print(" addr  = ");
Serial.print(addr);
Serial.print(" val  = ");
Serial.println(val);
  /***
    Advance to the next address, when at the end restart at the beginning.

    Larger AVR processors have larger EEPROM sizes, E.g:
    - Arduno Duemilanove: 512b EEPROM storage.
    - Arduino Uno:        1kb EEPROM storage.
    - Arduino Mega:       4kb EEPROM storage.

    Rather than hard-coding the length, you should use the pre-provided length function.
    This will make your code portable to all AVR processors.
  ***/
  addr = addr + 1;
  ii++;
if (addr == EEPROM.length()) {
 //  if (ii == 3)   {
  addr = 0;
 // ii = 0;
   // exit;
  }

  /***
    As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an
    EEPROM address is also doable by a bitwise and of the length - 1.

    ++addr &= EEPROM.length() - 1;
  ***/


  delay(1);
}

leggo con

/*
 * EEPROM Read
 *
 * Reads the value of each byte of the EEPROM and prints it
 * to the computer.
 * This example code is in the public domain.
 */

#include <EEPROM.h>

// start reading from the first byte (address 0) of the EEPROM
int address = 0;
byte value;
int i= 0;
int eepromlength= 0;

 

void setup() {
  // initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("ecco i dati   ");
//leggi();

 for (int i = 0; i <91 ;  i++) {
  leggi();
 }
  eepromlength=EEPROM.length();
  Serial.print("eepromlength");
  Serial.println(eepromlength);
  
}

void loop() {
  }

  void leggi() {
  // read a byte from the current address of the EEPROM
  value = EEPROM.read(address);

  Serial.print(address);
  Serial.print("\t");
  Serial.print(value, HEX);
  Serial.println();

  /***
    Advance to the next address, when at the end restart at the beginning.

    Larger AVR processors have larger EEPROM sizes, E.g:
    - Arduno Duemilanove: 512b EEPROM storage.
    - Arduino Uno:        1kb EEPROM storage.
    - Arduino Mega:       4kb EEPROM storage.

    Rather than hard-coding the length, you should use the pre-provided length function.
    This will make your code portable to all AVR processors.
  ***/
  address = address + 1;
 if (address == EEPROM.length()) {
   // if (address == 30) {
   eepromlength=EEPROM.length();
    address = 0;
  }

  /***
    As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an
    EEPROM address is also doable by a bitwise and of the length - 1.

    ++address &= EEPROM.length() - 1;
  ***/

 delay(1);
}

come li devo scrivere i miei dati ? binario decimale esadecimale?

imdany:
ho visto che ci sono 1024 "righe"(**1024 bytes) ** e su una riga non riesco a mettere il mio id penso la mia domanda è : come faccio a farceli stare tutti (1500 id che variano di lunghezza tra gli 8 e i 10 numeri decimali?

Ancora con questi valori decimali??... E basta un po'!... :smiley:

Già te l'avevo descritto: se gli ID sono composti da 4 byte, e li memorizzi in binario sono 4 byte, se li memorizzi in esadecimale sono 8 byte, se li memorizzi in decimale, tra 8 e 10 più carattere terminatore fanno mediamente 9 byte ma essendo a dimensione variabile si gestiscono malissimo. Quindi la scelta è, escludendo la memorizzazione decimale che è sicuramente la peggiore e meno efficiente, o la soluzione binaria o quella esadecimale.

Quella binaria è la soluzione più efficiente ma che ti costringe a programmare gli ID come valori binari quindi complicato da fare per un "umano". Quella esadecimale è la soluzione meno efficiente delle due vista la doppia occupazione, ma che ti consente di trattare gli ID come una sequenza di gruppi da 8 caratteri o righe.

Per il supporto, visto che hai preso la EEPROM devi anche capire come programmare la EEPROM, ossia se è più semplice programmare quella piuttosto che fare un semplice file testuale in una schedina SD. Indovia cosa ti consiglio? :wink: