Introduction: Estantería Inteligente. Proyecto Final - Computación Física

Se desarrollara un sistema tecnológico de bloqueo y desbloqueo de bandejas que se encuentran en una estantería, según el usuario que interactúe utilizando su identificación. Mediante un sistema de señalización se asegurará que las bandejas retiradas de la estantería sean puestas de nuevo en su lugar.

MATERIALES:

  • Madera MDF (9mm grosor)
  • 1 NodeMcu
  • 2 Servomotores
  • 2 RFID rc522
  • 2 Led's

El NodeMcu sera la placa que utilizaremos para conectar el resto de los componentes y usaremos su modulo WiFi para enviar los datos de los usuarios a un servidor web. Los RFID rc522 y los servomotores servirán para realizar el sistema de bloqueo de las bandejas por medio de cualquier tipo de etiquetas. Finalmente los Led's se usaran para dar una señalización, por medio del color, donde el usuario deberá ponerla bandeja una vez la devuelva.

SOFTWARE:

  • Arduino IDE.
  • Adobe Illustrator (Opcional)
  • Circuits.io (Opcional)

Step 1: Elaboración De Las Bandejas.

Se debe realizar los modelos de las bandejas en un software de edición (en este caso usamos Adobe Illustrator), para posteriormente utilizar una cortadora láser para hacer los cortes y obtener las bandejas. En este caso se utilizo madera MDF de 9mm de grosor. Recuerda que para utilizar una cortadora láser es necesario tener el formato del archivo en .dxf, por lo tanto se puede usar cualquier programa de edición que permita exportar en este tipo de formato.

Las medidas que se utilizaron para hacer la bandeja se pueden apreciar en la imagen adjunta.

Step 2: Elaboración De Los Ganchos.

Para asegurar las bandejas necesitamos ganchos, estos al igual que las bandejas, pueden ser hechos con un software de edición que exporte archivos en formato .dxf para posteriormente obtener los cortes con una cortadora láser.

Step 3: Conexión De Los Componentes.

Para realizar la conexión de los componentes, primero debemos tener en cuenta algo y es, como funcionan los pines en el NodeMCU. En este dispositivo existen dos formas de ver los pines, una es el Index y la otra es el GPIO. El primero es el que se puede visualizar fácilmente en la placa ya que estos corresponden al D0, D1, D2,... etc. Sin embargo los que necesitamos son el GPIO los cuales solo pueden ser visualizados a través de una imagen que los explique (imagen adjunta). Una vez entendida esta particularidad del NodeMCU podemos realizar las conexiones.

A continuación se mostrara las conexiones que nosotros utilizamos para el Sketch:

  • MOSI = GPIO13 = D7
  • MISO = GPIO12 = D6
  • SCK = GPIO14 = D5
  • RFID_1 : RST = GPIO4 = D2 ; SDA = GPIO0 = D3
  • RFID_2 : RST = GPIO16 = D0 ; SDA = GPIO5 = D1
  • Servo_1 = GPIO2 = D4
  • Servo_2 = GPIO1 = D10/TX
  • Led_1 = GPIO15 =D8
  • Led_2 = GPIO3 =D9/RX

Si no sabes como configurar el NodeMCU para programar en el IDE de Arduino, mira este enlace, ya que sera necesario para el siguiente paso:

Configurar NodeMCU en el Arduino IDE

Step 4: Programación.

Ahora empezaremos con la programación.

Inicialmente debemos añadir las librerías que usaremos para el proyecto:

#include <SPI.h>
#include "MFRC522.h"
#include <ESP8266WiFi.h>
#include <Servo.h>

Ahora definiremos los RFID, inicializamos y definimos los pines de los led's y los servomotores:

#define RST_PIN  4
#define SS_PIN  0
#define RST_PIN2  16
#define SS_PIN2  5
MFRC522 RFID(SS_PIN, RST_PIN);
MFRC522 RFID2(SS_PIN2, RST_PIN2);
Servo myservo;
Servo myservo2;
int led1 = 15;
int led2 =  3;

Como es necesaria la conexión a internet, debemos definir el ssid y el pass al que nos queremos conectar:

const char* ssid = "YourSSID";
const char* pass = "YourPass";
WiFiClient client; // Crea el cliente

A continuación realizaremos el setup(), en el cual debemos configurar los servomotores, los led's, los RFID y realizar la conexión WiFi:

Serial.begin(115200);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
myservo.attach(2); // Index --- D4
myservo2.attach(1); // Index --- D10/TX
myservo.write(0);
myservo2.write(0);
SPI.begin();
RFID.PCD_Init();
RFID2.PCD_Init();
Serial.println("connecting to:");
Serial.println(ssid);
WiFi.begin(ssid, pass);
int retries = 0;
while ((WiFi.status() != WL_CONNECTED) && (retries < 10)) 
{
retries++;
delay(500);
Serial.print(".");
}
Serial.println("");
if (WiFi.status() == WL_CONNECTED) {
Serial.println("WiFi connected");
}
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println("Escaneo de tarjetas UID");   

Antes de empezar con el loop() es necesario crear unos métodos que nos ayudaran a hacer la lectura del RFID y a enviar las ID's a un servidor.

Empezaremos con el método "leerRFID" al cual desde el loop() se le enviara el objeto MFRC522 y retorna el ID como String:

