utilizzo il seguente lettore Rfid http://www.seeedstudio.com/depot/125khz-rfid-module-uart-p-171.html?cPath=144_153
e da quanto dice il rispettivo datasheet (http://www.seeedstudio.com//depot/datasheet/RDM630-Spec..pdf), comunicando con l interfaccia seriale (pagina 4 del datasheet), il primo byte letto è il numero 2 decimale, i successivi 10 byte sono i codici ASCII delle cifre del TAG letto, i 2 successivi byte per il checksum e un ultimo con il numero 3 di default.
Il mio problema riguarda i 10 caratteri letti, che dovrebbero corrispondere all'ID del tag avvicinato al lettore.
Posto un esempio. Se do in pasto al lettore il tag con codice ID: 0013530444 , il lettore RFID mi riporta in seriale la seguente sequanza:
I received: 2
I received: 51
I received: 67
I received: 48
I received: 48
I received: 67
I received: 69
I received: 55
I received: 53
I received: 52
I received: 67
I received: 67
I received: 66
I received: 3
Ovviamente il primo e l'ultimo byte ricevuto mi stanno bene, perchè devono essere tali.
Il terzultimo ed il penultimo sono il checksum.
Ma i restanti 10, non mi convincono affatto. Per esempio, dato che l'ID del tag inizia per 0013... i primi 4 byte letti non dovrebbero essere 48,48,49,51... ?!?!?
Vi posto il codice con il quale leggo i valori da un Arduino ethernet R3:
int incomingByte = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
incomingByte = Serial.read();
//stampo sulla seriale di DEBUG
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}
premetto poi che il codice di lettura l'ho trovato sul sito ufficiale di Arduino.. non so davvero da cosa possa dipendere tutto ciò!
... Note: the 10 ASCII characters grouped as 5 hex data needs to be further processed as you may find that the 5 hex data is not equal to the number marked on the tags in Decimal. Actually the tag number is equal to the later 4 bytes in decimal. For example, the card number is 62E3086CED, the corresponding number marked on the tag should be 60717296877 which is the Decimal format of E3086CED. ...
Ha perfettamente ragione! Non mi era mai capitato che il valore letto fosse differente da quella scritto all'esterno del tag... solitamente ho utilizzato altri modelli di dispositivo lettore-chiave RFID.
Che dire... GRAZIE MILLE!
Ulteriore problema... non riesco a risalire al numero scritto fuori della card, partendo dei codici letti dalla seriale dell'arduino!
Anche prendendo in considerazione i soli byte interessati al campo"data" come scritto nel datasheet, e trascurando quindi sia header, sia footer, sia il checksum, non riesco a stampare a video il codice scritto all'esterno della scheda!
Qualche idea su come fare?
Ho anche provato a convertire i caratteri nei rispettivi valori interi, ma nada...
aiuto
Forse mi sono spiegato male, la corrispondenza l'ho verificata, ma il mio problema è su come ricreare da codice la sequenza esadecimale e stamparla poi a video.
L'ulteriore passo è, una volta letti tutti i byte, calcolare il checksum. In tutta sincerità, non so dove mettere mano al codice quando si tratta di dover raggruppare i byte hex !
Esiste una comoda funzione strtoul() che converte una stringa in un valore numerico unsigned long, mentre per il calcolo del checksum devi considerare tutti i 5 byte ricevuti ed operare su di essi uno XOR (operatore ^)
char x = "00CE754C"; // sequenza ricevuta
unsigned long y = 0;
y = strtoul(x, NULL, 16);
ciao, per prima cosa grazie della dritta.
Credo char x ="qwekn45n5"; si sbagliata... cioè dovrebbe essere char x[] ="qwekn45n5";
i valori conviene sempre leggerli come char o magati per il checksum ecc, farebbe comodo vederli come byte?
Temo che il tutto abbia dell'incredibile.
Posto il codice per chiarezza
// Project 45
#define lockPin 9
//#define speakerPin 9
#define tx 3
#define rx 2
#define unlockLength 2000
#include <SoftwareSerial.h>
SoftwareSerial rfidReader = SoftwareSerial(rx, tx);
int users = 3;
char* cards[] = { // valid cards
"11308547",
"3D00251C27",
"3D0029E6BF",
};
char* names[] = { // cardholder names
"Tom Smith",
"Dick Jones",
"Harry Roberts"
};
void setup() {
pinMode (lockPin, OUTPUT);
//pinMode (speakerPin, OUTPUT);
digitalWrite(lockPin, LOW);
Serial.begin(9600);
rfidReader.begin(9600);
}
void loop()
{
char cardNum[10]; // array to hold card number
byte cardBytes[6]; // byte version of card number + checksum
int index=0; // current digit
byte byteIn=0; // byte read from RFID
byte lastByte=0; // the last byte read
byte checksum = 0; // checksum result stored here
int i=1;
char x[8];
unsigned long y=0;
//Serial.flush();
//rfidReader.flush();
if (rfidReader.read()==2)
{
// read the RFID reader
while(index<12)
{ // 12 digits in unique serial number
byteIn = rfidReader.read(); // store value in byteIn
delay(100);
Serial.print(index);
Serial.print(") - Byte: ");
Serial.print(byteIn);
Serial.print(" -> Integer: ");
if ((byteIn==1) || (byteIn==2) || (byteIn==10) || (byteIn==13)) {return;}
// if STX, ETX, CR or LF break
if (index<10) {cardNum[index]=byteIn;} // store first 10 HEX digits only?(last 2 are checksum)
// convert ascii hex to integer hex value
if ((byteIn>='0') && (byteIn<='9'))
{
byteIn -= '0';
}
else if ((byteIn>='A') && (byteIn<='F'))
{
byteIn = (byteIn+10)-'A';
}
Serial.print(byteIn);
if(index==0||index==1)
Serial.print(" [IGNORATO]");
if(index==10||index==11)
Serial.print(" [CHECKSUM]");
Serial.println();
if ((index & 1) == 1)
{ // if odd number merge 2 4 bit digits into 8 bit byte
cardBytes[index/2]= (byteIn | (lastByte<<4)); // move the last digit 4 bits?left and add new digit
if (index<10) {checksum ^= cardBytes[index/2];} // tot up the checksum value
}
lastByte=byteIn; // store the last byte read
index++; // increment the index
if (index==12) {cardNum[10] = '\0';} // if we have reached the end of all digits?add a null terminator
}
//rfidReader.flush(); // togliendo questo commento, al passaggio successivo mantengo l'errore nella stringa
Serial.println(cardNum); // print the card number
int cardIndex =checkCard(cardNum); // check if card is valid and return index number
if(cardIndex>=0 && (cardBytes[5]==checksum))
{ // if card number and checksum are valid
Serial.println("Card Validated");
Serial.print("User: ");
Serial.println(names[cardIndex]); // print the relevant name
unlock(); // unlock the door
Serial.println();
}
else
{
Serial.println("Card INVALID");
for(i=1;i<11;i++)
{
x[i-1]=cardNum[i+1];
//Serial.print(x[i-1]);
//Serial.println(cardNum[i+1]);
}
//Serial.print(x);
x[i+1]='\0';
//Serial.print(x);
Serial.print("cardNum: ");
Serial.println(cardNum); //<---------------------------------------- !
Serial.print("x) HEX: ");
Serial.println(x);
//char z[]="00AC8E03";
//y=strtoul(z,NULL,16);
y=strtoul(x,NULL,16);
Serial.print("y) DEC: ");
Serial.println(y);
for(int j=0;j<8;j++)
{
Serial.print(x[j]);
Serial.print(" - ");
}
Serial.println();
//Serial.print("Convertito e': ");
//Serial.println(y);
//tone(speakerPin, 250, 250);
delay(250);
//tone(speakerPin, 150, 250);
}
}
}
int checkCard(char cardNum[10]) {
for (int x=0; x<=users; x++) { // check all valid cards
if(strcmp(cardNum, cards[x])==0) { // compare with last read card number
return (x); // return index of card number
}
}
return (-1); // negative value indicates no match
}
void unlock() {
//tone(speakerPin, 1000, 500);
digitalWrite(lockPin, HIGH);
delay(unlockLength);
digitalWrite(lockPin, LOW);
delay(unlockLength);
digitalWrite(lockPin, HIGH);
delay(unlockLength);
digitalWrite(lockPin, LOW);
}
Byte: 67 -> Integer: 12 [CHECKSUM]
ÿ3C00CE754 <<<------------------------------------------------------------------------ ???
Card INVALID
cardNum: <<------- non avviene la stampa del vettore caratteri "cardNum"
x) HEX: C00CE754
y) DEC: 3222071124
C - 0 - 0 - C - E - 7 - 5 - 4 - <<---- Codice HEX relativo alla card
Il problema è quella ÿ (indicata dalla freccia) che si trova in testa al codice. Non si sà da dove venga fuori! è assurdo, o fatto milioni di prove!
Oltretutto, la sua presenza(della Y) crea un successivo errore nella stampa del codice HEX relativo alla card, infatti la 'C' che si trova in testa alla sequanza di caratteri, dovrebbe trovarsi in coda!
La ÿ viene fuori da quel byte : 255 presente nel codice soprastante, che ha origine ignota... non so davvero da dove possa provenire quel byte!
Cosa ancor più sconvolgente è che , se faccio leggere al lettore Rfid velocemente lo stesso TAG senza dargli tempo di stampare sulla seriale la prima serie, il risultato è il seguente:
Byte: 255 -> Integer: 255 [IGNORATO]
Byte: 51 -> Integer: 3 [IGNORATO]
Byte: 67 -> Integer: 12
Byte: 48 -> Integer: 0
Byte: 48 -> Integer: 0
Byte: 67 -> Integer: 12
Byte: 69 -> Integer: 14
Byte: 55 -> Integer: 7
Byte: 53 -> Integer: 5
Byte: 52 -> Integer: 4
Byte: 67 -> Integer: 12 [CHECKSUM]
Byte: 67 -> Integer: 12 [CHECKSUM]
ÿ3C00CE754
Card INVALID
cardNum: <<------- non avviene la stampa del vettore caratteri "cardNum" !?!?
x) HEX: C00CE754
y) DEC: 3222071124
C - 0 - 0 - C - E - 7 - 5 - 4 - <-- fine stampa prima sequenza
Byte: 51 -> Integer: 3 [IGNORATO] <<----NB è scomparso il byte 255, causa della ÿ !!
Byte: 67 -> Integer: 12 [IGNORATO] <<--- ORA RIPORTANO ANCHE I 2 BYTE DA IGNORARE X IL CALCOLO DEL SERIALE
Byte: 48 -> Integer: 0
Byte: 48 -> Integer: 0
Byte: 67 -> Integer: 12
Byte: 69 -> Integer: 14
Byte: 55 -> Integer: 7
Byte: 53 -> Integer: 5
Byte: 52 -> Integer: 4
Byte: 67 -> Integer: 12
Byte: 67 -> Integer: 12 [CHECKSUM]
Byte: 66 -> Integer: 11 [CHECKSUM]
3C00CE754C
Card INVALID
cardNum: <<------- non avviene la stampa del vettore caratteri "cardNum" !?!?
x) HEX: 00CE754C
y) DEC: 13530444 <<----------È TUTTO ESATTO, PERFINO IL VALORE SERIALE CHE TROVO SCRITTO AL DI FUORI DEL TAG !! (13530444)
0 - 0 - C - E - 7 - 5 - 4 - C - <<--- è proprio l equivalente HEX di 13530444
TUTTO porta come dovrebbe in questo secondo passaggio!
Non so più davvero a che Santo appellarmi.
Come mai al secondo passaggio tutto va come dovrebbe?!?! come mai è scomparsa la ÿ ??
La stringa cardNum continua a non essere stampata, ma in fin dei conti quello è il male minore...
ho anche provato a fare un flush della seriale, ma niente da fare stesso risultato.
Se do tempo alla seriale di stampare tutti i caratteri, l'algoritmo per ricavare il seriale non funziona, se invece avvicino 2 volte in pochissimo tempo il tag al lettore, senza dar tempo all'ardu di stampare il tutto a video, nella seconda sequenza tutto sembra andar bene e funzionare a dovere (ma nella prima no).
La variabile i è usata due volte: una è globale e una è nel ciclo for.
Il compilatore potrebbe considerarle diverse a causa dei diversi scope; dovresti controllare i valori con dei print.
Ho suddiviso il codice in funzioni più semplici, fatto stampe di debug ovunque, cambiato la modalità di conservazione dei dati seriali (cambiando tipo dato e struttura) ma niente da fare... il grosso dubbio che ho è il fatto che quel bit "strano" scompare solo quando faccio sovrapporre due letture seriali veloci, altrimenti permane in ogni caso...
cosa intendi per veloci?non è che si riempie il buffer della seriale? In oltre è normale che la prima lettura in assoluto sia errta se inizia prima del loop di arduino.
Infine, quando dici di aver aumentato il baudrate e di aver letto solo roba starna, sicuro di averlo aumentato solo alla comunicazione con il PC e non anche alla comunicazione via seriale (quello è il classico output da baudrate troppo alto, invece se si imposta troppo basso in ricezione di solito non si ha nulla)