Oct
7
2013

RFID con Arduino (I)

Dale a "Me gusta" para continuar leyendo!

Tutorial sobre como programar los dispositivos RFID en Arduino

 


Después de varios meses sin poder publicar novedades en la web os traigo un tutorial bastante interesante para mi gusto sobre la tecnología RFID 13.56 para arduino.

Este tutorial es parte de un tutorial bastante extenso que no acaba en esta página debido a que todavía hay partes de esta tecnología que tengo que investigar.

Para acceder al contenido es necesario que os guste mi página de facebook. =)

 

En primer lugar, vamos a ver un poco como funciona esta tecnología y su funcionamiento para poder comprender los programas que más tarde podréis leer y utilizar.

Creo que wikipedia describe ya perfectamente que es este dispositivo:

RFID (siglas de Radio Frequency IDentification, en español identificación por radiofrecuencia) es un sistema de almacenamiento y recuperación de datos remoto que usa dispositivos denominados etiquetas, tarjetas, transpondedores o tags RFID. El propósito fundamental de la tecnología RFID es transmitir la identidad de un objeto (similar a un número de serie único) mediante ondas de radio. 

También deberemos saber antes de nada la estructura interna de las tarjetas RFID que vamos a usar posteriormente, yo trabajo con unas MIFARE de 1k o 4k.

Estas tarjetas estan divididas en varios bloques, dependiendo de la capacidad de la tarjeta. Cada bloque esta compuesto por 3 cadenas de datos mas 1 cadena con las contraseñas de acceso y las condiciones de acceso, este bloque es llamado “trailer”. Cada vez que queramos modificar uno de los bloques debemos “loguearnos” en cada uno de los bloques para que de acceso a escritura.

Os dejo una imagen que ilustra bastante bien la estructura interna(pulsar en ella para ver mejor):

Estructura RFID

 

Bueno una vez quitada la teoría vamos a lo interesante que es estos dispositivos RFID trabajando con arduino.

 

¿Que necesito?

Yo he utilizado los siguientes materiales, tu puedes escoger otros diferentes pero no te aseguro su funcionamiento al 100%.

 

– Arduino uno.

– Arduino shield

– RFID 13.56 Mhz con el chip PN532, yo lo compré en cooking hacks pero posiblemente podáis utilizar otro con el mismo chip, si alguien lo prueba con otro dispositivo y le funciona bien que me lo comente para actualizar el tutorial.

– Tarjeta mifare 1k: Yo las compre por ebay por 1 €/5 tarjetas.


 

Funciones en Arduino

 

Aquí os voy a exponer varias de las funciones más importantes que podemos usar en un programa con RFID, muchas fueron publicadas por cooking hacks en su web pero están tienen varios detalles modificados por mi porque encontré algún fallo o simplemente no me gustaban.

Las funciones importantes son:

authenticate(UID, dirección, clave de acceso) = Esta función devolverá un O si la contraseña A es correcta.

authenticateB(UID, dirección, clave de acceso) = Igual que la anterior pero para la contraseña B.

writeData(dirección, datos) = Esta función devolverá un O si se ha grabado correctamente.

readData(dirección, datos) = Esta función imprimirá los datos de la dirección especificada.

 

En la cabecera de nuestro programa de Arduino deberemos declarar cada una de las variables. A continuación pondré 2 ejemplos para escritura y lectura con nuestro RFID:

Lectura

 

/*

Tutorial de Diegotecnology.es para mas información sobre este tutorial visita la web

*/

uint8_t dataRX[35];
uint8_t dataTX[35];
uint8_t _UID[4];
uint8_t keyAccess[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } ;
uint8_t keyAccessB[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } ;
uint8_t address = 0x08;
uint8_t ATQ[2];
uint8_t state;
uint8_t aux[16]; 

void setup()
{

	Serial.begin(115200);
	delay(100);
        Serial.print("Tutorial de Diegotecnology.es");
        Serial.println();
	Serial.print("Modulo RFID preparado");
	delay(1000);	
	configureSAM();
}
/*

Tutorial de Diegotecnology.es para mas información sobre este tutorial visita la web

*/

