NFC + Arduino - Parte 2

Continuamos con la serie de tutoriales dedicados al uso de la tecnología NFC con Arduino. Si te perdiste la primera parte o si quieres refrescar conocimientos sólo tienes que pinchar en este link.

El NFC tiene dos modos de funcionamiento: el activo en el que los dos dispositivos crean los campos electromagnéticos para enviarse la información, y el pasivo en el que sólo uno de los dispositivos crea el campo y el otro dispositivo lo aprovecha. Con la shield que tengo sólo puedo actuar en modo pasivo, es decir para leer tarjetas o llaveros. La gran limitación es que no puedo comunicarme con otro dispositivo activo como un Smartphone.

Pero vamos a analizar más en detalle lo que podemos hacer con estas tarjetas NFC. Ya sabemos que todas disponen de un número de identificación único que podemos usar para identificar a la tarjeta con la que nos estamos comunicando. Además, el estándar Mifare 1k, que es el que usa la mayoría de estos elementos, tiene una parte de memoria EEPROM, es decir, que podemos  tanto almacenar información como leerla.

Que podamos leer o escribir información en la etiqueta no quiere decir que esta tarea sea fácil, conviene saber cómo está estructurada la memoria. La estructura es la siguiente: la memoria se divide en 16 sectores, cada sector tiene 4 bloques y cada bloque tiene 16 bytes. En total tenemos 64 bloques.

De forma esquemática: 16 sectores -> 4 bloques -> 16 bytes.

En cada sector 1 de los 4 bloques está destinado al control del acceso a los otros 3, dicho bloque contiene una clave de acceso que tenemos que conocer para acceder a la lectura o escritura de los otros bloques.

Por defecto la clave es uint8_t key[]= {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}. Aunque la podemos cambiar, no lo recomiendo salvo que sepas los que estás haciendo, ya que cambiar esta clave puede dejar inaccesible una parte de la memoria. Intentaré hacer un tutorial en el que explique cómo manejar con éxito estas claves, pero de momento las dejamos como vienen.

Si hacemos una lectura de toda la etiqueta con Arduino según viene de fábrica deberíamos ver algo así.

Así continuaría hasta el bloque 63. Como podemos observar, el bloque 0 es un bloque que contiene información del fabricante, por lo que el primer sector tiene un bloque menos disponible. Y podemos ver como los bloques 3,7,11,15…63 son los bloques que contienen las claves.

Todas las operaciones que están definidas en la librería que os dejé en la primera parte están explicadas en este manual, el cual es necesario leer para entender qué hace cada método que uso en el ejercicio.

Manual de la API del NFC

En este tutorial os voy a mostrar el siguiente ejercicio práctico. Leemos el bloque 4 de cualquier etiqueta NFC que encontremos.

NOTA: Si no hemos escrito nada nunca, deberán aparecernos 16 ceros seguidos.

Tras la primera lectura vamos a escribir en el bloque 4 una cadena desde el valor 0 al F (hexadecimal). Luego el programa hará una lectura para comprobar que hemos cambiado con éxito el bloque 4. El código es el siguiente.

/* ************************************************** Autor: Gonzalo Matarrubia ************************************************** Proyecto: 2o tutorial NFC para Geeky Theory ************************************************** Descripción: Este sketch hace una lectura del bloque 4. Tras la primera lectura hace una escritura en el mismo bloque. Luego sigue haciendo lecturas para comprobar que hemos modificado el bloque. ************************************************** */ //Incluimos la librería de la shield NFC #include <PN532.h> //Macros #define SCK         13 #define MOSI        11 #define SS            10 #define MISO        12 //Creamos un objeto NFC de clase PN532 PN532 NFC(SCK,MISO,MOSI,SS); //Declaramos variables globales boolean escrito = false; void setup () { Serial.begin(9600); if(!Serial) { delay(100); } //Configuramos el NCF NFC.begin(); //Comprobamos que tenemos puesta la shield uint32_t versiondata = NFC.getFirmwareVersion(); if( ! versiondata ) { while (1) { delay (100); } //No continuamos con el programa } //Configuramos el NFC para la lectura y escritura NFC.SAMConfig(); } void loop () { // Leemos el número de identificación, mientras no haya ninguna etiqueta valdrá 0 uint32_t id = NFC.readPassiveTargetID(PN532_MIFARE_ISO14443A); uint8_t key [ ] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF} ;  //Clave por defecto if ( id ) { Serial.print("Encontrada etiqueta #"); Serial.println(id); //Nos identificamos para el bloque 4 if( NFC.authenticateBlock (1, id, 4, KEY_A, key) ) { //Creamos un vector para almacenar la lectura uint8_t block[16]; //Leemos el bloque 4 if (NFC.readMemoryBlock (1, 4, block) ) { //Mostramos el bloque 4 for( int i = 0; i<16 ; i++){ Serial.print(block[i],HEX); //Para que quede más ordenado if(block[i] <= 0xF) Serial.print("  "); else Serial.print(" "); } Serial.print (" | Block 4 \n"); } //Si no hemos escrito antes hacemos la escritura en el bloque 4 if( !escrito ) { //Creamos un bloque de información para escribir uint8_t datos[16]; //Ponemos valores de 0 a F for(int i = 0; i<16; i++) datos[i]=i; Serial.print("Escribiendo... \n"); NFC.writeMemoryBlock (1,4, datos); Serial.print("Escritura finalizada \n"); escrito=true; } //else Serial.print("Lectura fallida \n"); //Util para hacer debug } //else Serial.print("Autentificación fallida \n"); //Util para hacer debug } delay(1500); }

Y el vídeo demostrativo de cómo funciona nuestro código.

[youtube http://www.youtube.com/watch?v=68ndpprg7l4&w=770]

Como habéis comprobado la dificultad es mayor que la de la primera parte. Me queda una tercera parte en la que explicaré como cambiar la contraseña que viene por defecto y no quedarnos sin acceso para siempre. Espero que os haya sido fácil de seguir y sino estoy encantado de resolver vuestras dudas en los comentarios.

¡Hasta la 3ª entrega!