Caja fuerte automatizada – TJ

El equipo

Iñaki Murillo del Prado – Ingeniería Informática
Sergio Torres Rivero – Ingeniería Informática
Raúl Villalba Amor – Ingeniería Informática

Idea

En el grupo 9 de Móstoles hemos realizado una caja fuerte. Nuestra intención es adaptar una caja fuerte convencional de una sola clave a una de mayor flexibilidad, con varios usuarios y sus claves pertinentes, de forma que varios miembros de la unidad familiar puedan tener acceso al mismo contenido pero sin tener que filtrar sus claves. Este proyecto podría servir de primer escalón para otro de mayor ambición en el que se busque la implementación de un sistema de cajas fuertes, donde cada usuario tenga acceso tanto a una celda individual como a una común.

Caja fuerte TJ

Planteamiento

Tras concebir la idea general nos dividimos en dos grupos de trabajo para organizar el trabajo de la manera más eficaz posible. Los grupos consisten en hardware (Iñaki) y software (Sergio, Raúl), destinamos dos personas debido a su mayor complejidad. Sin embargo, todos los integrantes han participado de forma activa en todas las fases. Como método de trabajo hemos utilizado la técnica de «Prueba y error», probando y añadiendo nuevas funcionalidades. Entre los principales objetivos encontramos:

  • Reconocimiento Keypad
  • Monitorizar información a través de LCD
  • Mostrar estado a través de Leds
  • Comprobar contraseña
  • Usuarios
  • Cambiar contraseña
  • Bloquear caja con servo

Recursos

Inicialmente disponíamos de ciertos recursos que la universidad nos había proporcionado, dichos elementos se representan con un coste de 0€ en la siguiente tabla:

ArtículoUnidadesPrecio (€)
LCD 16X215,99
1Adaptador para LCD IIC/I2C11,80
Keypad15,77
Leds (verde y rojo)20
Cables500
Servomotor10
Arduino10
Resistencia (10KΩ)10
Pila 9V11,5
Caja de cartón10
TOTAL15,06

Código de TJ

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 16, 2);
#include <Wire.h>
#include <i2cdetect.h>
#include <Keypad.h>

#include <Servo.h>
Servo miServo;

const int ledRojo = 13;
const int ledVerde = 12; 
  