void loop()
{
	Serial.print("\n");
	Serial.println("Esperando tarjeta...");

	init(_UID, ATQ);
	Serial.print("\n");
	Serial.print( "Id de la tarjeta: ");
	print(_UID , 4);

	state = authenticate(_UID, address, keyAccess);
	Serial.print("\n");

	 for (int n=0; n< 64; n++) 
    { 

      if (n % 4 == 0) 
      { 
        state = authenticate(_UID, n , keyAccess);
        Serial.print("\r\nAuthentication "); 
        Serial.print(n, DEC); 
        Serial.print(": "); 
        Serial.print(state);
         Serial.print("                                           ");

      } 

      state = readData(n, aux); 
      Serial.print("\r\nRead block "); 
      Serial.print(n); 
      Serial.print(": "); 
      Serial.print(state); 
      Serial.print("   "); 

      if (state == 0) 
      { 
        Serial.print(" | "); 
        for (int i=0; i< 16; i++) 
        { 
          Serial.print(" ");
          if (aux[i] <=  B01111) 
          { 
            Serial.print(" "); 
          } 
          Serial.print(aux[i], HEX); 
          Serial.print(" "); 
        } 
        Serial.print("                                  "); 
        if (n==0) 
          Serial.print("<--UID(first 4 bytes)"); 
        else if (((n+1) % 4) == 0) 
          Serial.print("<--Trailer block"); 
      } 
    } 
    Serial.println(); 

  delay(2000); 
  }
/*

Tutorial de Diegotecnology.es para mas información sobre este tutorial visita la web

*/
//**********************************************************************
//!The goal of this command is to detect as many targets (maximum MaxTg)
// as possible in passive mode.
uint8_t init(uint8_t *UID , uint8_t *ATQ)   //! Request InListPassive
{
  Serial.flush();

	dataTX[0] = 0x04; // Length
	lengthCheckSum(dataTX); // Length Checksum
	dataTX[2] = 0xD4;
	dataTX[3] = 0x4A; // Code
	dataTX[4] = 0x01; //MaxTarget
	dataTX[5] = 0x00; //BaudRate = 106Kbps
	dataTX[6] = 0x00; // Clear checkSum position
	checkSum(dataTX); 

	sendTX(dataTX , 7 ,23);

	for (int i = 17; i < (21) ; i++){
		_UID[i-17] = dataRX[i];
	UID[i-17] = _UID[i-17];
	}

	ATQ[0] = dataRX[13];
	ATQ[1] = dataRX[14];

	if ((dataRX[9]== 0xD5) & (dataRX[10] == 0x4B) & (dataRX[11] == 0x01)) {
		return 0;
	} else {
		return 1;
	}
}
/*

Tutorial de Diegotecnology.es para mas información sobre este tutorial visita la web

*/

//**********************************************************************
//!A block must be authenticated before read and write operations
uint8_t authenticate(uint8_t *UID, uint8_t blockAddress, uint8_t *keyAccess)
{
	dataTX[0] = 0x0F;
	lengthCheckSum(dataTX);
	dataTX[2] = 0xD4;
	dataTX[3] = 0x40; // inDataEchange
	dataTX[4] = 0x01; //Number of targets
	dataTX[5] = 0x60; // Authentication code
	dataTX[6] = blockAddress;
	for (int i = 0; i < 6 ; i++) {
		dataTX[i + 7] = keyAccess[i];
	}
	dataTX[13] = UID[0];  dataTX[14] = UID[1];
	dataTX[15] = UID[2];  dataTX[16] = UID[3];
	dataTX[17] = 0x00;
	checkSum(dataTX);
	sendTX(dataTX , 18 ,14);

	if ((dataRX[9]== 0xD5) & (dataRX[10] == 0x41) & (dataRX[11] == 0x00)) {
		return 0;
	} else {
		return 1;
	}
}

/*

Tutorial de Diegotecnology.es para mas información sobre este tutorial visita la web

*/

