Caja Fuerte SEM – Sistema de doble Seguridad

Caja Fuerte SEM con seguridad de clave numérica y reconocimiento de huella dactilar

Integrantes del grupo:

  • Martín Alami Mochi
  • Sergio Alvarez Scharfhausen
  • Eduard Vasile Stancu.

1       Introducción

La idea principal del proyecto es diseñar una caja de seguridad con doble sistema de seguridad: uno mediante la introducción de una clave numérica de cuatro dígitos por teclado y otro mediante la lectura de huella digital. Si ambos son correctos, se activa primero el motor, que haría girar un doble fondo, y posteriormente se abriría la cerradura de la caja.

Después de darle varias vueltas, nos gustó bastante está idea de montar un sistema para una caja de seguridad, con doble sistema de seguridad pero al final sin el doble fondo, cosa que siempre podremos hacerla en un futuro. En este proyecto, los sensores se encargan de recoger información que activa la apertura de la caja cuando se cumplen ciertas condiciones.

El proyecto, además, permite el cambio de código o de huella y muestra por pantalla el resultado de las operaciones y validaciones que realiza el sistema para autorizar la apertura.

Circuito fuera de la caja

2       Funcionamiento

A continuación, vamos a describir las funcionalidades que hemos incorporado en nuestro sistema de seguridad.

Al arrancar, el sistema nos pide elegir una opción entre las siguientes:

  • A: Abrir la caja
  • B: Borrar usuario
  • C: Cambiar contraseña o huella registrada

En cualquier otro caso, el sistema vuelve a pedir una opción válida entre las anteriores.

Al inicio, como no hay ningún usuario registrado, elijas la opción que elijas, el sistema pedirá crear un usuario.

2.1      Funcionalidad Crear usuario

Para crear un usuario, el sistema solicita introducir una clave por el teclado. Como cualquier sistema de validación habitual, se pedirá repetir la clave para confirmarla.

Si coinciden las dos claves introducidas, el sistema pide registrar una huella a través del lector.

Como en el caso anterior, pide introducir una segunda vez la huella para validarla y, como en el caso de otros sistemas de lectura de huella (móviles o tablets), tener varias “copias” de la huella y así hacer una mejor validación de la huella cuando se vaya a usar en futuras utilizaciones de la caja.

Con esto, ya estaría el usuario creado y registrado y, por lo tanto, se podrían realizar las otras operaciones y funciones de la caja.

2.2      Funcionalidad Cambiar clave o huella

Al seleccionar la opción de menú para cambiar la contraseña o la huella de un usuario ya creado, lo primero que hace el sistema es preguntar cuál de las dos cosas quieres modificar.

En el caso de elegir “cambiar contraseña”, te pedirá la contraseña antigua y luego, como se hizo al crear usuario, pedirá introducir dos veces la nueva contraseña para validarla.

De la misma forma, al elegir “cambiar huella”, el sistema pide primer introducir la huella antigua y, a continuación, registrar dos veces la nueva huella para su validación.

Durante este proceso, el sistema va mostrando por pantalla los mensajes con los pasos a seguir, la confirmación de la finalización correcta del proceso o los mensajes de error que pudieran producirse.

2.3      Función: Abrir caja

Esta función te pide por pantalla introducir por teclado la contraseña y, a continuación, la huella que se han registrado al crear o modificar el usuario, permitiendo tres intentos para cada una de ellas.

Si pasados tres intentos, no se ha introducido el dato correcto, el sistema vuelve al menú principal.

Si las dos cosas son correctas, la cerradura y la caja se abren.

2.4      Función Borrar usuario

Al seleccionar esta opción, el sistema pide confirmación por pantalla de que se va a proceder a la eliminación del usuario. En caso de respuesta afirmativa, primero se pedirán la clave y la huella, y si estas son correctas, se procede a eliminar los registros de contraseña y clave. En caso de respuesta negativa, el sistema vuelve al menú de inicio. Esta función está pensada para ser utilizada en el caso de que la caja pueda ser utilizada temporalmente por diferentes usuarios, de forma similar a las cajas de seguridad que suele haber en las habitaciones de los hoteles, por ejemplo.

2.5     Vídeo explicativo del funcionamiento

3       Materiales

Para llevar a cabo el proyecto, hemos utilizado los siguientes componentes y materiales:

MATERIALES DE CLASE
COMPONENTEUNIDADESPRECIO 
Resistencia 1KΩ1  
Resistencia 10 KΩ1  
Pantalla LCD1  
Cableado de cobre  
MATERIALES ADICIONALES
COMPONENTEUNIDADESPRECIO 
Arduino Mega 2560115,99€ 
Sensor de Huella119,99€ 
Cerradura eléctrica110,69€ 
Teclado14,00€ 
Relé15,50€ 
Protoplaca1  
Pilas 4,5 V3  
Transistor NPN1  
Tablas de Madera 40×408  
Pomo de la puerta1  
IMPORTE TOTAL57,37€ 

4       Sistema

4.1      Esquema del sistema

Se muestra a continuación el esquema diseñado para el sistema de seguridad:

4.2      Desarrollo y montaje del sistema

El sistema que hemos montado consta de cuatro partes diferenciadas. Para poder conectar todos los componentes hemos utilizado una placa de Arduino Mega 2560 que nos proporcionaba el suficiente número de pines para todos los elementos a incluir.

4.1.1       Teclado

Va conectado a 8 pines de la placa de Arduino, concretamente a los pines: 53, 51, 49, 47, 45, 43, 41, 39. Los cuatro primeros pines se utilizan para las filas y los cuatro siguientes para las columnas.

4.1.2       Pantalla LCD

Para montar la pantalla LCD, nos hemos basado en el circuito que aparece por defecto en Tikercad. Para conectarlo, hemos utilizado los pines 32, 30, 28, 26, 24 y 22.

4.1.3       Sensor de huella

Para el sensor de huella, hemos usado 4 pines:

  • 1 va a tierra (o GND)
  • 1 va a 5 V.
  • 2 van a los pines digitales 10 (RX) y 11 (TX).

Sabemos que los pines 10 y 11 son los que podemos utilizar porque son los dos primeros pines que soportan los datos de la huella para la placa de Arduino que hemos utilizado, esto viene especificado en la librería de software serial dentro de la propia página de Arduino. Si se hubiera utilizado otra placa de Arduino diferente, los pines también serían distintos.

4.1.4       Relé y cerradura

En este caso, utilizamos el pin digital 6 que pondremos a valor alto/bajo según la operación a realizar. Este pin lo conectamos a la base de un transistor al cual le llegan por el colector 12 V. El emisor va conectado al relé que va conectado al cable positivo de la cerradura y de tal forma que, cuando el pin 6 está a valor alto, el transistor está en saturación y, como consecuencia, el relé se activa y saca la suficiente potencia como para abrir la cerradura. En caso de que el pin 6 esté a valor bajo, al transistor no le llega corriente, lo que indica que está en corte y al relé no le llega corriente y, por lo tanto, la cerradura se mantiene cerrada.

5       Problemas y soluciones

5.1      Sensor de huella con salida incompatible

Compramos un primer sensor de huella y no nos fijamos en que las salidas no se podían conectar a la placa de Arduino. Tuvimos que devolverla y comprar una nueva.

5.2      Pines insuficientes en la placa Arduino 1

Nuestro sistema costa de varios componentes que utilizan 8+6+2+1=17 pines, por lo que la placa inicial de Arduino 1 no tenía suficientes pines para conectarlo todo. Teníamos dos opciones:

  • Comprar un multiplexor
  • Comprar la placa Arduino Mega 2560 que nos proporciona pines suficientes.

Hemos optado por comprar la placa de Arduino Mega 2560 porque nos ahorraba tiempo ya que el multiplexor había que soldarlo y configurarlo a través de código.

5.3      Corriente de la cerradura

Hacerle llegar el voltaje suficiente a la cerradura ha sido uno de los mayores problemas que nos hemos encontrado.

En un primer momento, intentamos varias soluciones:

  • Aumentar el voltaje con un único transistor: esta solución no funcionó porque, el transistor te hacía de cuello de botella y no te permitía alcanzar el voltaje necesario.
  • Hacer una puerta AND con dos transistores: esta solución tampoco nos funcionó porque nos encontrábamos con la misma situación del punto anterior.
  • Comprar una puerta AND: esta solución tampoco funcionó porque la puerta AND no funcionaba a los valores necesitados.
  • Utilizar únicamente un relé: esta solución no nos sirvió porque el relé necesita su propio voltaje para activarse y desactivarse, por lo que utilizando únicamente el pin de Arduino no llegábamos al voltaje para activar el relé.
  • Utilizar un relé añadiéndole una pila de 4,5 V: el problema que nos encontramos en este caso es que, aunque llegábamos al voltaje esperado para activar el relé y abrir la cerradura, al desactivar el pin del Arduino, pese a no llegar a los 5 V. necesarios para activar el relé, se ve que usar los 4,5 V. de la pila sí lo mantiene activado.

La solución definitiva fue añadir un transistor al relé para que, en caso de que el transistor estuviese en corte, al relé no le llegase nada de corriente y, en caso de que pase a saturación (como en nuestro caso), sí se active el relé.

5.4      Alto consumo de energía

Nos dimos cuenta al realizar sucesivas pruebas que las pilas se gastan con mucha rapidez y hemos tenido que añadir una tercera pila para asegurarnos de que siempre llegue el voltaje necesario.

5.5      Pantalla LCD

Al montar el circuito fuera de la caja, la pantalla funcionaba perfectamente, pero al realizar al montaje dentro de la caja, creemos que algún cable o alguna conexión se pierde y la pantalla deja de funcionar en muchas ocasiones.

No hemos tenido tiempo de revisar esta parte con detalle para corregir este defecto que nos impide el correcto funcionamiento del resto del sistema.

La pantalla nos sirve sobre todo para mostrar mensajes de lo que va haciendo el sistema y para compensar esto hemos decidido utilizar el monitor serie.

6       Código Arduino

//=======================================================
//     Librerías y variables globales del programa
//=======================================================
#include <LiquidCrystal.h>
#include <Keypad.h>
#include <Adafruit_Fingerprint.h>    // Libreria  para el Sensor de huella dactilar

SoftwareSerial mySerial(10, 11);     // Crear Serial para Sensor  Rx, TX del Arduino
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);


//=============================
//     Configuración LCD
//=============================
LiquidCrystal lcd(32, 30, 28, 26, 24, 22);


//===========================================
//     Configuración teclado matricial
//===========================================
const byte rows = 4;
const byte cols = 4;
int pantalla = 1;
char keys[rows][cols] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[rows] = {53, 51, 49, 47};//pines asignados, en el arduino están los impares seguidamente
byte colPins[cols] = {45, 43, 41, 39};

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, rows, cols );

//==============================
//     Variables globales
//==============================

char claveAux[12] = {'#', 5, 1, 5, 2, 5, 3, 5, 4, 5, 5, '#'};
char clave1[4];
char clave2[4];
char introducido[4];
int cont = 0;
int intentos = 3;
int huella = 0;
uint8_t huellaUsuario;


bool existeUsuario = false;
char claveUsuario[4];


//===================================
//=     Prototipos de funciones     =
//===================================

void borrarUsuario();
void fin(int error);//vuelve al inicio, y , si hay un error de teclado ,(1), lo muestra
bool chequeo(int abrir, int cont , int intentos);
void nuevaClave(int ambas);//valdrá 1 si tras hacer esto entrará en nuevaHuella()
void cambiarClave();
bool chequeoHuella(int intentos);
void nuevaHuella();
void cambiarHuella();

//===============================================
//=     Inicio de programa, configuraciones     =
//===============================================
void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2); //Cantidad de filas y columnas que en el LCD
  pinMode(6, OUTPUT);

  finger.begin(57600);  // inicializa comunicacion con sensor a 57600 Baudios
  if (!finger.verifyPassword()) {
    Serial.println("No hay comunicacion con el sensor de huella");
    Serial.println("Revise las conexiones");
    while (1) delay(1);
  }

}

//==========================================
//=     Funcionalidad de la aplicación     =
//==========================================
void loop() {
  /*MENÚ:
    A: Abrir Caja
    B: Borrar/Crear Usuario
    C: Cambiar Clave/Huella
  */
  lcd.clear();
  for (int i = 0; i < 3; i++) {
    lcd.setCursor(i, 0);
    lcd.print(">");
    lcd.setCursor(15 - i, 0);
    lcd.print("<");
    delay(600);
  }
  lcd.setCursor(4, 0);
  lcd.print("CAJA SEM");
  delay(1300);
  lcd.setCursor(0, 1);
  lcd.print("elija una opcion");
  char digito = keypad.waitForKey();
  lcd.setCursor(0, 1);
  lcd.print("    op -> ");  lcd.print(digito);  lcd.print("     ");
  
  delay(1400);
  switch (digito) {
    case 'A':
      if (existeUsuario) {
        if (chequeo(0, 0, 3) && chequeoHuella(3))   abrirCaja();
      }
      else  nuevaClave(1);
      break;
    case 'B':
      if (existeUsuario) borrarUsuario();
      else  nuevaClave(1);
      break;
    case 'C':
      if (!existeUsuario) fin(0);
      else {
        lcd.clear();
        lcd.setCursor(3, 0);
        lcd.print("CAMBIO DE:");
        lcd.setCursor(0, 1);
        lcd.print("Clave:1 Huella:0");
        digito = keypad.waitForKey();
        if (digito == '1') {
          lcd.setCursor(0, 1);
          lcd.print("      1          ");
          cambiarClave();
        }
        else if (digito == '0') {
          lcd.setCursor(0, 1);
          lcd.print("      0          ");
          delay(1000);
          cambiarHuella();
        }
        else fin(1);
      }
      break;
    case 'D':

      fin(0);
      break;
    default:
      fin(1);
  }

}
//------------------------------------------------------------
void abrirCaja() {
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Abriendo caja");
  digitalWrite(6, HIGH);
  delay(9000);
  digitalWrite(6, LOW);
  delay(3000);
  fin(0);
}
//------------------------------------------------------------
void cambiarClave() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("CAMBIO DE CLAVE");
  delay(2000);
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Ponga primero ");
  delay(1300);
  lcd.setCursor(0, 1);
  lcd.print("la clave antigua");
  delay(2000);
  if (chequeo(0, 0, 3))nuevaClave(0);
}
//------------------------------------------------------------
void cambiarHuella() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("CAMBIO DE HUELLA");
  delay(2000);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Ponga primero la");
  delay(1300);
  lcd.setCursor(0, 1);
  lcd.print("antigua huella");
  delay(2000);
  if (chequeoHuella(3)) nuevaHuella();
}
//---------------------------------------------------------
void borrarUsuario() {
  if (existeUsuario) {
    lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print("Borrar Usuario");
    lcd.setCursor(1, 1);
    lcd.print("SI->1  NO->0");
    char opcion = keypad.waitForKey();
    if (opcion == '1') {
      lcd.setCursor(0, 1);
      lcd.print("      1       \n\n");
      delay(1000);
      if (chequeo(0, 0, 3) && chequeoHuella(3)) {
        existeUsuario = false;
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("USUARIO BORRADO");
        fin(0);
      }
      else fin(1);
    }
    else if (opcion == '0') {
      lcd.setCursor(0, 1);
      lcd.print("      0       \n\n");
      fin(0);
    }
    else fin(1);
  }
  else  nuevaClave(0);
}
//----------------------------------------------------------------
bool chequeo(int abrir, int cont , int intentos) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("==== CODIGO ====");
  lcd.setCursor(1, 1);
  for (cont = 0; cont < 4; cont++) {
    introducido[cont] = keypad.waitForKey();
    lcd.print("  *");
  }
  if (cont == 4) {
    abrir = 1;
    delay(500);
    for (int i = 0; i < 4; i++) {
      if (introducido[i] != claveUsuario[i]) {
        abrir = 0;
        cont = 0;
        intentos--;
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("CODIGO ERRONEO");
        delay(1000);
        lcd.setCursor(0, 1);
        lcd.print("intentos-> ");   lcd.print(intentos);
        delay(1300);
        if (intentos > 0) chequeo(abrir, cont, intentos);
        else fin(1);
      }
    }
    if (abrir == 1) {
      delay(600);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("CODIGO CORRECTO");
      delay(1000);
      return true;
    }
  }
  else chequeo(abrir, cont, intentos);
}
//-------------------------------------------------------------
bool chequeoHuella(int intentos) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("==== HUELLA ====");
  while (!getFingerprintEnroll());
  if (finger.fingerFastSearch() != FINGERPRINT_OK) {
    intentos--;
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("HUELLA ERRONEA");
    delay(1000);
    lcd.setCursor(0, 1);
    lcd.print("intentos-> ");   lcd.print(intentos);
    delay(1300);
    if (intentos > 0) chequeoHuella(intentos);
    else fin(1);
  }
  else {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("HUELLA CORRECTA");
    delay(1000);
    return true;
  }
}
//--------------------------------------------------------------
void nuevaClave(int ambas) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("NUEVO USUARIO:");
  delay(1000);
  lcd.setCursor(0, 1);
  lcd.print("PONGA UN CODIGO");
  delay(2000);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("==== CODIGO ====");
  lcd.setCursor(1, 1);
  for (int i = 0; i < 4; i++) {
    clave1[i] = keypad.waitForKey();
    lcd.print("  *");
  }
  delay(1000);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("REPITA EL CODIGO");
  delay(1500);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("==== CODIGO ====");
  lcd.setCursor(1, 1);
  for (int i = 0; i < 4; i++) {
    clave2[i] = keypad.waitForKey();
    lcd.println("  *");
  }
  delay(1000);
  for (int i = 0; i < 4; i++) {
    if (clave1[i] != clave2[i]) {
      lcd.clear();
      lcd.setCursor(4, 0);
      lcd.print("CODIGOS ");
      lcd.setCursor(0, 1);
      lcd.print("NO COINCIDENTES ");
      delay(2000);
      nuevaClave(0);
    }
  }
  for (int i = 0; i < 4; i++) {
    claveUsuario[i] = clave2[i];
  }
  existeUsuario = true;
  lcd.clear();
  lcd.setCursor(5, 0);
  lcd.print("CLAVE");
  lcd.setCursor(2, 1);
  lcd.print("ESTABLECIDA");
  delay(2000);
  if (ambas == 0) fin(0);
  else {
    nuevaHuella();
  }
}
//--------------------------------------------------------------
void nuevaHuella() {
  getFingerprintEnroll();
  guardarHuella();
  delay(500);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("NUEVA HUELLA OK");
  fin(0);
}
//--------------------------------------------------------------
void fin(int error) {
  delay(100);
  lcd.clear();
  if (error == 1) {
    lcd.setCursor(3, 0);
    lcd.print("ERROR!!!");
    delay(1000);
  }
  loop();
}
//---------------------------------------------------------------
void guardarHuella() {

  huellaUsuario = finger.storeModel(1);

  if (huellaUsuario != FINGERPRINT_OK){ lcd.setCursor(3, 0);
    lcd.print("ERROR!!!");}
  delay(3000);
}
//------------------------------------------------------------------

uint8_t getFingerprintEnroll() {

  int p = -1;
  int id = 1;
  lcd.setCursor(0, 0);
  lcd.print("Pon la huella");
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        //Serial.println("Image taken");
        break;
      case FINGERPRINT_NOFINGER:
        //Serial.println(".");
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        Serial.println("Communication error");
        break;
      case FINGERPRINT_IMAGEFAIL:
        Serial.println("Imaging error");
        break;
      default:
        Serial.println("Unknown error");
        break;
    }
  }

  // OK success!

  p = finger.image2Tz(1);
  switch (p) {
    case FINGERPRINT_OK:
      //Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.printfln("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }
  p = 0;
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  p = -1;
  lcd.clear();

  lcd.println("Otra vez");
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        //Serial.println("Image taken");
        break;
      case FINGERPRINT_NOFINGER:
        Serial.print(".");
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        Serial.println("Communication error");
        break;
      case FINGERPRINT_IMAGEFAIL:
        Serial.println("Imaging error");
        break;
      default:
        Serial.println("Unknown error");
        break;
    }
  }

  // OK success!

  p = finger.image2Tz(2);
  switch (p) {
    case FINGERPRINT_OK:
      //Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  p = finger.createModel();
  if (p == FINGERPRINT_OK) {
    //Serial.println("Prints matched!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_ENROLLMISMATCH) {
    Serial.println("Fingerprints did not match");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;

  }

  return true;
}

7      Conclusiones y comentarios

7.1      Resumen del proyecto y posibles mejoras

Al realizar el proyecto hemos conseguido cumplir los objetivos iniciales de introducir la huella y el teclado, pero debido a la falta de tiempo hemos tenido que prescindir del doble fondo.

Posibles mejoras:

  • Incorporar el sistema de doble fondo.
  • Que un mismo usuario pueda guardar más de una huella.
  • Un modo administrador (a la hora de hacer el código lo empezamos a implementar, pero no se llegó a completar).

7.2      Tabla de tiempos

Circuito30 horas
Montaje37 horas
Código23 horas
Total90 horas

8  Bibliografía

https://www.arduino.cc/en/Tutorial/LibraryExamples/SoftwareSerialExample

https://adafruit.github.io/Adafruit-Fingerprint-Sensor-Library/html/class_adafruit___fingerprint.html#a79d36eb63d36c60ab43198ac47120f76

https://www.tinkercad.com

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 *