char seleccionarOpcion;
char seleccionarOpcionA;
char seleccionarOpcionB;
char seleccionarOpcionC;
const String masterPass = "11235";
char claveInsertada;
String claveCompleta;
String contrInicial;
const byte FILAS = 4;
const byte COLUMNAS = 4;
byte pinFilas[FILAS] = {11, 10, 9, 8};
byte pinColum[COLUMNAS] = {7, 6, 5, 4};
char teclado [FILAS] [COLUMNAS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

Keypad miTeclado = Keypad(makeKeymap(teclado), pinFilas, pinColum, FILAS, COLUMNAS );
  
 void setup(){
    Serial.begin(9600);
    miServo.attach(3);
    pinMode(ledRojo,OUTPUT);
    pinMode(ledVerde,OUTPUT);
    digitalWrite(ledRojo, HIGH);
    digitalWrite(ledVerde, LOW); 
    claveCompleta.reserve(32);
    miServo.write(90);
    lcd.init();
    lcd.backlight();
    lcd.setCursor(0, 0);
    lcd.print("Grupo 9-Mostoles");
    delay(3000);
    lcd.clear();   
 }
 
  void loop(){
    static String nuevaContrasennaA= "11235";
    static String nuevaContrasennaB= "11235";
    static String nuevaContrasennaC= "11235";
    if (digitalRead(ledRojo)){
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Caja cerrada");
        lcd.setCursor(0, 1);
        lcd.print("Pulse A,B,C o #");
        delay(3000);
        seleccionarOpcion = miTeclado.getKey();
        while(!seleccionarOpcion){
          seleccionarOpcion = miTeclado.getKey();
        }
        switch(seleccionarOpcion){
          case 'A':
              comprobarContrasenna(nuevaContrasennaA);
              lcd.clear();
              lcd.setCursor(0, 0);
              lcd.print("1: Cambiar clave");
              lcd.setCursor(0, 1);
              lcd.print("2: Salir");
              delay(3000);
              seleccionarOpcionA = miTeclado.getKey();    
              while(!seleccionarOpcionA){
                seleccionarOpcionA = miTeclado.getKey();
              }
              switch(seleccionarOpcionA){
                case '1':
                    lcd.clear();
                    lcd.setCursor(0, 0);
                    lcd.print("Nuevo clave: ");
                    delay(3000);
                    nuevaContrasennaA= "";
                    claveInsertada = miTeclado.getKey();
                    while((claveInsertada != '#') && (claveInsertada != '*')){
                        claveInsertada = miTeclado.getKey();
                        if ((claveInsertada) && (claveInsertada != '#') && (claveInsertada != '*')){
                            nuevaContrasennaA += claveInsertada;
                            lcd.setCursor(0, 1);
                            lcd.print(nuevaContrasennaA);
                        }
                    }
                    lcd.clear();
                    lcd.setCursor(0, 0);
                    lcd.print("Nueva clave: ");
                    lcd.setCursor(0, 1);
                    lcd.print(nuevaContrasennaA);
                    delay(3000);
                break;
                default:
                    lcd.clear();
                    lcd.setCursor(0, 0);
                    lcd.print("Cerrando caja");
                    miServo.write(90);
                    delay(3000);
                    digitalWrite(ledVerde, LOW);
                    digitalWrite(ledRojo, HIGH);
                break;
              }
          break;
          case 'B':
              comprobarContrasenna(nuevaContrasennaB);
              lcd.clear();
              lcd.setCursor(0, 0);
              lcd.print("1: Cambiar clave");
              lcd.setCursor(0, 1);
              lcd.print("2: Salir");
              delay(3000);
              seleccionarOpcionB = miTeclado.getKey();    
              while(!seleccionarOpcionB){
                seleccionarOpcionB = miTeclado.getKey();
              }
              switch(seleccionarOpcionB){
                case '1':
                    lcd.clear();
                    lcd.setCursor(0, 0);
                    lcd.print("Nuevo clave: ");
                    delay(3000);
                    nuevaContrasennaB= "";
                    claveInsertada = miTeclado.getKey();
                    while((claveInsertada != '#') && (claveInsertada != '*')){
                        claveInsertada = miTeclado.getKey();
                        if ((claveInsertada) && (claveInsertada != '#') && (claveInsertada != '*')){
                            nuevaContrasennaB += claveInsertada; 
                            lcd.setCursor(0, 1);
                            lcd.print(nuevaContrasennaB);
                        }
                    }
                    lcd.clear();
                    lcd.setCursor(0, 0);
                    lcd.print("Nueva clave: ");
                    lcd.setCursor(0, 1);
                    lcd.print(nuevaContrasennaB);
                    delay(3000);
                break;
                default:
                    lcd.clear();
                    lcd.setCursor(0, 0);
                    lcd.print("Cerrando caja");
                    miServo.write(90);
                    delay(3000);
                    digitalWrite(ledVerde, LOW);
                    digitalWrite(ledRojo, HIGH);
                break;
              }
          break;
          case 'C':
              comprobarContrasenna(nuevaContrasennaC);
              lcd.clear();
              lcd.setCursor(0, 0);
              lcd.print("1: Cambiar clave");
              lcd.setCursor(0, 1);
              lcd.print("2: Salir");
              delay(3000);
              seleccionarOpcionC = miTeclado.getKey();    
              while(!seleccionarOpcionC){
                seleccionarOpcionC = miTeclado.getKey();
              }
              switch(seleccionarOpcionC){
                case '1':
                    lcd.clear();
                    lcd.setCursor(0, 0);
                    lcd.print("Nuevo clave: ");
                    delay(3000);
                    nuevaContrasennaC= "";
                    claveInsertada = miTeclado.getKey();
                    while((claveInsertada != '#') && (claveInsertada != '*')){
                        claveInsertada = miTeclado.getKey();
                        if ((claveInsertada) && (claveInsertada != '#') && (claveInsertada != '*')){
                            nuevaContrasennaC += claveInsertada; 
                            lcd.setCursor(0, 1);
                            lcd.print(nuevaContrasennaC);
                        }
                    }
                    lcd.clear();
                    lcd.setCursor(0, 0);
                    lcd.print("Nueva clave: ");
                    lcd.setCursor(0, 1);
                    lcd.print(nuevaContrasennaC);
                    delay(3000);
                break;
                default:
                    lcd.clear();
                    lcd.setCursor(0, 0);
                    lcd.print("Cerrando caja");
                    miServo.write(90);
                    delay(3000);
                    digitalWrite(ledVerde, LOW);
                    digitalWrite(ledRojo, HIGH);
                break;
              }
          break;
          case '#':
            comprobarContrasenna(masterPass);
          break;
          default:
              lcd.clear();
              lcd.setCursor(0, 0);
              lcd.print("Usuario no valido");
          break;
        }     
    }   
    else{
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Caja abierta");
        lcd.setCursor(0, 1);
        lcd.print("Cierre y pulse D");
        claveInsertada = miTeclado.getKey();
        while(!claveInsertada){
            claveInsertada = miTeclado.getKey();
        }
        if (claveInsertada == 'D'){
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("Cerrando caja");
            miServo.write(90);
            delay(3000);
            digitalWrite(ledVerde, LOW);
            digitalWrite(ledRojo, HIGH);
        } 
    }
}

void comprobarContrasenna(String posibleContrasenna){
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Introduzca clave");
    delay(3000);
    claveCompleta = "";
    claveInsertada = miTeclado.getKey();
    while((claveInsertada != '#') && (claveInsertada != '*')){
        claveInsertada = miTeclado.getKey();
        if ((claveInsertada) && (claveInsertada != '#')){
            claveCompleta += claveInsertada; 
            lcd.setCursor(0, 1);
            lcd.print(claveCompleta);
        }
    }  
    if((claveCompleta == masterPass)||(claveCompleta == posibleContrasenna)){
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Clave correcta");
        digitalWrite(ledRojo, LOW);
        digitalWrite(ledVerde, HIGH);
        miServo.write(0);
        }
    else{
        if (claveInsertada != '*'){
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("Clave incorrecta");
        }
        comprobarContrasenna(posibleContrasenna);
    }
}

Hardware

Para la elaboración del hardware de nuestra caja fuerte, primero realizamos las pruebas de los diferentes casos de uso en una protoboard separada, incluyendo todos los elementos. Esto no solo acelera el montaje en fases tempranas del desarrollo, sino que también nos ayuda a recuperarnos de posibles errores o fallos en la configuración del circuito o en los pines la placa de Arduino.
Una vez configurados los pines de nuestros diferentes elementos en la placa Arduino, pasamos a conectarlos en nuestras protoboard. En la superior colocamos el lcd, el adaptador de pines que nos permitió adaptar el número de pines necesarios de 16 a 4, uno de nuestros principales problemas durante el proyecto, pegamos nuestro keypad y colocamos nuestros dos leds, rojo y verde, además de los cables necesarios para la comunicación entre los elementos de ambas placas. En la inferior conectamos el resto de los elementos del circuito, configuramos los cables anteriormente mencionados, aquellos que van a corriente y a tierra y además colocamos una resistencia para regular el voltaje que les llega a ambos leds, ya que de ser excesivo podrían fundirse.
Todo esto lo colocamos en nuestra caja de cartón (ya que nos era mucho más cómodo para colocar el lcd y poner engancharlo correctamente), marcada y con los cortes correspondientes para pasar los cables. Colocamos el servo en la ranura en el borde de la caja que hacía de “cerradura” según el ángulo programado y una vez colocados el resto de los elementos conectamos todos estos a los pines correspondientes del Arduino, los que teníamos asignados en el programa. Solo nos quedaba por conectar el adaptador de corriente con la pila al Arduino.

Parte Exterior
Parte Interna

Software

Para el desarrollo de la caja fuerte nos centramos en los diferentes casos de uso que queríamos que ofreciera nuestro producto. Antes de permitirle al usuario seleccionar alguna opción, una vez encendida la caja fuerte, debemos comprobar si la puerta está abierta o cerrada.
Si bien es cierto que partimos de la premisa que la puerta está cerrada, y así es como lo inicializamos en el “set up( )”, esta funcionalidad destaca en la ejecución repetida del “loop( )”, donde siempre se debe comprobar el estado de la puerta antes de llegar al resto de funcionalidades. Esta comprobación se lleva a cabo mediante un “if ( ) … else” del estado del led rojo. Si está en “HIGH”, significa que la caja está cerrada, el otro estado seria en “LOW” e implicaría que la caja está abierta. Posteriormente, y en caso de que la caja esté cerrada, se le pide al usuario que seleccione con qué clave quiere abrir la caja, usuarios A, B, C o con la clave maestra (“#”).
Cabe mencionar que todos los usuarios pueden entrar con su clave personalizada, en caso de tenerla o con la clave maestra. Para la comprobación de dicha clave utilizamos un subprograma recursivo. En este subprograma guardamos la clave introducida por teclado en una variable y una vez que el usuario ha terminado de introducir la clave, pulsa el equivalente a la tecla enter (“D”) o la tecla de reintroducir clave (“”), mediante un “if ( ) … else” comprobamos si la clave introducida por el usuario coincide con la clave asignada a su usuario (se lo pasamos como parámetro al subprograma) o la clave maestra.
En caso de ser así, abrimos la caja y salimos del subprograma, sino pasamos al “else” y comprobamos si el último elemento introducido fue “”, en dicho caso simplemente llamamos recursivamente al subprograma, de no ser así, antes de realizar dicha llamada avisamos al usuario que la clave introducida es incorrecta. Una vez la clave introducida es correcta el usuario puede salir y pasar a cerrar la caja, o introducir una nueva clave, esto es posible debido a que hemos declarado las variables locales como “static”, por lo que dicho cambio se verá reflejado. Para ello al igual que antes, simplemente se pide al usuario que introduzca la nueva clave, mostrándose la misma por pantalla, hasta que pulse “#” o “*” y reescribamos la contraseña del usuario por la introducida.
Para finalizar, debemos hablar sobre el caso en el que la caja este abierta, en este caso se pide al usuario que pulse “D” y luego se procede a girar el servo y actualizar el estado de los leds. Cabe mencionar que la forma de interacción con el usuario es mediante un “keypad” básico y una pantalla lcd en la que siempre se muestra el estado de la operación que está realizando el usuario y el feedback correspondiente una vez finalizada.

Video explicativo

https://drive.google.com/file/d/1oaemYjgh-goYGRlf5SoeW__tfqvOb2_Z/view?usp=sharing

Idea

También te podría gustar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *