NFC Module for Arduino SKU:DFR0231

Sera a tutti, vi scrivo alle 5 di mattina perchè è tutta la notte che sbatto la testa cercando di far funzionare questo modulo per arduino:
http://www.dfrobot.com/wiki/index.php/NFC_Module_for_Arduino_(SKU:DFR0231)
Il funzionamento sembra semplice, il codice che uso è molto simile a quello dell'esempio nella pagina citata, ho apportato un paio di attamenti per farlo funzionare su un arduino uno, ovvero, al posto di Serial1 uso una connessione seriale creata con la libreria SoftwareSerial.

Riporto qui il codice.

/*
PN532 reads the tag by Arduino mega/Leonardo
 command list:
  
 #wake up reader
 send: 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 03 fd d4 14 01 17 00
 return: 00 00 FF 00 FF 00 00 00 FF 02 FE D5 15 16 00
  
 #get firmware
 send: 00 00 FF 02 FE D4 02 2A 00
 return: 00 00 FF 00 FF 00 00 00 FF 06 FA D5 03 32 01 06 07 E8 00
  
 #read the tag
 send: 00 00 FF 04 FC D4 4A 01 00 E1 00
 return: 00 00 FF 00 FF 00 00 00 FF 0C F4 D5 4B 01 01 00 04 08 04 XX XX XX XX 5A 00
 XX is tag.
  
 */
  
 //************* start **************
 
const unsigned char wake[24]={
  0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xfd, 0xd4, 0x14, 0x01, 0x17, 0x00};//wake up NFC module
const unsigned char firmware[9]={
  0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD4, 0x02, 0x2A, 0x00};//
const unsigned char tag[11]={
  0x00, 0x00, 0xFF, 0x04, 0xFC, 0xD4, 0x4A, 0x01, 0x00, 0xE1, 0x00};//detecting tag command
const unsigned char std_ACK[25] = {
  0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x0C, \
0xF4, 0xD5, 0x4B, 0x01, 0x01, 0x00, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x00};
unsigned char old_id[5];
 
unsigned char receive_ACK[25];//Command receiving buffer
//int inByte = 0;               //incoming serial byte buffer
 
#include "SoftwareSerial.h"
SoftwareSerial NFC_Module(10,11);

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#define print1Byte(args) NFC_Module.write(args)
#define print1lnByte(args)  NFC_Module.write(args),NFC_Module.println()
#else
#include "WProgram.h"
#define print1Byte(args) NFC_Module.print(args,BYTE)
#define print1lnByte(args)  NFC_Module.println(args,BYTE)
#endif
 

void setup()
{
  Serial.begin(9600);   // open serial with PC
  NFC_Module.begin(115200);    //open serial1 with device
  //Serial2.begin(115200);
  wake_card();
  delay(100);
  read_ACK(15);
  delay(100);
  display(15);
 
 
}
 
void loop()
{
  send_tag();
  read_ACK(25);
  delay(100);
  if (!cmp_id ()) {
    if (test_ACK ()) {
      display (25);
      delay (100);
    }
  }
  copy_id ();
}
 
 
void copy_id (void)
{//save old id
  int ai, oi;
  for (oi=0, ai=19; oi<5; oi++,ai++) {
    old_id[oi] = receive_ACK[ai];
  }
}
 
  
char cmp_id (void)
{//return true if find id is old
  int ai, oi;
  for (oi=0,ai=19; oi<5; oi++,ai++) {
    if (old_id[oi] != receive_ACK[ai])
      return 0;
  }
  return 1;
}
 
 
int test_ACK (void)
{// return true if receive_ACK accord with std_ACK
  int i;
  for (i=0; i<19; i++) {
    if (receive_ACK[i] != std_ACK[i])
      return 0;
  }
  return 1;
}
 
 
void send_id (void)
{//send id to PC
  int i;
  Serial.print ("ID: ");
  for (i=19; i<= 23; i++) {
    Serial.print (receive_ACK[i], HEX);
    Serial.print (" ");
  }
  Serial.println ();
}
 
 
void UART1_Send_Byte(unsigned char command_data)
{//send byte to device
  print1Byte(command_data);
#if defined(ARDUINO) && ARDUINO >= 100
  NFC_Module.flush();// complete the transmission of outgoing serial data
#endif
}
 
 
void UART_Send_Byte(unsigned char command_data)
{//send byte to PC
  Serial.print(command_data,HEX);
  Serial.print(" ");
}
 
 
void read_ACK(unsigned char temp)
{//read ACK into reveive_ACK[]
  unsigned char i;
  for(i=0;i<temp;i++) {
    receive_ACK[i]= NFC_Module.read();
  }
}
 
 
void wake_card(void)
{//send wake[] to device
  unsigned char i;
  for(i=0;i<24;i++) //send command
    UART1_Send_Byte(wake[i]);
}
 
 
void firmware_version(void)
{//send fireware[] to device
  unsigned char i;
  for(i=0;i<9;i++) //send command
    UART1_Send_Byte(firmware[i]);
}
 
 
void send_tag(void)
{//send tag[] to device
  unsigned char i;
  for(i=0;i<11;i++) //send command
    UART1_Send_Byte(tag[i]);
}
 
 
void display(unsigned char tem)
{//send receive_ACK[] to PC
  unsigned char i;
  for(i=0;i<tem;i++) //send command
    UART_Send_Byte(receive_ACK[i]);
  Serial.println();
}

