viernes, 26 de enero de 2024

SPI Identificacion rfID con RC522

Uso del modulo RC522 con PIC

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.

La programación se realizara utilizando MPLABX y el compilador XC8 ambos disponibles en la pagina de microchip. Aquí dejo los enlaces de las versiones utilizadas para nuestro ejemplo:  <<MPLABX v6.15>>   <<XC8 v2.45>>
La configuración del entorno se utiliza el pack PIC16Fxxx_DFP(1.5.151)
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
El termino RFID(Radio Frequency Identification), hace referencia al sistema de identificación basado en radiofrecuencia, el cual posibilita el almacenamiento y recuperación de datos en forma remota utilizando etiquetas o tarjetas de identificación diseñadas para este fin.
El sistema opera en los rangos de 125 134kHz, 140 148.5kHz clasificado como frecuencia baja y 13.56MHz en frecuencia alta. El conjunto esta formado de dos partes:

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.
El lector mantiene a su alrededor un campo electromagnético de modo que al acercar una etiqueta al lector, ésta se alimenta de la energía inducida por el campo electromagnético, estableciendo así la comunicación.
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. 
En cuanto a la etiqueta que utilizaremos, MIFARE es una tecnología de tarjetas inteligentes sin contacto, propiedad de NXP Semiconductors que cumplen con el estándar ISO-14443 tipo A. Siendo actualmente una de las que mayor uso tiene a nivel mundial.
En forma general podemos encontrarlos bajo la siguiente clasificación:
  • MIFARE Ultralight 512 bit Sin Seguridad
  • MIFARE Classic 1K-4Kbytes Seguridad Crypto-1
  • MIFARE Desfire 4Kbit Seguridad 3DES
El ISO-14443 consta de cuatro partes y se describen dos tipos de tarjetas, el tipo A y el tipo B, las principales diferencias entre ambas, se centra en el mecanismo de modulación, codificación y protocolo de inicialización.
 
Descripción del Modulo RC522.
Es un lector para tarjetas rfID basado en el circuito integrado MFRC522, opera en frecuencia 13.56MHz y soporta ISO14443 tipo A. El modulo es de fácil conexión al microcontrolador mediante la interfaz serial SPI el cual puede opera hasta los 10MHz, con alimentación de 3.3V y consumo inferior a los 100mA.  La fig3. ilustra la distribución de pines del modulo RC522, la conexión al modulo sera directa siempre que el microcontrolador trabaje con 3.3V, caso contrario era necesario convertidores de nivel en las lineas MISO/MOSI/SCK/SS.
Fig3. Pines modulo RC522

Descripción de la Tarjeta MiFare 1K.
Esta tarjeta desarrollada por NXP posibilita llevar a cabo transacciones en menos de 100ms, lo cual resulta adecuado para aplicaciones como el cobro de peaje, boletería y control de acceso. En cuanto a sus características describiremos tres:
 
1. Identificación.  Provee un mecanismo de Anti-colisión que posibilita la lectura simultanea de varias tarjetas, el proceso dura aproximadamente 3ms, con incremento de 1ms por cada colisión detectada.
 
2. Almacenamiento. Consta de una memoria EEPROM con capacidad de 1kB, la misma que se encuentra distribuida en 16 sectores, cada sector formado por 4 bloques y cada bloque formado por 16 bytes, ver fig4.
Fig4. Mapa de memoria EEPROM 1kbyte

3. Seguridad. Cuenta con identificador único (4 bytes), autenticación mutua de tres pasos y clave de acceso por sector (KeyA/B). El proceso de autenticación de tres pasos se ilustra en la fig5.
Fig5. Procedimiento de autenticación de tres pasos
Observe que de acuerdo al esquema que muestra la Fig5. las operaciones en memoria requieren completar el proceso de autenticación, el cual implica validar las llaves A/B para acceder a cada bloque y efectuar cambios incluyendo la actualización de llaves, el proceso de autenticación esta limitado una cantidad de intentos, pasado la cantidad de intentos el acceso quedara bloqueado de manera irreversible. Este proceso se comentara en una próxima actualización de la presente publicación.
 
A raíz de la amplia aceptación de esta tecnología y el buen éxito de la familia MiFARE Classic, los requisitos de aplicación y las necesidades de seguridad se han incrementado, por lo tanto, ya no se recomienda su uso en aplicaciones de seguridad relevantes, siendo una alternativa la serie MiFARE Plus.
 
 Esquema del circuito PIC

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 configuracn 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
Una vez recuperado el identificador y numero de serie de la tarjeta, en las variables rfid_tagtype y rfid_serialnum, se procede a enviar por el puerto UART un mensaje con la siguiente escrutura: ID: 0000h N:00000000

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

Conclusiones y Recomendaciones.
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.
 
Sin mas que mencionar agradezco tu visita al blog y espero que el ejemplo visto pueda ser útil en tu formación y el proyecto que desarrollas.
Atte. Pablo Zárate Arancibia
email: pablinza@me.com / pablinzte@gmail.com, @pablinzar
Santa Cruz de la Sierra - Bolivia



No hay comentarios.:

Publicar un comentario