//**********************************************************************
//!A block must be authenticated before read and write operations
uint8_t authenticateB(uint8_t *UID, uint8_t blockAddress, uint8_t *keyAccessB)
{
	dataTX[0] = 0x0F;
	lengthCheckSum(dataTX);
	dataTX[2] = 0xD4;
	dataTX[3] = 0x40; // inDataEchange
	dataTX[4] = 0x01; //Number of targets
	dataTX[5] = 0x61; // Authentication code
	dataTX[6] = blockAddress;
	for (int i = 0; i < 6 ; i++) {
		dataTX[i + 7] = keyAccessB[i];
	}
	dataTX[13] = UID[0];  dataTX[14] = UID[1];
	dataTX[15] = UID[2];  dataTX[16] = UID[3];
	dataTX[17] = 0x00;
	checkSum(dataTX);
	sendTX(dataTX , 18 ,14);

	if ((dataRX[9]== 0xD5) & (dataRX[10] == 0x41) & (dataRX[11] == 0x00)) {
		return 0;
	} else {
		return 1;
	}
}
//**********************************************************************
//!Write 16 bytes in address .
uint8_t writeData(uint8_t address, uint8_t *blockData)  //!Writing
{
	Serial.print("                ");
	dataTX[0] = 0x15;
	lengthCheckSum(dataTX); // Length Checksum
	dataTX[2] = 0xD4;
	dataTX[3] = 0x40;//inDataEchange CODE
	dataTX[4] = 0x01;//Number of targets
	dataTX[5] = 0xA0;//Write Command
	dataTX[6] = address; //Address		

	for (int i = 0; i < 16; i++) {
		dataTX[i+7] = blockData[i];
	}

	dataTX[23] = 0x00;
	checkSum(dataTX);
	sendTX(dataTX , 24 ,14);		

	if ((dataRX[9]== 0xD5) & (dataRX[10] == 0x41) & (dataRX[11] == 0x00)) {
		return 0;
	} else {
		return 1;
	}
}
//**********************************************************************
//!Read 16 bytes from  address .
uint8_t readData(uint8_t address, uint8_t *readData) //!Reading
{
	Serial.print("                ");

	dataTX[0] = 0x05;
	lengthCheckSum(dataTX); // Length Checksum
	dataTX[2] = 0xD4; // Code
	dataTX[3] = 0x40; // Code
	dataTX[4] = 0x01; // Number of targets
	dataTX[5] = 0x30; //ReadCode
	dataTX[6] = address;  //Read address
	dataTX[7] = 0x00;
	checkSum(dataTX);
	sendTX(dataTX , 8, 30);
	memset(readData, 0x00, 16);  

	if ((dataRX[9]== 0xD5) & (dataRX[10] == 0x41) & (dataRX[11] == 0x00)) {
		for (int i = 12; i < 28; i++) {
			readData[i-12] = dataRX[i];
		}
		return 0;
	} else {
		return 1;
	}
}
//**********************************************************************
//!The PN532 sends back the version of the embedded firmware.
bool getFirmware(void)  //! It is needed to launch a simple command to sycnchronize
{
  Serial.print("                ");

	memset(dataTX, 0x00, 35);
	dataTX[0] = 0x02; // Length
	lengthCheckSum(dataTX); // Length Checksum
	dataTX[2] = 0xD4; // CODE
	dataTX[3] = 0x02; //TFI
	checkSum(dataTX); //0x2A; //Checksum   

	sendTX(dataTX , 5 , 17);
	Serial.print("\n");
	Serial.print("Your Firmware version is : ");

	for (int i = 11; i < (15) ; i++){
		Serial.print(dataRX[i], HEX);
		Serial.print(" ");
	}
	Serial.print("\n");
}

//**********************************************************************
//!Print data stored in vectors .
void print(uint8_t * _data, uint8_t length)
{
	for (int i = 0; i < length ; i++){
		Serial.print(_data[i]);
		Serial.print(" ");
	}
	Serial.print("\n");
}
/*

Tutorial de Diegotecnology.es para mas información sobre este tutorial visita la web

*/

