Utilizando el lector NFC RC522 en la Raspberry Pi
La tecnología de Near Field Communications (NFC) se ha vuelto muy popular desde hace un par de años, al incluirse en teléfonos móviles, tarjetas de crédito e incluso pasaportes.
Hace unos días, adquirí algunos lectores NFC para intentar conectarlos a la Raspberry Pi para un par de proyectos que tengo en mente. Esta será una extremadamente-corta entrada, donde les explicaré los avances en su uso y funcionamiento y les compartiré el código que he utilizado para hacer funcionar el módulo lector.
El módulo RFID
Las tecnologías de identificación por radio-frecuencia (RFID) cubren una amplia gama de estándares. Los dispositivos con NFC son aquellos que funcionan utilizando inducción magnética y trabajan a una frecuencia de 13.56MHz.
Usualmente las etiquetas RFID funcionan como simples códigos de barra, es decir, simplemente reportan un número que es identificado por el lector. El estándar NFC tiene la característica particular que permite el envío y recepción de datos, de manera adicional existen estándares que ofrecen cifrado en la comunicación lo que permite almacenar información "sensible" y protegerla en la transmisión. Piensen en las tarjetas de crédito y los pasaportes.
El módulo que elegí es el MF522-AN, este "kit" me gustó mucho porque incluye un pequeño llavero NFC, una tarjeta "S50",, una tableta de pruebas con antena incluida y los pines necesarios que facilitan la conexión.
Este módulo se comunica por medio de la interfaz I2C o SPI. Esta entrada no vamos a detenernos mucho en explicar como funciona esta interfaz ya que lo que más nos interesa saber, es que es una forma muy fácil de conectar sensores a tabletas controladores, en nuestro caso, a la Raspberry Pi.
Configurando nuestra Raspberry Pi
El puerto GPIO posee soporte tanto para I2C como para SPI. Antes de conectar el módulo debemos habilitar el soporte de la siguiente manera:
Editamos el siguiente archivo:
/etc/modprobe.d/raspi-blacklist.conf
Una vez abierto debemos comentar la línea:
blacklist spi-bcm2708
El archivo nos deberá quedar como se muestra aquí:
# blacklist spi and i2c by default (many users don't need them) #blacklist spi-bcm2708 blacklist i2c-bcm2708
Reiniciamos nuestra Raspberry Pi y verificamos que existan los dispositivos con el comando "ls":
pi@raspberrypi ~ $ ls /dev/spidev0.* /dev/spidev0.0 /dev/spidev0.1
Conectando el Módulo
La conexión del módulo es sumamente sencilla como se mostró en la imagen al inicio:
Solo tengan cuidado de no invertir las líneas MOSI y MISO y conectarlas justo como se muestra en el diagráma.
Antes de continuar... Una brevísima explicación de la interfaz SPI
En proyectos anteriores hemos utilizado el puerto serial para Leer/Escribir datos. Dicho puerto tiene la ventaja de que resulta muy fácil de utilizarse y podemos fácilmente procesar los datos que recibimos.
Tanto I2C como SPI son interfaces para comunicación entre circuitos. Este tipo de interfaz utiliza un "bus" para comunicarse es decir un solo cable sirve para enviar o recibir datos desde distintos dispositivos.. Para el caso de SPI tenemos escencialmente 4 líneas:
- MOSI: Master Out Slave In, por esta línea se envían datos en forma serial desde el dispositivo "maestro" a los dispositivos esclavos.
- MISO: Master In Slave Out, por esta línea los dispositivos esclavos envían datos al dispositivo maestro.
- SCK/SCLK: Línea de reloj, aquí se envía un tren de pulsos que se encarga sincronizar las comunicaciones entre los dispositivos.
- CE: Cada dispositivo tiene una línea de "habilitado", en el dispositivo maestro deberían de haber tantas líneas de habilitado como dispositivos esclavos existan. Los dispositivos esclavo en cambio solo tienen una línea CE que les indica cuando tienen que enviar/recibir datos. En este ejemplo la linea SDA hace las veces de "CE" en nuestro lector NFC.
La interfaz SPI si bien "utiliza" más líneas que I2C tiene la ventaja de que alcanza altas velocidades de transferencia (1Mbps), además su implementación usualmente resulta más sencilla ya que utiliza simples línea serie.
Para mayor detalle pueden leer el artículo sobre SPI en la Wikipedia.
El código fuente...
Primero, necesitamos descargar una pequeña biblioteca que nos permitirá acceder al puerto SPI en la Raspberry Pi en python GitHub con el siguiente comando:
git clone https://github.com/lthiery/SPI-Py
Nos cambiamos a la carpeta SPI-Py y ejecutamos:
sudo python setup.py install
Una ves haya terminado descargamos el código fuente de la clase que controla el lector NFC:
git clone https://github.com/mxgxw/MFRC522-python
Para ejecutarlo, simplemente nos cambiamos a la carpeta MFRC522-python y ejecutamos:
sudo python MFRC522.py
Esta vez no voy a explicar en detalle el funcionamiento ya que es bastante más complicado que una comunicación serial simple. Pero intentando resumir un poco el código se encarga de inicializar el lector NFC y mantenerse leyendo continuamente para detectar una tarjeta y leer el ID correspondiente.
MIFAREReader = MFRC522() while continue_reading: (status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL) if status == MIFAREReader.MI_OK: print "Card detected" (status,backData) = MIFAREReader.MFRC522_Anticoll() if status == MIFAREReader.MI_OK: print "Numero de la tarjeta: "+str(backData[0])+","+str(backData[1])+","+str(backData[2])+","+str(backData[3])+","+str(backData[4])
Importante: Esta es una re-escritura en Python del código de ejemplo
para Arduino, aún no está completo, por el momento solo permite detectar
el tipo de tarjeta y leer el número de identificación. Conforme pase el
tiempo actualizaré el resto de funciones.
Sin embargo, con esta funcionalidad muy "sencilla" de lectura del ID podrían generar una secilla aplicación de llave electrónica.
Unas cuantas fotos
Por último les comparto unas cuantas fotos del lector conectado funcionando y del programa en ejecución desde la Raspberry Pi.
No habiendo nada más que decir... ¡Hasta la pŕoxima!
Comentarios
Pero eventualmente por escribir las informaciones en una tarjeta...como se puede hacer? Tiene ya un codigo preparado? Hay un instruccion especial?
Gracias,
Mil millones de gracias por el artículo...
Saludos!!
One thing appears during the test. The program started correctly. While scanning my tags following message appeared:
AUTH ERROR
Card detected
Card read UID: 74,181,103,10,146
Size: 8
AUTH ERROR!!
AUTH ERROR(status2reg & 0x08) != 0
What happend here? I am pretty new to python and I tried to understand what happend in the code, but I really did not understand this message. Can you help me?
if you could email me back at smeck1999@gmail.com it would be much appriciated. Thanks again! - Seth Moeckel
***********************************
Me vendría bien un poco de ayuda si no te importa . He hecho todo correctamente , pero cuando ejecuto el archivo python no pasa nada. que va directamente de vuelta al "usuario @ Examplename ~ $ '
si usted me podría enviar de vuelta a smeck1999@gmail.com sería muy appriciated . Gracias de nuevo ! Esto se tradujo con traductor Google ... espero su no difícil de entender .
Solo un comentario, donde dice de ejecutar "sudo python MFRC522.py", en realidad si no entiendo mal debiera decir "sudo python Read.py" (o Write.py). Es decir MFRC522.py es la libreria, y Read.py y Write.py son los programas de ejemplo que sí tiene sentido ejecutar, verdad?
saludos!
El error que mostraba era el siguiente... "Can't open device: No such file or directory"
Busque por todos lados y aquí como lo solucione:
ejecutas el comando "sudo raspi-config" después seleccionas "Advanced Options" seleccionas "SPI" Y lo habilitas poniendo todo "YES" repites el proceso "Advanced Options" y esta ves seleccionas I2C y de nuevo le das todo "YES" reinicias y funciona ;
El lector no me lee ninguna tarjeta y no sé si puede ser por los warnings que me lanza SPI-Py cuando lo instalo. Dudo de si estos warnings son parte de los mensajes normales o pueden ser los causantes de que el lector no me lea ninguna tarjeta.
La salida por pantalla cuando ejecuto sudo python setup.py install es:
running install
running build
running build_ext
building 'spi' extension
creating build
creating build/temp.linux-armv7l-2.7
gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c spi.c -o build/temp.linux-armv7l-2.7/spi.o
spi.c:197:2: warning: initialization from incompatible pointer type [enabled by default]
spi.c:197:2: warning: (near initialization for ‘SpiMethods[0].ml_meth’) [enabled by default]
creating build/lib.linux-armv7l-2.7
gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro build/temp.linux-armv7l-2.7/spi.o -o build/lib.linux-armv7l-2.7/spi.so
running install_lib
copying build/lib.linux-armv7l-2.7/spi.so -> /usr/local/lib/python2.7/dist-packages
running install_egg_info
Removing /usr/local/lib/python2.7/dist-packages/SPI_Py-1.0.egg-info
Writing /usr/local/lib/python2.7/dist-packages/SPI_Py-1.0.egg-info
¿Eso son los mensajes que se deberían ver o los warning no deberían estar? ¿Me podrías copiar aquí tu salida por pantalla?
Muchas gracias.
Conecta el negativo del led en a una tierra del raspberry y el positivo va a la posicion 7 de los pines del rapberry... "el cuarto pin de la primera fila"
https://unpocodejava.files.wordpress.com/2013/08/image033.png
--------------------------------------------------------------
import RPi.GPIO as GPIO
import spi
import signal
from time import sleep
pinNum=7 # BOARD
GPIO.setmode(GPIO.BOARD)
GPIO.setup(pinNum,GPIO.OUT)
sleep(1)
GPIO.output(pinNum,True)
sleep(0.3)
GPIO.output(pinNum,False)
Por el minuto estoy tratando de recuperar la SD ya que se estropeo al insertar un usb de un teclado inalambrico (eso creo), si no accedo a la sd no puedo cambiar el codigo creo que tendre que hacer el trabajo nuevamente.
Pero mas que nada el problema se produce al intentar usar RPi.GIO dentro de MFRC522.py
Muchas gracias !!!!!
Tienes que escribir esto al principio de tu código
import RPi.GPIO as GPIO
Fíjate bien en como está escrito ya que en tu comentario dices que la librería es RPi.GIO
El tipo de pin se llama GPIO, General Purpose Input/Output, por esto la librería se llama RPi.GPIO.
a ver si me podeis ayudar, ya que mis conocimientos en esta materia son escasos:
Cuando introduzco en la consola, el siguiente comando:
git clone https://github.com/lthiery/SPI-Py
me dice: fatal: destination path 'SPI-Py' already exists and is not an empty directory....¿a alguién se le ocurre que puede estar ocurriendo?...porque el directorio existe.....
Mil gracias de antemano.