Il problema si presenta immediatamente, il comando di "wake up" non funziona, o almeno così credo, dato che mi da una risposta diversa da quella riportata dalla documentazione e successivamente non rileva nessuna card.
La risposta che esce è:

0 80 0 0 0 80 2 FF 75 25 9 F8 FF FF FF

quando dovrebbe essere:

00 00 FF 00 FF 00 00 00 FF 02 FE D5 15 16 00

Ho provato anche gli altri comandi, ovvero il "get firmware" e il "read the tag" che rispettivamente mi restituiscono:
0 80 0 0 0 80 6 FD 75 20 53 90 E8 8 7 FC FF FF FF
e

0 80 0 0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF

Non sono un esperto di sistemi rfid, quindi può essermi sfuggito qualcosa di basilare, purtroppo ho fatto l'errore di affidarmi a un modulo quasi privo di documentazione.
Per escludere le cose ovvie ho provato diversi pin per la connessione, sia l'alimentazione a 3.3v sia quella a 5v e anche diversi baud rate per la connessione seriale al pc.
Sono grato a chiunque possa darmi qualche consiglio.

Prova a fare un pò di debug

void wake_card(void)
{//send wake[] to device
 Serial.println(F("Send Wake"));  
 unsigned char i;
 for(i=0;i<24;i++) //send command
   { 
    UART1_Send_Byte(wake[i]);
    Serial.print(wake[i]);    
   }
  Serial.println(F(" ")); 
}

Guarda cosa ti stampa per sapere cosa invii.

Grazie della risposta, il risultato del debug è:

8585000000000000002553253212201230

aggiungendo gli spazi e codificando in esadecimale lo stampato, quindi:

void wake_card(void)
{
  Serial.println(F("Send Wake"));
  unsigned char i;
  for(i=0;i<24;i++) //send command
  {
    Serial.print(wake[i],HEX);
    Serial.print(" ");
    UART1_Send_Byte(wake[i]);
  }
  Serial.println(F(" "));
}

esce:

55 55 0 0 0 0 0 0 0 0 0 0 0 0 0 0 FF 3 FD D4 14 1 17 0

Il codice corrisponde con quello di riferimento, quindi dovrebbe essere tutto ok nell'invio dei dati.

interessante,

leggevo su wikipedia che

NFC è inoltre compatibile con la diffusa architettura delle smart card contactless

intendono le normali schede RFID ? Daltronde l'NFC e' uno sviluppo dell'RFID

hai provato gia' con un cellulare ?

Non ho provato con il cellulare perchè il mio non ha integrata questa tecnologia, ma ho provato con diverse schede da 13.56mhz e persino una a 125khz.
Il problema a mio parere si presenta già dall'inizio quando invio il segnale d'accensione e ricevo una risposta diversa da quella standard.

Ho fatto ulteriori prove e ho notato che non ricevo sempre il medesimo risultato ai comandi di input, ad esempio inviando più volte il "wake up", quindi:

55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 03 fd d4 14 01 17 00

ho ricevuto:

(primo vuoto)
0 80 0 0 0 80 2 FF 75 25 9 F8
0 80 0 0 0 80 2 FF 75 22 9 F8
0 0 0 80 2 FF 75 25 9 F8
0 80 0 0 0 80 2 FF 75 25 9 F8
0 0 0 80 2 FF 75 25 11 F8
0 80 0 0 0 80 2 FF 75 25 11 F8
0 80 0 0 0 80 2 FF 75 25 9 F8
0 80 0 0 0 80 2 FF 75 23 8 F8

Mi sorge il dubbio di avere dei problemi di ricezione del messaggio, ma non ho idea da dove derivino, la frequenza di baud è supportata nelle specifiche della libreria di SoftwareSerial e non ho apportato altre modifiche al software d'esempio.

Ma la velocità della scheda è fissa o la puoi abbassare? L'NFC viaggia solo a 115K?

Esattamente, la velocità è di 115200, nella documentazione non ho trovato niente riguardo la modifica della frequenza di trasmissione seriale.
Comunque nelle specifiche della libreria SoftwareSerial la frequenza di 115200 è supportata, inoltre essendo uno shield apposito per arduino l'avranno testato, no?