//**********************************************************************
//!This command is used to set internal parameters of the PN532,
bool configureSAM(void)//! Configure the SAM
{
	Serial.print("               ");

	dataTX[0] = 0x05; //Length
	lengthCheckSum(dataTX); // Length Checksum
	dataTX[2] = 0xD4;
	dataTX[3] = 0x14;
	dataTX[4] = 0x01; // Normal mode
	dataTX[5] = 0x14; // TimeOUT
	dataTX[6] = 0x00; // IRQ
	dataTX[7] = 0x00; // Clean checkSum position
	checkSum(dataTX);

	sendTX(dataTX , 8, 13);
}
//**********************************************************************
//!Send data stored in dataTX
void sendTX(uint8_t *dataTX, uint8_t length, uint8_t outLength)
{
	Serial.write(0x00);
	Serial.write(0x00);
	Serial.write(0xFF); 

	for (int i = 0; i < length; i++) {
		Serial.write(dataTX[i]);
	}

	Serial.write(0x00);
	getACK();
	waitResponse();// Receive response
	getData(outLength);
}
//**********************************************************************
//!Wait for ACK response and stores it in the dataRX buffer
void getACK(void)
{
	delay(5);
	waitResponse();
	for (int i = 0; i < 5 ; i++) {
		dataRX[i] = Serial.read();
	}
}
//**********************************************************************
//!Wait the response of the module
void waitResponse(void)
{
	int val = 0xFF;
	int cont = 0x00;
	while(val != 0x00) { //Wait for 0x00 response
		val = Serial.read();
		delay(5);
		cont ++;
	}
}
//**********************************************************************
//!Get data from the module
void getData(uint8_t outLength)
{
	for (int i=5; i < outLength; i++) {
		dataRX[i] = Serial.read();//read data from the module.
	}
}
//**********************************************************************
//!Calculates the checksum and stores it in dataTX buffer
void checkSum(uint8_t *dataTX)
{
	for (int i = 0; i < dataTX[0] ; i++) {
		dataTX[dataTX[0] + 2] += dataTX[i + 2];
	}
	byte(dataTX[dataTX[0] + 2]= - dataTX[dataTX[0] + 2]);
}
//**********************************************************************
//!Calculates the length checksum and sotres it in the buffer.
uint8_t lengthCheckSum(uint8_t *dataTX)
{
	dataTX[1] = byte(0x100 - dataTX[0]);
}
Escritura
/*

Tutorial de Diegotecnology.es para mas información sobre este tutorial visita la web

*/

uint8_t dataRX[35];//Receive buffer.
uint8_t dataTX[35];//Transmit buffer.
uint8_t _UID[4];// stores the UID (unique identifier) of a card.
uint8_t keyAccess[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff } ;// stores the key or password.
uint8_t keyAccessB[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff } ;
uint8_t address = 0x08;//Address to read.
uint8_t ATQ[2];//Answer to request
uint8_t state;//state of the process
uint8_t state2;//state of the process
uint8_t aux[16];//Auxiliar buffer. 
uint8_t blockData[] =	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

void setup()
{

	//Start serial port 115200 bps:
	Serial.begin(115200);
	delay(100);
	Serial.print("Tutorial de Diegotecnology.es");
        Serial.println();
	Serial.print("Modulo RFID preparado");
        delay(1000);

	configureSAM();

        Serial.print("\n");
	Serial.println("Esperando tarjeta...");
	/////////////////////////////////////////////////////////////
	//Get the UID Identifier
	init(_UID, ATQ);
	Serial.print("\n");
	Serial.print( "Id de la tarjeta: ");
	print(_UID , 4);

	Serial.print("\n");

       state = authenticate(_UID, 0x01 , keyAccess); // it is supposed all the blocks have the same key 
       state2 = authenticateB(_UID, 0x01, keyAccessB);
      Serial.print("\r\nAuthentication block"); 
       Serial.print(0x08, DEC); // show the number of the block [n = 0..63 in a 1 kB RFID card] 
        Serial.print(": "); 

     if ( state == 0 ){
        Serial.print("Success authentication block A");}

         if ( state2 == 0 ){
        Serial.println("Success authentication block B");}

  state = writeData(0x01, blockData);
		Serial.print("\n");
			if ( state == 0) {
				Serial.println("Write block OK");

			} else {
				Serial.println("Write failed");}

  state = writeData(0x02, blockData);
		Serial.print("\n");
			if ( state == 0) {
				Serial.println("Write block OK");

			} else {
				Serial.println("Write failed");}

 state = writeData(0x03, blockData);
		Serial.print("\n");
			if ( state == 0) {
				Serial.println("Write block OK");

			} else {
				Serial.println("Write failed");}

/*

Tutorial de Diegotecnology.es para mas información sobre este tutorial visita la web

*/

   delay(2000);
   Serial.print("\n");
   readData(0x01, aux);
   Serial.print("\n");
   Serial.println("************************************************************************");
   Serial.print("Data write now:  ");
for (int i=0; i< 16; i++) 
        { 
          if (aux[i] <=  B01111) 
          { 
            Serial.print(" "); 
          } 
          Serial.print(aux[i], HEX); // print the 16 bytes of the block 'n' 
          Serial.print(" "); 
        }

   Serial.print("\n");     
   Serial.print("************************************************************************");

   readData(0x02, aux);
    Serial.print("\n");
   Serial.println("************************************************************************");
   Serial.print("Data write now:  ");
for (int i=0; i< 16; i++) 
        { 
          if (aux[i] <=  B01111) 
          { 
            Serial.print(" "); 
          } 
          Serial.print(aux[i], HEX); // print the 16 bytes of the block 'n' 
          Serial.print(" "); 
        }

   Serial.print("\n");     
   Serial.print("************************************************************************");

readData(0x03, aux);
    Serial.print("\n");
   Serial.println("************************************************************************");
   Serial.print("Data write now:  ");
for (int i=0; i< 16; i++) 
        { 
          if (aux[i] <=  B01111) 
          { 
            Serial.print(" "); 
          } 
          Serial.print(aux[i], HEX); // print the 16 bytes of the block 'n' 
          Serial.print(" "); 
        }

   Serial.print("\n");     
   Serial.print("************************************************************************");
}

void loop()
{}
/*

Tutorial de Diegotecnology.es para mas información sobre este tutorial visita la web

*/    

//**********************************************************************
//!The goal of this command is to detect as many targets (maximum MaxTg)
// as possible in passive mode.
uint8_t init(uint8_t *UID , uint8_t *ATQ)   //! Request InListPassive
{
  Serial.flush();

	dataTX[0] = 0x04; // Length
	lengthCheckSum(dataTX); // Length Checksum
	dataTX[2] = 0xD4;
	dataTX[3] = 0x4A; // Code
	dataTX[4] = 0x01; //MaxTarget
	dataTX[5] = 0x00; //BaudRate = 106Kbps
	dataTX[6] = 0x00; // Clear checkSum position
	checkSum(dataTX); 

	sendTX(dataTX , 7 ,23);

	for (int i = 17; i < (21) ; i++){
		_UID[i-17] = dataRX[i];
	UID[i-17] = _UID[i-17];
	}

	ATQ[0] = dataRX[13];
	ATQ[1] = dataRX[14];

	if ((dataRX[9]== 0xD5) & (dataRX[10] == 0x4B) & (dataRX[11] == 0x01)) {
		return 0;
	} else {
		return 1;
	}
}
//**********************************************************************
//!A block must be authenticated before read and write operations
uint8_t authenticate(uint8_t *UID, uint8_t blockAddress, uint8_t *keyAccess)
{
	dataTX[0] = 0x0F;
	lengthCheckSum(dataTX);
	dataTX[2] = 0xD4;
	dataTX[3] = 0x40; // inDataEchange
	dataTX[4] = 0x01; //Number of targets
	dataTX[5] = 0x60; // Authentication code
	dataTX[6] = blockAddress;
	for (int i = 0; i < 6 ; i++) {
		dataTX[i + 7] = keyAccess[i];
	}
	dataTX[13] = UID[0];  dataTX[14] = UID[1];
	dataTX[15] = UID[2];  dataTX[16] = UID[3];
	dataTX[17] = 0x00;
	checkSum(dataTX);
	sendTX(dataTX , 18 ,14);

	if ((dataRX[9]== 0xD5) & (dataRX[10] == 0x41) & (dataRX[11] == 0x00)) {
		return 0;
	} else {
		return 1;
	}
}

//**********************************************************************
//!A block must be authenticated before read and write operations
uint8_t authenticateB(uint8_t *UID, uint8_t blockAddress, uint8_t *keyAccessB)
{
	dataTX[0] = 0x0F;
	lengthCheckSum(dataTX);
	dataTX[2] = 0xD4;
	dataTX[3] = 0x40; // inDataEchange
	dataTX[4] = 0x01; //Number of targets
	dataTX[5] = 0x61; // Authentication code
	dataTX[6] = blockAddress;
	for (int i = 0; i < 6 ; i++) {
		dataTX[i + 7] = keyAccessB[i];
	}
	dataTX[13] = UID[0];  dataTX[14] = UID[1];
	dataTX[15] = UID[2];  dataTX[16] = UID[3];
	dataTX[17] = 0x00;
	checkSum(dataTX);
	sendTX(dataTX , 18 ,14);

	if ((dataRX[9]== 0xD5) & (dataRX[10] == 0x41) & (dataRX[11] == 0x00)) {
		return 0;
	} else {
		return 1;
	}
}
//**********************************************************************
//!Write 16 bytes in address .
uint8_t writeData(uint8_t address, uint8_t *blockData)  //!Writing
{
	Serial.print("                ");
	dataTX[0] = 0x15;
	lengthCheckSum(dataTX); // Length Checksum
	dataTX[2] = 0xD4;
	dataTX[3] = 0x40;//inDataEchange CODE
	dataTX[4] = 0x01;//Number of targets
	dataTX[5] = 0xA0;//Write Command
	dataTX[6] = address; //Address		

	for (int i = 0; i < 16; i++) {
		dataTX[i+7] = blockData[i];
	}

	dataTX[23] = 0x00;
	checkSum(dataTX);
	sendTX(dataTX , 24 ,14);		

	if ((dataRX[9]== 0xD5) & (dataRX[10] == 0x41) & (dataRX[11] == 0x00)) {
		return 0;
	} else {
		return 1;
	}
}
//**********************************************************************
//!Read 16 bytes from  address .
uint8_t readData(uint8_t address, uint8_t *readData) //!Reading
{
	Serial.print("                ");

	dataTX[0] = 0x05;
	lengthCheckSum(dataTX); // Length Checksum
	dataTX[2] = 0xD4; // Code
	dataTX[3] = 0x40; // Code
	dataTX[4] = 0x01; // Number of targets
	dataTX[5] = 0x30; //ReadCode
	dataTX[6] = address;  //Read address
	dataTX[7] = 0x00;
	checkSum(dataTX);
	sendTX(dataTX , 8, 30);
	memset(readData, 0x00, 16);  

	if ((dataRX[9]== 0xD5) & (dataRX[10] == 0x41) & (dataRX[11] == 0x00)) {
		for (int i = 12; i < 28; i++) {
			readData[i-12] = dataRX[i];
		}
		return 0;
	} else {
		return 1;
	}
}
//**********************************************************************
//!The PN532 sends back the version of the embedded firmware.
bool getFirmware(void)  //! It is needed to launch a simple command to sycnchronize
{
  Serial.print("                ");

	memset(dataTX, 0x00, 35);
	dataTX[0] = 0x02; // Length
	lengthCheckSum(dataTX); // Length Checksum
	dataTX[2] = 0xD4; // CODE
	dataTX[3] = 0x02; //TFI
	checkSum(dataTX); //0x2A; //Checksum   

	sendTX(dataTX , 5 , 17);
	Serial.print("\n");
	Serial.print("Your Firmware version is : ");

	for (int i = 11; i < (15) ; i++){
		Serial.print(dataRX[i], HEX);
		Serial.print(" ");
	}
	Serial.print("\n");
}

//**********************************************************************
//!Print data stored in vectors .
void print(uint8_t * _data, uint8_t length)
{
	for (int i = 0; i < length ; i++){
		Serial.print(_data[i]);
		Serial.print(" ");
	}
	Serial.print("\n");
}
//**********************************************************************
//!This command is used to set internal parameters of the PN532,
bool configureSAM(void)//! Configure the SAM
{
	Serial.print("               ");

	dataTX[0] = 0x05; //Length
	lengthCheckSum(dataTX); // Length Checksum
	dataTX[2] = 0xD4;
	dataTX[3] = 0x14;
	dataTX[4] = 0x01; // Normal mode
	dataTX[5] = 0x14; // TimeOUT
	dataTX[6] = 0x00; // IRQ
	dataTX[7] = 0x00; // Clean checkSum position
	checkSum(dataTX);

	sendTX(dataTX , 8, 13);
}
//**********************************************************************
//!Send data stored in dataTX
void sendTX(uint8_t *dataTX, uint8_t length, uint8_t outLength)
{
	Serial.write(0x00);
	Serial.write(0x00);
	Serial.write(0xFF); 

	for (int i = 0; i < length; i++) {
		Serial.write(dataTX[i]);
	}

	Serial.write(0x00);
	getACK();
	waitResponse();// Receive response
	getData(outLength);
}
//**********************************************************************
//!Wait for ACK response and stores it in the dataRX buffer
void getACK(void)
{
	delay(5);
	waitResponse();
	for (int i = 0; i < 5 ; i++) {
		dataRX[i] = Serial.read();
	}
}
//**********************************************************************
//!Wait the response of the module
void waitResponse(void)
{
	int val = 0xFF;
	int cont = 0x00;
	while(val != 0x00) { //Wait for 0x00 response
		val = Serial.read();
		delay(5);
		cont ++;
	}
}
//**********************************************************************
//!Get data from the module
void getData(uint8_t outLength)
{
	for (int i=5; i < outLength; i++) {
		dataRX[i] = Serial.read();//read data from the module.
	}
}
//**********************************************************************
//!Calculates the checksum and stores it in dataTX buffer
void checkSum(uint8_t *dataTX)
{
	for (int i = 0; i < dataTX[0] ; i++) {
		dataTX[dataTX[0] + 2] += dataTX[i + 2];
	}
	byte(dataTX[dataTX[0] + 2]= - dataTX[dataTX[0] + 2]);
}
//**********************************************************************
//!Calculates the length checksum and sotres it in the buffer.
uint8_t lengthCheckSum(uint8_t *dataTX)
{
	dataTX[1] = byte(0x100 - dataTX[0]);
}

/*

Tutorial de Diegotecnology.es para mas información sobre este tutorial visita la web

*/

Con este tutorial tenéis de sobra para empezar con el RFID de arduino, tened paciencia, 
no es fácil trabajar con esta tecnología. Para proximos tutoriales prepararé como formatear tarjetas RFID 
que vienen con el mensaje NDEF predefinido de fabrica.

 

Related Posts

About the Author:

Técnico en equipos electrónicos de consumo, técnico superior en desarrollo de productos electrónicos y estudiante de ingenieria informatica. Más sobre mí en: http://www.diegotecnology.es/diego-romano/

16 Comments + Add Comment

  • Hola Diego,
    ante todo enhorabuena y muchas gracias por tus artículos y tus trabajos!!
    Referente a la tecnología RFID me gustaría preguntarte qué componentes serían necesarios para una alarma anti theft con tags que pudieran ser leídos a una distancia de 1000mm a 2000mm. Sería posible llevar a cabo el proyecto con una simple Arduino UNO? y qué modelo de tarjeta reader RFID sería recomendable? Supongo que los tags deberían ser UHF pues tengo entendido que aceptan un mayor rango de distancia.
    Gracias de antemano y disculpas por mi desconocimiento sobre el tema.
    Saludos

    • Hola,

      Pues la verdad es que estos dispositivos de RFID siguen un standard de telecomunicaciones que limita la potencia de la señal para la identificación de tags. Probablemente con cualquier lector rfid si lo pasas por un amplificador y le adaptas una antena quizá te pueda servir pero solo estoy especulando, no se si funcionaría.
      Respecto a la frecuencia también hay standares de telecomunicaciones en las que se usa la frecuencia 13.56 Mhz y 125 Khz para estos dispositivos, puedes elegir la que quieras.

      Saludos.

      • Muchas gracias Diego, es lo que me imaginaba más o menos.

        Saludos y buen fin de semana 😉

  • Hola esta información es muy útil, gracias. He trabajado con esta tecnología mas o menos de dos a tres semanas y ya acabe mi aplicación, sin embargo en el transcurso del aprendizaje grabe por error el trailer de un bloque, y al momento de leer, procede hasta ese bloque y no puede continuar, hay alguna forma de darle nuevamente el encabezado a la tarjeta???? Por favor necesito una mano ;). Yo utilizo un arduino 1 una mifare de 1K, y un modulo rfid rd522

    • Hola,

      La verdad es que ami me paso lo mismo, cambie el trailer de algún bloque para darle nuevas contraseñas o diferentes permisos y deje el tag inservible, no se decirte como se podría reestablecer el tag o cambiar ese sector. Si lo descubres, me interesaría saberlo tambien.

      Saludos.

  • Buenos dias, quisiea saber si ustedes saben cual es la distancia maxima a la que el arduino con rfid lee los tags, tambien megustaria saber si saben cuantos tags puede leer al mismo tiempo.

    Gracias.

    • La distancia máxima es aproximadamente 5 cm, tiene unos standard que lo regulan y no permiten mayor potencia, supongo que por la invasión de privacidad que puede suponer. y tags solo puede leer de uno en uno pero la lectura dura microsegundos

      • Hola Diego

        Como puedo leer y guardar los valores de las tarjetas en un SQL Server ?

        Saludos.

        • Hola,

          Tendrás que darle conectividad a tu dispositivo (wifi o ethernet) y desde ahi ya lanzar la petición sql contra tu servidor para insertar los datos que quieras meter.

          Saludos.

          • gracias por la info, es muy util, he empezado hace poco con RFID, trabajo con Arduino uno y una mifare de 1K

            Llevo solo dos semanas en ello y me está costando un poco, este tutorial me va a venir muy bien para terminar mi aplicación.

            un saludo desde Salamanca!

  • Hola diego, quisiera preguntarte que como podria hacer un programa para leer los numeros de las tarjetas, acabo de adquirir el RFID y no tengo el numero de las tarjetas no se si sea necesario para la programacion

    • En el programa que tienes en la web, la variable _UID es el numero de la tarjeta, si lo modificas el programa y lo imprimes por pantalla podrás verlo.

  • Hola, esta información es justo lo que necesito para realizar un proyecto, pero no consigo el PN532, dime el RFID RD522 con librería de Miguel Balboa puede ser compatible. Saludos desde
    Argentina

  • Hola diego, muy interesantes tu proyecto de verdad me fue muy útil pero, pero me podrías orientar pues necesito un sistema que me lea una información a una tarjeta no necesariamente rfid sino otra tipo a una distancia máxima de 5 mts no menos pero tiene que ser por arduino, que me recomiendas tu por favor, a soy es aficionado a esta programación no soy experto.

  • Hola, me interesa mucho tu proyecto es de gran importancia y ayuda, pero como puedo obtener los códigos porque no puedo copiarlos desde la página..
    Gracias x tu ayuda

  • hola, estos ejemplos funcionan con el lector RDM6300 de 125Khz?
    Saludos

Leave a comment

Accede al blog o regístrate!

Licencia Creative Commons

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información.plugin cookies

ACEPTAR