Fig1. Elementos para rfID |
Este sitio fue creado para compartir el mutuo interés en la electrónica y en especial la programación de microcontroladores PIC. Descrita la introducción te agradezco por visitar mi blog recordando que siempre estamos abiertos a cualquier critica constructiva relacionada con esta publicación.
En esta ocasión veremos como comunicar un microcontrolador PIC16F con el modulo RC522, el cual permite llevar a cabo al lectura de tarjetas basadas en la tecnología rfID. El propósito sera de establecer la comunicación SPI, recuperar el numero serial de una tarjeta MiFARE y enviar este numero como mensaje a través del puerto serie UART del PIC16F.
Mencionar también que es necesario contar con conocimientos mínimos sobre programación en lenguaje C y el uso de microcontroladores PIC16.
Introducción a la Tecnología rfID
Fig2. Sistema rfID |
- Etiqueta(Transpondedor): formado por una antena(RF), la unidad de control digital(MCU) y una memoria(EEPROM).
- Lector(Interrogador): compuesto por la antena(RF), un decodificador y el puerto de comunicación serial UART/SPI/I2C.
La distancia de lectura depende de la potencia del módulo lector, en nuestro caso son aproximadamente 50mm(RC522), pero existen lectores con mayor rango de alcance.
- MIFARE Ultralight 512 bit Sin Seguridad
- MIFARE Classic 1K-4Kbytes Seguridad Crypto-1
- MIFARE Desfire 4Kbit Seguridad 3DES
Fig3. Pines modulo RC522 |
Fig5. Procedimiento de autenticación de tres pasos |
La Fig6. muestra el esquema de conexión del microcontrolador PIC16F al modulo RC522. En este circuito el PIC16F esta alimentado con voltaje de 5V, y se utiliza un regulador MCP1702 para alimentar al modulo RC522 con 3.3V, debido a que las lineas de salida SDO, SCK y SS del PIC16F operan con 5V, se utilizan divisores resistivos para limitar el nivel de voltaje en las entradas del modulo RC522. Por otro lado la comunicación serial con la PC, utiliza un convertidor USB a UART, en nuestro caso es el CP-2102, pero puede ser cualquier otro conversor, porque solo se requiere un par de conexiones TXD y RXD con PIC16F. Finalmente existe un diodo LED conectado al pin RE2 que servirá para indicar la actividad del programa.
Fig6. Esquema del circuito PIC16-RC522 |
Programa del Microcontrolador PIC
El objetivo de este programa es comprobar la conectividad PIC16F - RC522, para lo cual se realizara la identificación de una tarjeta MiFARE, para obtener la etiqueta del modelo de tarjeta y el numero de serie correspondiente, sin entrar en la fase de autenticación y operaciones en la memoria EEPROM. Pero quedo comprometido a futuro publicar otra entrada explicando con mas detalle todo el proceso y operaciones adicionales que se pueden realizar en la tarjeta.
En cuanto a los procedimiento y funciones utilizadas en el programa, estos se resumen en los archivos de cabecera rc522.h y spi.h, aclarar el código ha sido modificado a partir de fuentes encontradas en la red.
Ahora exploraremos las secciones que tiene el código principal main.c con una breve explicación de lo que se pretende realizar. En la parte final dejo el enlace para descarga del proyecto MPLABX que contiene todos lo archivos utilizados.
#pragma config FOSC = INTRC_NOCLKOUT, WDTE = OFF, LVP = OFF
#include <xc.h>
#include <stdint.h>
#include <stdio.h>
#include "spi.h"
#include "rc522.h"
#define LEDpin PORTEbits.RE2 //Pin para indicador led
volatile uint8_t tick1ms; //Bandera de tiempo para 1ms
volatile uint16_t tickcnt; //Contador de 1ms, reinicia cada seg.
uint8_t buff[8];
uint16_t rfid_tagtype; //Variable para el tag_id
uint32_t rfid_serialnum; //Variable para el serial number
void main(void) //Código principal
{
setup(); //Configura los puertos y módulos
RC522_Init(); //Inicializa el modulo
while(1)
{
if(tick1ms) //Condición por cada 1ms
{
tick1ms = 0;
taskled();
if(tickcnt == 100) //Solo cuando pasen 100ms
{
if(RC522_Request(PICC_REQIDL, buff) == MI_OK)
{
rfid_tagtype = buff[0];
rfid_tagtype <<= 8;
rfid_tagtype |= buff[1];
if(RC522_ReadCardSerial(buff) == MI_OK)
{
rfid_serialnum = buff[0];
rfid_serialnum <<= 8;
rfid_serialnum |= buff[1];
rfid_serialnum <<= 8;
rfid_serialnum |= buff[2];
rfid_serialnum <<= 8;
rfid_serialnum |= buff[3];
printf("ID:%Xh N:%lu\r\n", rfid_tagtype, rfid_serialnum);
}
RC522_Halt();
}
}
}
}
}
En las lineas luego de la configuración e inicialización de los modulo, el programa ingresa en un bucle condicionado a la bandera tick1ms, que se activa cada milisegundo, para este fin se utiliza la interrupción del temporizador TMR0, la rutina de servicio a la interrupción también controla el incremento de la variable tickcnt reiniciando cuando su valor completa un mil. Dentro del bucle se llama al procedimiento taskled cada 1ms para indicar actividad del programa con un destello de luz. Así mismo dentro del rango del contador tickcnt, cuando este llega al valor de 100ms, se procederá a la identificación de tarjeta, llevando a cabo la detección una vez por segundo, debido que este contador se reinicia a los 1000ms.
Entonces, con intervalo de un segundo se lleva a cabo la detección de tarjetas, a través de la función RC522_Request(PICC_REQIDL, buff), esta función retornara 0 ante la presencia de una tarjeta MiFARE dentro de la zona de proximidad del lector RC522, además copiara en el vector buff dos bytes de identificación de acuerdo a la siguiente tabla:
- 0x4400 = Mifare_UltraLight
- 0x0400 = Mifare_One(S50)
- 0x0200 = Mifare_One(S70)
- 0x0800 = Mifare_Pro(X)
- 0x4403 = Mifare_DESFire
Cuando la identificación es correcta en función a la tabla, se procede a leer el numero de serie con la función RC522_ReadCardSerial(buff), ambas funciones obtiene esta informacion del sector 0, bloque 0 el cual esta destinado únicamente solo para lectura de la informacion proporcionada por el fabricante. vea la fig7.
Fig7. Datos del fabricante, solo para lectura |
Puesto que el proceso transcurre en un periodo menor a 100ms, se procede a colocar el modulo en espera por tiempo restante antes de completar el segundo, con el procedimiento RC522_Halt().
Seguidamente se describe el procedimiento de configuracion de los periféricos, la rutina de interrupción ISR y la tarea para el destello del indicador led.
void setup(void)
{
OSCCONbits.IRCF = 0b111; //Oscilador 8MHz Tcy = 0.5us
while(OSCCONbits.HTS == 0){};
ANSEL = 0; //Pines AN0-AN7 en modo digital
ANSELH = 0; //Pines AN8-AN13 en modo digital
TRISAbits.TRISA5 = 0; //Salida para RC522_CS
TRISEbits.TRISE2 = 0; //Pin de salida LED
OPTION_REGbits.nRBPU = 0;
/* CONFIGURACION UART 9600 BPS*/
BAUDCTLbits.BRG16 = 0; //8-bit BaudGen
TXSTAbits.BRGH = 1; //Modo High Speed
TXSTAbits.TXEN = 1; //Habilita el transmisor UART
//RCSTAbits.CREN = 1; //Habilita el receptor UART
RCSTAbits.SPEN = 1; //Activa el modulo UART
SPBRG = 51; //Formula [8M/(16 * 9600)] - 1
/* CONFIGURACION MSSP MODO SPI */
TRISCbits.TRISC5 = 0; //SDO Salida en modo master
TRISCbits.TRISC3 = 0; //SCK Salida en modo master
SSPCONbits.SSPM = 0b0001; //Master SPI(Fosc/16) 500KHz
SSPSTATbits.SMP = 1; //Data sample at end SMP = 1
SSPCONbits.CKP = 0; //Clock Idle low level SCK=0
SSPSTATbits.CKE = 1;//Positive edge clock enable CKE = 1;
SSPCONbits.SSPEN = 1;//Enable SSP Module
/* CONFIGURACION TIMER0 1MS*/
OPTION_REGbits.T0CS = 0;//Modo Termporizador
OPTION_REGbits.PSA = 0; //Con prescala para el TMR0
OPTION_REGbits.PS = 0b011; //Prescala 1:16
TMR0 = 130; //255-(time/(pre*(4/Fosc)) time=0.001 seg
INTCONbits.T0IF = 0; //Limpia bandera
INTCONbits.T0IE = 1; //Habilita interrupcion TMR0
INTCONbits.GIE = 1; //Habilita interrupciones
}
void __interrupt() isr() //Servicio de interrupcion
{
if(INTCONbits.T0IF) //Interrupcion del TMR0
{
TMR0 += 130; //Restablece contador
INTCONbits.T0IF = 0; //Limpia la bandera
tick1ms = 1; //Activa bandera de tiempo 1ms
if(tickcnt++ > 999) tickcnt = 0; //Reinicio 1s
}
}
void taskled(void) //Destello led
{
static uint16_t cnt = 0;
cnt ++;
if(cnt == 800) LEDpin = 1;
if(cnt > 999)
{
LEDpin = 0;
cnt = 0;
}
}
taskled es un procedimiento que se ejecuta en cada milisegundo, haciendo cuenta de las repeticiones la variable local cnt, que se incrementa desde un valor 0 hasta 999, el led se activara cuando cnt sea 800 hasta que supere los 999, en este lapso el destello durara aproximadamente 200 ms (999 - 800).
Pruebas de funcionamiento
Antes de abrir el proyecto en MPLABX, asegúrate de tener instalado la versión del compilador XC8, una vez confirmado procedemos a abrir el proyecto, y luego de llevar a cabo la exploración de los archivos, procedemos a compilar el programa, si no hay errores procedemos a cargar el código al microcontrolador y llevar a cabo las pruebas de funcionamiento.
En primer lugar debe notar que el led de indicación destella una vez por segundo, esto nos indica la correcta ejecución del programa, restando únicamente acercar una tarjeta RFID para que se lleve a cabo la identificación y se muestre un mensaje a través del puerto serie. Para poder visualizar este mensaje un componente disponible para MPLABX, accediendo a menu->tools->plugins, en esta ventana nos aseguramos de activar la instalación del componentes Simple Serial Port Terminal
Fig8. Instalación de Simple Serial Port Terminal |
Una vez instalado Simple Serial Port Terminal se configurar con el puerto COM asignado al convertidor UART-USB, en windows las asignaciones tiene nombre COMxx, mientras que para linux se cuenta con el acceso al flujo /dev/ttyUSBx.
Finalizada la configuracion del terminal, cada vez que se aproxime una tarjeta MiFARE, veremos un mensaje con el identificador y numero serial como se observa en la Fig9.
Fig9. Mensajes de las tarjetas identificadas |
La fig10, muestra el circuito utilizado para el proyecto, donde se puede observar una placa de pruebas PIC16F, circuito de conversion de nivel, modulo lector RC522 y llavero con chip MiFARE Classic.
Fig10. Circuito PIC utilizado para el programa |
Se verificado el funcionamiento adecuado de la comunicación entre el PIC16F y el modulo RC522 como parte del objetivo de esta publicación, si bien las características de las tarjetas MiFARE posibilitan mayores prestaciones de seguridad, tales como la Autenticación por bloque, y el almacenamiento de variables en memoria con operaciones de auto incremento o decremento. En muchas situaciones solo basta con llevar a cabo la lectura del numero serial, puesto que la identificación de la tarjeta posibilita asociarlo con un elemento u objeto sujeto al control, por ejemplo se puede consultar un base de datos del personal autorizado en base al numero de serie en su tarjeta de control.
Aquí dejo los enlaces para que puedas descargar el proyecto MPLABX, se encuentra en formato gzip recordando que soy usuario de linux y es probable que necesites modificar algunas referencias para compilar con windows.
Atte. Pablo Zárate Arancibia
email: pablinza@me.com / pablinzte@gmail.com, @pablinzar
Santa Cruz de la Sierra - Bolivia