Review: Shield NFC para Arduino PN532 ISP

A partir de aquí comienzan los ejemplos de uso de la memoria EEPROM, todos ellos han sido probados y funcionan correctamente. En cualquier caso no me hago responsable de lo que pueda suceder con ellos y los dispositivos NFC.

Almacenar en la memoria cuantas veces se ha leído una llave

/**
 * Author:     Alberto Gil Tesa
 * WebSite:    http://giltesa.com
 * License:    CC BY-NC-SA 3.0
 *
 * Description:
 *   ARDUINO SHIELD NFC PN532 ISP
 *
 *   Ejemplo de uso de la shield NFC con chip PN532:
 *   Contabiliza el numero de veces que se lee la llave.
 *   Con cada lectura se suma 1 al contador de la EEPROM de
 *   la llave y se imprime el resultado por el monitor serial.
 */


#include <PN532.h>

// Shield NFC:
#define SCK        13
#define MOSI       11
#define SS         10
#define MISO       12


PN532 nfc(SCK, MISO, MOSI, SS);


void setup()
{
   Serial.begin(9600);
   nfc.begin();
   nfc.SAMConfig();
}


void loop()
{
   // Contador es un array de bytes de tamaño 1, es necesario crear la variable de este modo ya que el metodo que escribe la informacion espera recibir un puntero hacia el dato.
   byte contador[1];

   // Es la clave de acceso necesaria para acceder a cada sector de la memoria:
   byte keys[]= {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};


   uint32_t id = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A);

   // Si se obtuvo un ID...
   if( id > 0 )
   {
      // Antes de hacer uso de la memoria es necesario autenticarse con la clave de acceso, para ello se le pasa como parametro:
      // - El tipo de tarjeta, pudiendo elegir entre 1 o 2.
      // - El ID de dispositivo NFC al que queremos acceder a su memoria.
      // - La direccion de memoria del bloque en el que queremos autenticarnos, no se le indica el bloque que contiene la clave, si no al que se quiere acceder. El solo se apaña para encontrar la clave correspondiente al bloque.
      // - El tipo de clave, se puede elegir entre KEY_A o KEY_B.
      // - La clave de arriba.
      if( nfc.authenticateBlock(1, id ,0x08, KEY_A, keys) )
      {
         // Una vez autenticados se lee en el bloque 0x08, 1 byte de memoria.
         if( nfc.readMemoryBlock(1, 0x08, contador) )
         {
            // Cada 255 lecturas de la tarjeta se resetea el contador:
            if( contador[0] >= 255)
               contador[0] = 0;

            // Se suma 1 al contador cada vez que se hace una lectura con la Shield:
            contador[0] += 1;

            Serial.print("Contador= "); Serial.println(contador[0]);

            // Se escribe el nuevo valor del contador en el bloque 0x08:
            nfc.writeMemoryBlock(1, 0x08, contador);
         }
      }
      else
      {
         Serial.println("Clave incorrecta o error de lectura");
      }

   }

}

Almacenar en la memoria un texto de 447 bytes

/**
 * Author:     Alberto Gil Tesa
 * WebSite:    http://giltesa.com
 * License:    CC BY-NC-SA 3.0
 *
 * Description:
 *   ARDUINO SHIELD NFC PN532 ISP
 *
 *   Ejemplo de uso de la shield NFC con chip PN532:
 *   En este otro ejemplo mediante los metodos "readAllMemory" y "writeAllMemory" añadidos por mi
 *   se puede leer o escribir en la memoria de forma consecutiva sin tener que preocuparnos por los
 *   bloques de autenticacion.
 *   Podemos almacenar los datos que queramos siempre y cuando sean arrays de bytes.
 *   Eso quiere decir que se pueden almacenar cadenas o estructuras de datos Union.
 *
 *   En concreto este ejemplo guarda un parrafo de texto de 447 caracteres/bytes.
 */


#include <PN532.h>

// Shield NFC:
#define SCK  13
#define MOSI 11
#define SS   10
#define MISO 12
PN532 nfc(SCK, MISO, MOSI, SS);


byte texto[] = "El hardware consiste en una placa con un microcontrolador Atmel AVR y puertos de entrada/salida. Los microcontroladores mas usados son el Atmega168, Atmega328, Atmega1280, ATmega8 por su sencillez y bajo coste que permiten el desarrollo de multiples disenios. Por otro lado el software consiste en un entorno de desarrollo que implementa el lenguaje de programacion Processing/Wiring y el cargador de arranque (boot loader) que corre en la placa.";
byte textoTag[sizeof(texto)];
boolean escrito = false;


void setup()
{
   Serial.begin(9600);
   nfc.begin();
   nfc.SAMConfig();
}


void loop()
{
   uint32_t id = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A);

   if( id > 0 )
   {
      // Escribe por primera vez el texto en la memoria EEPROM de la Tag:
      if( !escrito )
      {
         if( !nfc.writeAllMemory( id , texto, sizeof(texto) ) )
            Serial.println("Error de escritura");
         else
         {
            escrito = true;
            Serial.println("Escritura realizada correctamente");
         }
      }


      // Le el contenido de la memoria EEPROM:
      if( escrito )
      {
         if( ! nfc.readAllMemory(id , textoTag , sizeof(textoTag)) )
            Serial.println("Error de lectura");
         else
         {
            for( int i=0 ; i<sizeof(textoTag) ; i++ )
               Serial.print( (char)textoTag[i] );

            Serial.println("\n");
            delay(2000);
         }
      }

   }

}

Almacenar estructuras de datos con las variables que queramos

Este ejemplo se compone de dos ficheros o sub-ejemplos, el primero es solo de escritura y el segundo de lectura.
Lo que hace el ejemplo de escritura es escribir en la EEPROM una estructura de datos Union, que contiene en su interior una estructura de datos Struct y que a su vez contiene 3 variables de tipo byte que almacenan el valor de luminosidad de los colores rojo, verde y azul. De este modo solo hay que pasarle la estructura Union al método writeAllMemory para que la escriba entera con todas las variables que hayamos metido en su interior, es realmente cómodo!

/**
 * Author:     Alberto Gil Tesa
 * WebSite:    http://giltesa.com
 * License:    CC BY-NC-SA 3.0
 *
 * Description:
 *   ARDUINO SHIELD NFC PN532 ISP
 *
 *   Ejemplo de uso de la shield NFC con chip PN532.
 *   Escribe en la memoria EEPROM de la llave NFC
 *   la configuracion de colores de un LED RGB
 */


struct DATOS{
   byte rojo;
   byte verde;
   byte azul;
};

union MEMORIA{
   DATOS color;
   byte  b[sizeof(DATOS)];
}
rgb;


#include <PN532.h>

// Shield NFC:
#define SCK        13
#define MOSI       11
#define SS         10
#define MISO       12
boolean escrito = false;


PN532 nfc(SCK, MISO, MOSI, SS);


void setup()
{
   Serial.begin(9600);
   nfc.begin();
   nfc.SAMConfig();
}


void loop()
{
   uint32_t id = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A);

   if( id > 0  &&  !escrito )
   {
      // Segun el color del Tag (del plastico) deberemos de descomentar la linea que se corresponda
      // para que tenga coherencia con la configuracion que almacena:

      rgb.color.rojo  = 0;   rgb.color.verde = 255; rgb.color.azul  = 0;   // Lima
      // rgb.color.rojo  = 0;   rgb.color.verde = 0;   rgb.color.azul  = 255; // Azul
      // rgb.color.rojo  = 204; rgb.color.verde = 0;   rgb.color.azul  = 0;   // Rojo
      // rgb.color.rojo  = 160; rgb.color.verde = 255; rgb.color.azul  = 0;   // Amarillo
      // rgb.color.rojo  = 255; rgb.color.verde = 255; rgb.color.azul  = 255; // Blanco
      // rgb.color.rojo  = 0;   rgb.color.verde = 0;   rgb.color.azul  = 0;   // GRIS == OFF

      if( !nfc.writeAllMemory( id , rgb.b, sizeof(rgb.b) ) )
         Serial.println("Error de escritura");
      else
      {
         escrito = true;
         Serial.println("Escritura realizada correctamente");
      }

   }
}

Lo mismo sucede con el segundo ejemplo que en este caso su funcion es leer la configuración grabada en la EEPROM y encender el Led RGB en los colores/tonalidades que hayamos indicado.

Como siempre recomiendo leer las respectivas entradas de estructuras Union y Struct para entender como funcionan.

/**
 * Author:     Alberto Gil Tesa
 * WebSite:    http://giltesa.com
 * License:    CC BY-NC-SA 3.0
 *
 * Description:
 *   ARDUINO SHIELD NFC PN532 ISP
 *
 *   Ejemplo de uso de la shield NFC con chip PN532.
 *   Lee en la memoria EEPROM de la llave NFC
 *   la configuracion de colores de un LED RGB
 *   para encenderlo segun corresponda.
 */


struct DATOS{
   byte rojo;
   byte verde;
   byte azul;
};

union MEMORIA{
   DATOS color;
   byte  b[sizeof(DATOS)];
}
rgb;


#include <PN532.h>

// Shield NFC:
#define SCK        13
#define MOSI       11
#define SS         10
#define MISO       12

// Pines LED RGB:
#define LED_AZUL    2
#define LED_VERDE   3
#define LED_ROJO    4


PN532 nfc(SCK, MISO, MOSI, SS);


void setup()
{
   Serial.begin(9600);
   nfc.begin();
   nfc.SAMConfig();

   pinMode( LED_AZUL  , OUTPUT );
   pinMode( LED_VERDE , OUTPUT );
   pinMode( LED_ROJO  , OUTPUT );
}


void loop()
{
   uint32_t id = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A);

   if( id > 0 )
   {
      if( !nfc.readAllMemory(id , rgb.b , sizeof(rgb.b)) )
         Serial.println("Error de lectura");
      else
      {
         analogWrite( LED_ROJO  , rgb.color.rojo  );
         analogWrite( LED_VERDE , rgb.color.verde );
         analogWrite( LED_AZUL  , rgb.color.azul  );
         delay(1000);
      }
   }
}

Y con los ejemplos se termina esta review. Si te ha gustado puedes compartirla para que mas gente pueda leerla :slight_smile:

Edit:
Bendita limitación de caracteres -_-

giltesa, pedazo post y contribucion. Genial y buen trabajo!

Genial, fantastico post!!!!!

Esta genial. Menuda currada.

Un post genial...Muchas gracias Giltesa!!!!!

Es posible modificar el código nfc que transmite una llave?

hay nfc grabables y otras fijas, no es mas que un codigo

maxid:
hay nfc grabables y otras fijas, no es mas que un codigo

Y suponiendo que tengo una grabable, se puede clonar el codigo entero de otra en esa que es grabable? Es decir para que acabe siendo "la misma clave"

si, busca en atmel tienen los chips. Despues en ebay, dx y demas encuentras de todo
Estas se usan para lugares donde hay visitas, hoteles y le dan una llave de acceso, el cual le cambian el codigo. Es mas simple cambiar el codigo de la tarjeta que reprogramar el lector. En realidad es un problema de seguridad que debes auditar.

maxid:
si, busca en atmel tienen los chips. Despues en ebay, dx y demas encuentras de todo
Estas se usan para lugares donde hay visitas, hoteles y le dan una llave de acceso, el cual le cambian el codigo. Es mas simple cambiar el codigo de la tarjeta que reprogramar el lector. En realidad es un problema de seguridad que debes auditar.

Llaveros NFC programables para móvil, Arduino, etc. - el blog de giltesa
Recomendaciones para ti - DealeXtreme

entonces que funcion de la librería debería usar para pasar toda la información de una llave a otra y así tenerla duplicada. Mi idea es leer de una llave y pasar toda esa información a una que permita escritura para poder tenerla "por duplicado"

Esta shield funciona también con Arduino Leonardo o hay que hacer alguna modificación?

karlospv94:

maxid:
si, busca en atmel tienen los chips. Despues en ebay, dx y demas encuentras de todo
Estas se usan para lugares donde hay visitas, hoteles y le dan una llave de acceso, el cual le cambian el codigo. Es mas simple cambiar el codigo de la tarjeta que reprogramar el lector. En realidad es un problema de seguridad que debes auditar.

Llaveros NFC programables para móvil, Arduino, etc. - el blog de giltesa
Recomendaciones para ti - DealeXtreme

entonces que funcion de la librería debería usar para pasar toda la información de una llave a otra y así tenerla duplicada. Mi idea es leer de una llave y pasar toda esa información a una que permita escritura para poder tenerla "por duplicado"

En la libreria que puse, y modifique, tienes añadidos dos metodos para leer y escribir toda la informacion de golpe... pero necesitas las claves de acceso a cada bloque de memoria. Los metodos estan adaptados para que funcionen con las compradas por ebay.

karlospv94:
Esta shield funciona también con Arduino Leonardo o hay que hacer alguna modificación?

Si, funciona sin problemas en el Leonardo.

giltesa:

karlospv94:

maxid:
si, busca en atmel tienen los chips. Despues en ebay, dx y demas encuentras de todo
Estas se usan para lugares donde hay visitas, hoteles y le dan una llave de acceso, el cual le cambian el codigo. Es mas simple cambiar el codigo de la tarjeta que reprogramar el lector. En realidad es un problema de seguridad que debes auditar.

Llaveros NFC programables para móvil, Arduino, etc. - el blog de giltesa
Recomendaciones para ti - DealeXtreme

entonces que funcion de la librería debería usar para pasar toda la información de una llave a otra y así tenerla duplicada. Mi idea es leer de una llave y pasar toda esa información a una que permita escritura para poder tenerla "por duplicado"

En la libreria que puse, y modifique, tienes añadidos dos metodos para leer y escribir toda la informacion de golpe... pero necesitas las claves de acceso a cada bloque de memoria. Los metodos estan adaptados para que funcionen con las compradas por ebay.

karlospv94:
Esta shield funciona también con Arduino Leonardo o hay que hacer alguna modificación?

Si, funciona sin problemas en el Leonardo.

vale ya entiendo. Es decir, en el código de la librería s epresupone que la clave es 0xFF.... pero si quisiese leer un bloque de otra tarjeta debería poner la clave real de esa tarjeta para cada bloque para poder leer, verdad?

karlospv94:

giltesa:

karlospv94:

maxid:
si, busca en atmel tienen los chips. Despues en ebay, dx y demas encuentras de todo
Estas se usan para lugares donde hay visitas, hoteles y le dan una llave de acceso, el cual le cambian el codigo. Es mas simple cambiar el codigo de la tarjeta que reprogramar el lector. En realidad es un problema de seguridad que debes auditar.

Llaveros NFC programables para móvil, Arduino, etc. - el blog de giltesa
Recomendaciones para ti - DealeXtreme

entonces que funcion de la librería debería usar para pasar toda la información de una llave a otra y así tenerla duplicada. Mi idea es leer de una llave y pasar toda esa información a una que permita escritura para poder tenerla "por duplicado"

En la libreria que puse, y modifique, tienes añadidos dos metodos para leer y escribir toda la informacion de golpe... pero necesitas las claves de acceso a cada bloque de memoria. Los metodos estan adaptados para que funcionen con las compradas por ebay.

karlospv94:
Esta shield funciona también con Arduino Leonardo o hay que hacer alguna modificación?

Si, funciona sin problemas en el Leonardo.

vale ya entiendo. Es decir, en el código de la librería s epresupone que la clave es 0xFF.... pero si quisiese leer un bloque de otra tarjeta debería poner la clave real de esa tarjeta para cada bloque para poder leer, verdad?

Eso es, en este caso la clave de estas tarjetas (de todos los llaveros y de la tarjeta con forma de tarjeta de credito) es:
uint8_t keys[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}
Pero en otras llaves podria ser distinta.

Y hay que tener cuidado con no escribir en la memoria donde se guarda la clave o perderas ese bloque y los siguientes.

giltesa:

karlospv94:

giltesa:

karlospv94:

maxid:
si, busca en atmel tienen los chips. Despues en ebay, dx y demas encuentras de todo
Estas se usan para lugares donde hay visitas, hoteles y le dan una llave de acceso, el cual le cambian el codigo. Es mas simple cambiar el codigo de la tarjeta que reprogramar el lector. En realidad es un problema de seguridad que debes auditar.

Llaveros NFC programables para móvil, Arduino, etc. - el blog de giltesa
Recomendaciones para ti - DealeXtreme

entonces que funcion de la librería debería usar para pasar toda la información de una llave a otra y así tenerla duplicada. Mi idea es leer de una llave y pasar toda esa información a una que permita escritura para poder tenerla "por duplicado"

En la libreria que puse, y modifique, tienes añadidos dos metodos para leer y escribir toda la informacion de golpe... pero necesitas las claves de acceso a cada bloque de memoria. Los metodos estan adaptados para que funcionen con las compradas por ebay.

karlospv94:
Esta shield funciona también con Arduino Leonardo o hay que hacer alguna modificación?

Si, funciona sin problemas en el Leonardo.

vale ya entiendo. Es decir, en el código de la librería s epresupone que la clave es 0xFF.... pero si quisiese leer un bloque de otra tarjeta debería poner la clave real de esa tarjeta para cada bloque para poder leer, verdad?

Eso es, en este caso la clave de estas tarjetas (de todos los llaveros y de la tarjeta con forma de tarjeta de credito) es:
uint8_t keys[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}
Pero en otras llaves podria ser distinta.

Y hay que tener cuidado con no escribir en la memoria donde se guarda la clave o perderas ese bloque y los siguientes.

De acuerdo, gracias! Ahora ya se me han aclarado unas dudas que tenía :slight_smile:
No hay ninguna forma entonces de modificar la clave de cada sector? Porque sino cualquier persona que conozca mi tarjeta sabrá cual es la clave y podría leer toda la info de ella...

Yo la intente modificar en una pero no sé si lo hice mal o que pero el caso es que brickee los bloques de memoria y no supe restaurar la clave original ni nada. No probé con más llaveros pues no quería cargarme más...

En cualquier caso, la información que grabes dentro la puedes guardar cifrada con algún algoritmo asi que lo de la clave de acceso a los bloques de memoria es lo de menos, por mucho que lean la informacion si no la saben descifrar no les va a servir para nada.

Vale no lo habia pensado. Hacer un metodo en el lector para que invierta las operaciones de cifrado para cuando tenga que leer un bloque de datos. Estoy tonto jajaj. Gracias!

Hola he estado checando tu post y la verdad es excelente, en mi caso ocupo otras librerias para el manejo de PN532 que es un poco mas sencillo su uso, pero en fin tengo duda sobre una situación, es posible de alguna forma bloquear el borrado de un Tag NFC?, es que quiero implementar algo pero que obviamente no la vayan a borrar el contenido, como dices se puede encriptar los datos pero no esta excento que alguien borre el contenido de la tarjeta o del Tag. Esto lo digo por que hay telefonos con la capacidad de leer tags NFC y asi mismo aplicaciones para poder leer/escribir/borrar.

Espero me puedas ayudar en esta duda, o alguna alternativa a esto.

hola compañero buenas tardes desde Colombia, desde ya te felicito por tal excelente tutorial para este dispositivo :stuck_out_tongue_closed_eyes: pero requiero de tu ayuda profesional para aprender a manejar el dispositivo mifare rc522, estoy tratando de grabar una cadena de texto como un numero de idientificacion de la cédula de ciudadana de nuestro país pero no tengo ni idea como hacerlo, he mirado las librerías del mc522 pero la verdad no es mucho lo que aporten, soy un poco inexperto con esto a pesar que ya tengo tiempo aprendiendo con arduino. te animas y nos enseñas como un gran profesional de la electrónica