Hai un altro convertitore seriale TTL/USB? Potresti intercettare il dialogo sulla SoftSerial per vedere se il problema è lì.
Se alla fine non funziona e sei sicuro di inviare i parametri giusto, contatta il venditore, vedi se può sostituirti la scheda.

p.s. hai controllato il datasheet del micro che gestisce l'NFC? C'è qualcosa di interessante?

... in effetti, se hai un convertitore TTL-USB potresti fare un'altra cosa ... usare la SoftwareSerial per parlare con il PC (a 9600) e la seriale VERA per colloquiare a 115 KBaud con la schedina.

Ho già verificato che 115 KBaud sono tantini per Arduino e ho già incontrato qualche problemino a quelle velocità ... :wink:

Guglielmo

Tra l'altro hai preso l'unica scheda col PN532 che parla via UART. Tutte le altre, meglio supportate (vedi sito Adafruit), dialogano tramite SPI o I2C. :roll_eyes:

Purtroppo non dispongo di un altro convertitore ttl, però ho trovato la documentazione del pn532 e sto cominciando a studiarmela, la trovo molto complicata ma pian piano ci arrivo.
Grazie a tutti per i consigli, se trovo una soluzione o mi avvicino ad essa vi terrò informati.

Ok. :wink:

Torno a chiedere aiuto perchè dopo ore e ore di lettura del manuale e diverse prove, non sono riuscito a capire nemmeno se le stringhe che il modulo mi manda sono errori o risposte.
A pagina 28 ho trovato le regole per il protocollo di comunicazione con il quale si possono scrivere i comandi.
Ad esempio ho capito:

Il comando di wake up ovvero:
55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 03 fd d4 14 01 17 00
è composto così:
55 55 00 00 00 00 00 00 00 00 00 00 00 00 00          00 ff          03       fd      d4      14 01      17            00
-------------------Preamble------------------      Start Code       LEN      LSC     TFI       DATA      DCS       Postamble
i comandi contenuti sono: 
0x14 --> SAMConfiguration 
0x01 --> Normal mode (riferito al comando 0x14)

La risposta del modulo dovrebbe essere:
00 00 FF 00 FF 00 00 00 FF 02 FE D5 15 16 00
ovvero:
00 00 FF 00 FF 00 00         00 FF        02       FE      D5        15          16           00
--------Preamble-----     Start Code     LEN      LSC     TFI       DATA       DSC       Postamble
La risposta vera e propria sarebbe 0x15, che non ho ben capito a cosa si riferisce,
dovrebbe riguardare un'impostazione analogica che il pn532 utilizzerà per la baudrate (ma non credo centri con la comunicazione seriale).

Il messaggio che però ricevo è:

00 00 00 80 02 FF 75 25 11 F8
(Ne ho scelto uno a caso, nei messaggi precedenti potete vedere varie versioni)
La prima cosa che mi verrebbe da cercare è il TFI che indica il verso della comunicazione, dovrebbe essere D5 ovvero PN532-->HOST. 
Dato che non c'è vado a controllarmi la sintassi degli errori dove viene dato come esempio:

00 00 FF 01 FF 7F 81 00
Così composto:
    00           00 FF       01    FF       7F        81     00
Preamble       Start Code    LEN   LSC   Error Code   DCS  Postamble

A questo punto provo a interpretare il codice che mi viene restituito come errore:
00 00        00 80        02     FF     75 25      11       F8
Preamble   Start Code    LEN    LSC   Error Code   DCS   Postamble

Non riesco proprio a capire, 'Preamble' e 'Postamble' da quanto ho capito possono avere diversi valori, ma il 'Start Code' dovrebbe essere fisso a "00 FF".
Inoltre se prendiamo in considerazione i vari pacchetti di controllo ci sono degli errori: LEN + LSC non risulta 0x00 e ERROR CODE + DCS idem.

Se qualcuno mi può aiutare a capire gliene sarò davvero grato perchè ci sto predendo la testa.

Dopo che invii il comando il modilo deve risponderti con un ACK di conferma del comando ricevuto. (pag. 33)
Questo ha la forma
00 00 FF 00 FF 00
(pagine 30 del manuale http://www.nxp.com/documents/user_manual/141520.pdf)
e poi il messaggio di risposta.
Quello che tu chiami preamble è in effetti il codice ACK a cui segue la risposta attesa. Sono 2 messaggi distinti.

Secondo me, tu ricevi invece un codice parziale dovuto ad errori di trasmissione e/o ricezione.

Capito, ho appena acquistato un convertitore usb-ttl su ebay così da poter testare questa eventualità e poi può sempre tornare utile, appena arriva faccio i test e aggiorno il post,
grazie per il tempo che dedichi ai miei problemi.
Buona serata.