Ir al contenido principal

Te puede intersar

Conectando ESP8266 a la nube de Amazon(AWS) - Core IOT

RFID con arduino y raspberry pi + base de datos

Hola en esta entrada mostraremos como hacer un sistema RFID para control de acceso o control de asistencias, para ello haremos uso un arduino con el cual realizaremos la lectura y procesamiento de las tarjetas rfid, una raspberry pi con el cual implementaremos una base de datos en sqlite y recibiremos la información del arduino mediante comunicación serial y un parlante que nos servirá como indicador de acceso.

Vídeo:


Materiales:

  • Arduino UNO
  • Raspberry pi 3b+
  • Modulo RFID RC522
  • Parlante con conector rca o para raspberry
  • Jumpers

Programando arduino para lectura de RFID:

Empezaremos realizando el código para leer las tarjetas RFID con el modulo RC522 en arduino, pero antes echemos un vistazo a las conexiones necesarios entre el modulo con nuestro arduino. 

Primero debemos saber que el modulo RC522 utiliza el protocolo SPI para comunicación, dicho protocolo utiliza 3 pines para su propósito (MOSI , MISO,SCK,SS), de donde el pin SCK define el ciclo de reloj y los pines MOSI y MISO definen la comunicación de maestro a esclavo y de eslavo a maestro respectivamente (en nuestro caso Arduino - modulo RC522) y el pin SS define el dispositivo esclavo.

En arduino los pines descritos en el párrafo anterior se encuentras definidos y los utilizaremos haciendo uso de la librería SPI.h. A continuación mostramos los pines designados para SPI en arduino UNO:

Pines SPI arduino
(Los pines de SPI pueden variar según la versión que utilices puedes revisarlo AQUI)

Teniendo claro estos conceptos revisemos las conexiones entre el arduino con el modulo RC522 en la siguiente tabla:

Conexion de arduino con MFRC522
Ahora escribimos el siguiente código en arduino:

#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN  9    //Pin 9 para el reset del RC522
#define SS_PIN  10   //Pin 10 para el SS (SDA) del RC522
#define LED 7

MFRC522 mfrc522(SS_PIN, RST_PIN); 

void setup() {
  Serial.begin(9600); //Iniciamos La comunicacion serial
  SPI.begin();        //Iniciamos el Bus SPI
  mfrc522.PCD_Init(); // Iniciamos el MFRC522
  pinMode(7,OUTPUT);
}

byte ActualUID[4]; //almacenará el código del Tag leído

void loop() {
	//Enviamos codigo de tarjeta RFID si hay una nueva
    enviarCodigoRFID();
    //Leemos por el puerto serial valores del raspberry pi
    char valor_raspberry = Serial.read();
    
    //Si valor recibido es 'P' encendemos el LED
    if(valor_raspberry == 'P' ){
      digitalWrite(LED,HIGH);
      delay(3000);
      digitalWrite(LED,LOW);
    }
}

//Envia un codigo RFID en una cadena de 8 caracteres
void enviarCodigoRFID(){ ;
//Limpia la tarjeta rfid anteriormente leiada
    limpiarVector();
    leerCodigo();
    //Si se leyo tarjeta rfid
    if(!compararCodigo(ActualUID)){
      for(byte i = 0; i < 4; i++){
        if(ActualUID[i] <= 15){
          Serial.print(0);
          Serial.print(ActualUID[i],HEX);
        }else{
          Serial.print(ActualUID[i],HEX);
        }
      }
    }
}

void limpiarVector(){
  for(int i = 0; i<4;i++){
    ActualUID[i]=0;
  }
}

//Lee el codigo de la tarjeta rfid
void leerCodigo() {
    String txt;
    // Revisamos si hay nuevas tarjetas  presentes
    if ( mfrc522.PICC_IsNewCardPresent()){  
      //Sfeleccionamos una tarjeta
            if(mfrc522.PICC_ReadCardSerial()) {
                  // Enviamos serialemente su UID
                 for (byte i = 0; i < mfrc522.uid.size; i++){
                      ActualUID[i]= mfrc522.uid.uidByte[i];          
                 }    
                 //Terminacion de lectura de la tarjeta
                  mfrc522.PICC_HaltA();                 
            }
    }
}

boolean compararCodigo(byte array1[]){
  byte  array2[]={0,0,0,0};
  if(array1[0] != array2[0])return(false);
  if(array1[1] != array2[1])return(false);
  if(array1[2] != array2[2])return(false);
  if(array1[3] != array2[3])return(false);
  return(true);
}

Analizando un poco el código, el arduino se encuentra a la espera de una nueva tarjeta rfid, si se detecta una nueva tarjeta enviara por el puerto serial el código rfid como una cadena de tamaño 8, luego de ello esperara leerá la respuesta del rfid en caso el usuario sea autorizado enviara un carácter 'P' con el cual se encenderá un led en el arduino por 3 segundos.

Creando la base de datos SQLite en raspberry 

Continuando con el proyecto necesitamos crear el programa principal que recibira los códigos RFID procesados por el arduino ademas de realizar la validación con la base de datos. 

Entonces empezaremos creando la base de datos apoyándonos en DB Browser, el cual instalaremos en nuestra raspberry pi de la ejecutando los siguientes comandos en el CLI :

    sudo apt-get update

    sudo apt-get install sqlite3

    sudo apt-get install sqlite3browser

Una vez finalizada la instalación utilizamos la interfaz gráfica del raspberry OS, si no tienes una pantalla puedes usar un software de escritorio remoto como VNC  viewer el cual viene instalado por defecto en raspberry OS por lo que solo debes instalar el programa en tu PC (puedes descargarlo desde AQUI ).

Continuando con el proyecto en nuestro Raspberry OS vamos a inicio > accesorios > DB Browser for SQLITE. Esperamos que cargue el programa y creamos nuestra base de datos en NEW DATABASE, luego vamos a la pestaña de EXECUTE SQL y copiamos el siguiente código:

    ---Querys de sqlite---


    create table usuarios(

rfid varchar(8) not null primary key,

nombre varchar(30) not null,

apellido varchar(40) not null

    ) ;


    create table registro(

evento_id integer not null primary key autoincrement,

user_id varchar(8) not null,

fecha date,

hora time,

constraint fk_usuarios 

foreign key (user_id) references usuarios(rfid)

    );


Ejecutamos con el botón de play y guardamos los cambios en Write Changes. Con este query  creamos 2 tablas una que almacenara los datos del usuario como su nombre, apellido y el tag RFID que le fue asignado, la segunda tabla almacenara los datos referentes a los eventos cada que un usuario se identifique con su tag RFID. Finalizado este procedimiento reconocemos el archivo .db que generamos al crear nuestra base de datos ya que sera el que usaremos mas adelante.


(Imagen de la interfaz de DB BROWSER)

También puedes pasar por esta otra ENTRADA en la cual puedes ver como instalar, utilizar y crear bases de datos desde cero de forma simple con DB Browser para SQLITE. O puedes descargar el archivo .db que utilizamos para este proyecto al final en botón de descarga junto con otros archivos.

Continuando ahora volvemos a la linea de comandos y crearemos primero un modulo de python que contendrá el código necesario para interactuar con nuestra base de datos. Primero creamos un nuevo archivo de python con el siguiente comando en la CLI:

    sudo nano accesoDB.py

En donde accesoDB.py es el nombre del modulo en mi caso, al ejecutar el comando se nos abrirá el editor de texto en donde escribiremos el código que se muestra a continuación:



import sqlite3
from sqlite3 import Error
from datetime import datetime

def obtenerFecha():
    now = datetime.now()
    fecha_hoy = str(now.year) + "-" + str(now.month) + "-" + str(now.day)
    return fecha_hoy

def obtenerHora():
    now = datetime.now()
    hora_hoy= str(now.hour) + ":" + str(now.minute)
    return hora_hoy

def conectarBD(nombre_db):

    conexion = None

    try:
        conexion = sqlite3.connect(nombre_db)
    except Error as e:
        print(e)
    finally:
        if conexion != None:
            print('Conexion con base de datos exitosa')

    return conexion

def consultarTabla(conexion,tabla='usuarios'):

    if conexion != None:
        sql = "select * from {0}".format(tabla)
        cursor = conexion.cursor()
        cursor.execute(sql)

        filas = cursor.fetchall()

        for fila in filas:
            print(fila)

def consultarUsuario(conexion,nombre):
    if conexion != None:
        try:
            sql=("select usuarios.rfid, usuarios.nombre, usuarios.apellido, registro.fecha, registro.hora "
                 "from usuarios "
                 "join registro "
                 "on usuarios.rfid = registro.user_id "
                 "where usuarios.nombre like \"{0}\"".format(nombre))
            cursor = conexion.cursor()
            cursor.execute(sql)

            filas = cursor.fetchall()

            for fila in filas:
                print(fila)
        except Error as e:
            print(e)

def buscarRFID(conexion,rfid):
        nombre="Desconocido"

        if conexion != None:
                cursor = conexion.cursor()
                sql = ("select nombre from usuarios"
                        " where rfid = \"{0}\"".format(rfid))
                cursor.execute(sql)
                rpta = cursor.fetchone()
                nombre = rpta

        return nombre

def agregarUsuario(conexion,rfid,nombre,apellido):
    if conexion != None:
        sql = ("insert into usuarios (rfid,nombre,apellido) "
               "values (\"{0}\",\"{1}\",\"{2}\")".format(rfid,nombre,apellido))
        cursor = conexion.cursor()
        cursor.execute(sql)
        conexion.commit()

        return True

    return False

def agregarRegistro(conexion,user_id,hora,fecha):
    if conexion != None:
        sql = ("insert into registro (user_id,fecha,hora) "
               "values (\"{0}\",\"{1}\",\"{2}\")".format(user_id,hora,fecha))
        cursor = conexion.cursor()
        cursor.execute(sql)
        conexion.commit()
        return True

    return False

def modificar(conexion,rfid,nombre=' ',apellido=' '):
    if conexion != None:
        sql = ("update usuarios "
               "set nombre = \"{0}\" , apellido=\"{1}\" "
               "where rfid = \"{2}\" ".format(nombre,apellido,rfid))
        cursor = conexion.cursor()
        cursor.execute(sql)
        conexion.commit()
        return True

    return False

#AGREGAR NUEVOS USUARIOS

conn = conectarBD("accesoSSTECH.db")
rpta = agregarUsuario(conn,'rfid','NOMBRE','APELLIDO')
print(rpta)
conn.close()


En este modulo las lineas finales las hemos dejado para ingresar nuevos usuarios, solo debemos cambiar rfid por el tag respectivo al igual que los nombres y apellidos de usuario aunque también podemos hacerlo desde DB BROWSER en browse data.

Ahora crearemos el código principal de nuestro programa con el cual realizaremos la comunicación con el arduino y con la base de datos.Para ello creamos el modulo acceso.py y escribimos el siguiente código:


import serial
import time
import pygame.mixer as mixer
import querysDB as sqliteDB

#Se crea el puerto para comunicacion serial con arduino
arduino = serial.Serial('/dev/ttyACM0',baudrate = 9600)

try:
        arduino.open()
except:
        print("RFID LISTO")

#Funcion para reproducir archivos de audio. wav
def reproducirAudio(audio):
        mixer.init(frequency=22050, size=-16, channels=2, buffer=706)
        mixer.music.load(audio)
        mixer.music.play()
        while mixer.music.get_busy():
                continue
               
# Ciclo principal de ejecucion del programa
while True:

        if arduino.inWaiting() > 0:
		#Lee si hay un mensaje nuevo por parte del arduino
                rpta_rfid = arduino.read(8)
                print("TAG RFID: {0}".format(rpta_rfid))
                conn = sqliteDB.conectarBD('accesoSSTECH.db')
				# Valida el tag rfid
                busqueda = sqliteDB.buscarRFID(conn,rpta_rfid)

                if(busqueda != None):
                		#En caso el usuario fue indentificado
                        print("Usuario reconocido\n")
                        arduino.write("P")
                        time.sleep(.5)
                        reproducirAudio('acceso_permitido.wav')
                        time.sleep(.5)

                        fecha = sqliteDB.obtenerFecha()
                        hora = sqliteDB.obtenerHora()
                        sqliteDB.agregarRegistro(conn,rpta_rfid,fecha,hora)
                        time.sleep(.2)
                else:
                        #caso contrario
                        print("Usuario Desconocido\n")
                        reproducirAudio('acceso_denegado.wav')
                        time.sleep(.5)

                conn.close()


Adicional mente le agregamos un parlante para reproducir audios de confirmación o denegación al identificar un usuario , esto lo implementamos con la función reproducirAudio() en la cual abrimos un archivo de audio .wav los cuales puedes descargar en el botón de descargar al final de esta entrada. El parlante puede ser cualquiera que tengamos a la mano solo debemos conectarlo al jack 3.5 para audio de nuestra raspberry y listo.

Para finalizar conectamos el puerto serial de nuestro arduino conectado con el modulo RC522 a la raspberry pi al puerto USB, y ejecutamos el comando python acceso.py en la linea de comandos y comenzamos a probar nuestro sistema.

Si queremos ver los registros que valla generando nuestro sistema podemos usar nuevamente DB BROWSER en browse data o podemos crear un nuevo modulo de python y escribir el siguiente codigo:


	import querysDB as sqliteDB

	conn = sqliteDB.conectarBD('accesoSSTECH.db')

	sqliteDB.consultarTabla(conn,'registro')

Listo hemos finalizado por ahora. En este proyecto hemos usado conexión serial entre arduino y raspberry pi aunque no era del todo necesario ya que podríamos a ver usado una raspberry pi solamente para realizar todo el sistema, sin embargo lo realizamos así para poder manejar otros sensores a futuro. En futuras entradas estaremos viendo variantes de este proyecto y algunas mejoras que podemos agregar. Por lo pronto espero que este pequeño proyecto te sirva de ayuda y si tienes alguna duda o sugerencia no dudes en comentarlo, también si tienes alguna variante o mejora a este proyecto que le pueda interesar a los demás también te invito a comentarlo.

Muchas gracias por llegar hasta aquí, hasta la próxima.

DESCARGA DE ARCHIVOS:

Síguenos en nuestras redes:


 

Puedes escribirnos al correo: sstechnologyrp@gmail.com para cualquier consulta personal

Comentarios

Entradas populares