String leerRFID(MFRC522 rfid)
{
  String ID0;
  String ID1;
  String ID2;
  String ID3;
  String ID;  // Enviamos serialemente su UID
  for (byte i = 0; i < rfid.uid.size; i++) {
    ActualUID[i] = rfid.uid.uidByte[i];
    if (i == 0) {
      ID0 = String(ActualUID[i]);
    }
    if (i == 1) {
      ID1 = String(ActualUID[i]);
    }
    if (i == 2) {
      ID2 = String(ActualUID[i]);
    }
    if (i == 3) {
      ID3 = String(ActualUID[i]);
    }
  }
  ID = ID0 + " " + ID1 + " " + ID2 + " " + ID3;
  return ID;
  // Terminamos la lectura de la tarjeta tarjeta  actual
  RFID.PICC_HaltA();
  RFID2.PICC_HaltA();
}

Ahora crearemos el método "postearDato" el cual recibir el ID de la bandeja y el numero de la bandeja que en ese momento esta utilizándose. Este método retorna la respuesta del servidor para saber si el dato fue posteado de manera correcta o no. En este método es necesario tener el host y el url del servidor al cual se enviara el dato. Este dato tiene la forma de un JSON.

String postearDato(String IDe, String bandeja) {
 const char* host = "HostDelServidor";
  String url = "/URL";
  const int httpsPort = 80;
 Serial.print("conectando a: ");
  Serial.println(host);
 if (!client.connect("https://host", httpsPort)) {
    Serial.println("connection failed");
    return "no se conecto";
  }
 String JSON = "{\"juego\":\"Bandeja" + bandeja + "\",\"identificador_usuario\":\"" + IDe + "\",\"fecha\":\"2017-05-18T16:36:14.197Z\"}";
  Serial.println(JSON);
client.print(String("POST ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Content-Type: application/json\r\n" +
               "Content-Length: " + JSON.length() + "\r\n\r\n" +
               JSON);
 String line = client.readStringUntil('\n');
  return line;
}

Una vez creados estos métodos, ahora si podemos hacer el método loop(). En este debemos realizar la lectura de los RFID y se llamar a los métodos que establecimos para hacer la lectura del las etiquetas y para enviar el dato al servidor. Como esto es un sistema que no va a permitir que un usuario pueda sacar mas de una bandeja, con ayuda de un contador se puede almacenar el ID del que saque la bandeja y este no podrá sacar otra mas hasta que devuelva la que tiene. Como en este caso estamos probando con dos RFID, lo que se realiza en la lectura de uno, se realiza en la del otro. Finalmente también agregamos el estado de los led's para hacer la señalización y el movimiento de los servos para desbloquear y bloquear las bandejas.

String IDe = "";
String IDe2 = "";
int cont1 = 0;
int cont2 = 0;
String PID = "ID";
String IDe_almacenado;
String IDe_almacenado2;

void loop() {
 // LECTURA RFID 1 !
  if (RFID.PICC_IsNewCardPresent())
  {
    //Seleccionamos una tarjeta
    if (RFID.PICC_ReadCardSerial())
    {
      Serial.println("Se Leyó RFID_1");
      //servo cerrado todo el tiempo  !!
      IDe = leerRFID(RFID); 
    if (IDe.equals(IDe_almacenado2)) {
        //servo se mantiene cerrado
        Serial.println("Se mantiene el servo cerrado... RFID_1");
      }
      
      else {
        cont1++;
        if (cont1 == 1) {
          Serial.println("SE ALMACENO RFID_1 !");
          myservo.write(180);
          IDe_almacenado = IDe;
          
          //si la bandeja se detecta abrir servo
          //si ya no se detecta cerrar servo
         String Bandeja1 = "1";
          String respuesta = postearDato(IDe_almacenado, Bandeja1);
          Serial.println(respuesta);
         delay(3000);
          digitalWrite(led1, HIGH);
          myservo.write(0);
        }
        if (IDe.equals(IDe_almacenado) && cont1 > 1) {
          //el servo se abre obligatoriamente
          //si detectal la bandeja, cerrar servo
          myservo.write(180);
          delay(3000);
          myservo.write(0);
          digitalWrite(led1, LOW);
          IDe_almacenado = "";
          cont1 = 0;
          Serial.println("SE REINICIO RFID_1 ");
        }
      }

    }
  }//Fin RFID_1

  // LECTURA RFID 2 !
  if ( RFID2.PICC_IsNewCardPresent())
  {
    //Seleccionamos una tarjeta
    if ( RFID2.PICC_ReadCardSerial())
    {
      Serial.println("Se Leyó RFID_2");
      IDe2 = leerRFID(RFID2);</p><p>      if (IDe2.equals(IDe_almacenado)) {
        //servo se mantiene cerrado
        Serial.println("Se mantiene el servo cerrado... RFID_2");
      }
      
      else
      {
        cont2++;
        if (cont2 == 1) {
          Serial.println("SE ALMACENO RFID 2 ");
           myservo2.write(180);
          IDe_almacenado2 = IDe2;
          String Bandeja2 = "2";
          String respuesta = postearDato(IDe_almacenado2, Bandeja2);
          Serial.println(respuesta);
          delay(3000);
          digitalWrite(led2, HIGH);
           myservo2.write(0);
        }
        if (IDe2.equals(IDe_almacenado2) && cont2 > 1) {
            myservo2.write(180);
          delay(3000);
             myservo2.write(0);
          IDe_almacenado2 = "";
          cont2 = 0;
          digitalWrite(led2, LOW);
          Serial.println("SE REINICIO RFID 2 ");
        }

      }
   }
  }//Fin RFID 2
  Serial.println("Identificacion_RFID_1:" +  IDe_almacenado);
  Serial.println("Identificacion_RFID_2:" +  IDe_almacenado2);
delay(1000);
}