HOTEL AUTÓNOMO

Alberto Carrón Campón

Ignacio Bautista Llorente

Marta García Abad

INTRODUCCIÓN

El proyecto se basa en un sistema de gestión para un hotel autónomo, en el cual los usuarios pueden entrar y salir cuando quieran, sin necesidad de una persona física que lo gestione. Este proyecto está inspirado en los hoteles cápsula que hay en Japón, cuyo funcionamiento es controlado por máquinas.

La idea final es que simplemente con diferentes tipos de sensores (de distancia, de huella dactilar, etc.) y pantallas, se pueda simular los diferentes servicios que puede ofrecerte un hotel al uso sin necesidad de tener personal físico en el propio hotel.

MATERIALES

Placa Arduino UNOIncluido en Starter Pack
Placa ProtoboardIncluido en Starter Pack
Sensor ultrasónico de distancia HC-SR04Incluido en Starter Pack
Servomotor de 180º4,79€
Resistencia de 220Ω x 6Incluido en Starter Pack
Diodo led verde x 6Incluido en Starter Pack
Cables Macho – MachoIncluido en Starter Pack
Cables Macho – HembraIncluido en Starter Pack
Módulo Ky-022 Sensor Receptor Infrarrojo IR (con mando, pila no incluida)3,87€
Placas de madera (20x20cm) x 57,5€
Total16,14€
Tabla de componentes y precios

FUNCIONAMIENTO

La funcionalidad de este proyecto se basa en el reconocimiento, por parte del sensor de distancia, de cualquier objeto que altere la distancia entre dicho sensor y el suelo; cuando esta distancia se ve alterada, significa que hay alguien interesado en entrar al hotel. Si hay habitaciones vacías (hay algún led encendido), el sistema le asignará al cliente una habitación, desbloqueando la entrada y mostrando por pantalla el nº de la habitación asignada al cliente. En ese momento se recogerá automáticamente el tiempo de entrada del cliente (en esta primera versión no puede ser predefinido debido a algunos problemas que se mencionarán más adelante) y se apagará el led de la habitación asignada.

Para la salida de los huéspedes, habrá una pantalla interactiva en el hall del propio hotel donde el cliente, a través de su huella dactilar (en esta primera versión se ha implementado esta funcionalidad mediante el uso de un mando a distancia), se identificara y seleccionará su habitación para finalizar o ampliar, en casos de un tiempo de estancia predefinido, su estancia en el hotel; liberando de esta manera la habitación y dejándola accesible para otro cliente. Cuando un cliente decide finalizar su estancia recibe un comprobante sobre su tiempo total de estancia y el precio asociado a esta y cuando este importe ha sido abonado, la barrera de la entrada vuelve a desbloquearse y se muestra por pantalla un mensaje de despedida.

HARDWARE

SOFTWARE

En cuanto al software, a continuación se muestra el código que hemos implementado y para el que hemos necesitado las siguientes librerías:

  • Servo.h: librería necesaria para el funcionamiento del servomotor utilizado para automatizar la entrada al edificio.
  • HCSR04.h: librería necesaria para el funcionamiento del sensor ultrasónico de distancia utilizado para automatizar la entrada al edificio.
  • IRremote.h: librería necesaria para el funcionamiento del sensor receptor de infrarrojos utilizado par automatizar la salida de

CÓDIGO

/* Librerías correspondientes a las funcionalidades */
#include <Servo.h>
#include <HCSR04.h>
#include "IRremote.h"
#define RECEPTOR_IR 3


const int PIN_UDS = 12;
const int PIN_UDS_2 = 11;
const double DIST_UDS = 10.00;

const int PIN_SERVO = 10;
const int POSI_SERVO = 0;

const int  NUM_HAB = 6;

const int PIN_LED1 = 9;
const int PIN_LED2 = 2;
const int PIN_LED3 = 4;
const int PIN_LED4 = 6;
const int PIN_LED5 = 13;
const int PIN_LED6 = 8;

Servo servoE;        
UltraSonicDistanceSensor sensorE(PIN_UDS, PIN_UDS_2);  
float distanceE;

boolean habitacionesLibres[NUM_HAB] = { true, true, true, true, true, true };  //Array de habitaciones libres
int habitaciones;                                         //Contador de habitaciones para llevar la cuenta de cuantas hay libres
int habitacionE;                                         
int habitacionS;

int LED1 = PIN_LED1;  //LED 1 en pin 1
int LED2 = PIN_LED2;   //LED 2 en pin 2
int LED3 = PIN_LED3;  //LED 3 en pin 4
int LED4 = PIN_LED4;  //LED 4 en pin 7
int LED5 = PIN_LED5;  //LED 5 en pin 8
int LED6 = PIN_LED6;  //LED 6 en pin 9

//Variables usadas para regular los tiempos
unsigned long tEntrada1;
unsigned long tEntrada2;
unsigned long tEntrada3;
unsigned long tEntrada4;
unsigned long tEntrada5;
unsigned long tEntrada6;

unsigned long tSalida1;
unsigned long tSalida2;
unsigned long tSalida3;
unsigned long tSalida4;
unsigned long tSalida5;
unsigned long tSalida6;

unsigned long tTotal;



void setup() {
  Serial.begin(9600);
  Serial.print("Bienvenidos");
  IrReceiver.begin(RECEPTOR_IR);
  for (int i = 0; i <= 5; i++) {
    habitacionesLibres[i] = true;
  }
  habitaciones = NUM_HAB;            
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);  
  pinMode(LED4, OUTPUT);  
  pinMode(LED5, OUTPUT);  
  pinMode(LED6, OUTPUT);  
 
  servoE.attach(PIN_SERVO); //Servomotor en pin 10
  servoE.write(POSI_SERVO); //Posicion inicial
 
  encenderLeds();
}


void loop() {
  if (IrReceiver.decode()) {
    botonesMando();
    IrReceiver.resume();
  }
  distanceE = sensorE.measureDistanceCm();

  /* Funcionalidad de entradas */
  if (habitaciones > 0 && distanceE < DIST_UDS) {  //Si hay habitaciones disponibles y detecta a algun cliente
    habitaciones--;
    subirEntrada();

    if(habitacionesLibres[0] == true) { //Selecionamos la primera habitacion que no se encuentre ocupada
      digitalWrite(LED1, LOW);
      habitacionesLibres[0] = false;
      tEntrada1 = millis(); //Obtenemos el momento en el que se le asigna una habitacion a un cliente
      habitacionE = 1;
    }else if (habitacionesLibres[1] == true) {
      digitalWrite(LED2, LOW);
      habitacionesLibres[1] = false;
      tEntrada2 = millis();
      habitacionE = 2;
    }else if (habitacionesLibres[2] == true) {
      digitalWrite(LED3, LOW);
      habitacionesLibres[2] = false;
      tEntrada3 = millis();
      habitacionE = 3;
    } else if (habitacionesLibres[3] == true) {
      digitalWrite(LED4, LOW);
      habitacionesLibres[3] = false;
      tEntrada4 = millis();
      habitacionE = 4;
    } else if (habitacionesLibres[4] == true) {
      digitalWrite(LED5, LOW);
      habitacionesLibres[4] = false;
      tEntrada5 = millis();
      habitacionE = 5;
    } else if (habitacionesLibres[5] == true) {
      digitalWrite(LED6, LOW);
      habitacionesLibres[5] = false;
      tEntrada6 = millis();
      habitacionE = 6;
    }
    delay(3000);
    bajarEntrada();
  } // Fin comprobación habitaciones
  delay(2000);
}

/* Funcionalidades del mando */
void botonesMando() {
  auto myRawdata= (IrReceiver.decodedIRData.decodedRawData);

  /* Distintas funcionalidades según el botón que pulsemos */
  switch (bitreverse32Bit(myRawdata)) {  
    case 16769055:  //botón de bajar, baja la barrera de entrada
      bajarEntrada();
      break;

    case 16754775:  //botón de subir, subir la barrera de entrada
      subirEntrada();
      break;

    case 16748655:  //botón EQ, se reinicia el hotel
      encenderLeds();
      servoE.write(POSI_SERVO);
      habitaciones = 6;
      for (int i = 0; i <= 5; i++) {
        habitacionesLibres[i] = true;
      }
      Serial.print("Habitaciones libres: ");
      Serial.println(habitaciones);
      Serial.println("Bienvenido");
      break;

    case 16724175:  //Al pulsar el botón 1, decidimos que el cliente abandona la habitación 1
      if (habitacionesLibres[0] == false) { //Comprobación de que la habitación esté ocupada
        digitalWrite(LED1, HIGH);
        habitacionesLibres[0] = true;
        habitacionS = 1;
        Serial.print("Ha quedado libre la habitacion ");
        Serial.print(habitacionS);
        Serial.print("\n");
        tSalida1 = millis();  
        imprimirTiempoEstancia();
        checkoutxSerial(habitacionS);
      } else {
        Serial.print("La habitacion no esta ocupada\n");
      }
      break;

    case 16718055:  //Al pulsar el botón 2, decidimos que el cliente abandona la habitacion 2
      if (habitacionesLibres[1] == false) {
        digitalWrite(LED2, HIGH);
        habitacionesLibres[1] = true;
        habitacionS = 2;
        Serial.print("Ha quedado libre la habitacion ");
        Serial.print(habitacionS);
        Serial.print("\n");
        tSalida2 = millis();
        imprimirTiempoEstancia();
        checkoutxSerial(habitacionS);
      } else {
        Serial.print("La habitacion no esta ocupada\n");
      }
      break;

    case 16743045:  //Al pulsar el botón 3,  decidimos que el cliente abandona la habitación 3
      if (habitacionesLibres[2] == false) {
        digitalWrite(LED3, HIGH);
        habitacionesLibres[2] = true;
        habitacionS = 3;
        Serial.print("Ha quedado libre la habitacion ");
        Serial.print(habitacionS);
        Serial.print("\n");
        tSalida3 = millis();
        imprimirTiempoEstancia();
        checkoutxSerial(habitacionS);
      } else {
        Serial.print("La habitacion no esta ocupada\n");
      }
      break;

    case 16716015:  //Al pulsar el botón 4,  decidimos que el cliente abandona la habitacion 4
      if (habitacionesLibres[3] == false) {
        digitalWrite(LED4, HIGH);
        habitacionesLibres[3] = true;
        habitacionS = 4;
        Serial.print("Ha quedado libre la habitacion ");
        Serial.print(habitacionS);
        Serial.print("\n");
        tSalida4 = millis();
        imprimirTiempoEstancia();
        checkoutxSerial(habitacionS);
      } else {
        Serial.print("La habitacion no esta ocupada\n");
      }
      break;

    case 16726215:  //Al pulsar el botón 5,  decidimos que el cliente abandona la habitacion 5
      if (habitacionesLibres[4] == false) {
        digitalWrite(LED5, HIGH);
        habitacionesLibres[4] = true;
        habitacionS = 5;
        Serial.print("Ha quedado libre la plaza ");
        Serial.print(habitacionS);
        Serial.print("\n");
        tSalida5 = millis();
        imprimirTiempoEstancia();
        checkoutxSerial(habitacionS);
      } else {
        Serial.print("La habitacion no esta ocupada\n");
      }
      break;

    case 16734885:  //Al pulsar el botón 6, decidimos que el cliente abandona la habitacion 6
      if(habitacionesLibres[5]==false){
      digitalWrite(LED6, HIGH);
      habitacionesLibres[5] = true;
      habitacionS = 6;
      Serial.print("Ha quedado libre la plaza ");
      Serial.print(habitacionS);
      Serial.print("\n");
   tSalida6 = millis();
      imprimirTiempoEstancia();
      checkoutxSerial(habitacionS);
      } else {
        Serial.print("La plaza no esta ocupada\n");
      }
      break;    
  }
  delay(500);
}

/* Funciones para encender y apagar todos los leds */
void encenderLeds() {
  digitalWrite(LED1, HIGH);
  digitalWrite(LED2, HIGH);
  digitalWrite(LED3, HIGH);
  digitalWrite(LED4, HIGH);
  digitalWrite(LED5, HIGH);
  digitalWrite(LED6, HIGH);
}
void apagarLeds() {
  digitalWrite(LED1, LOW);
  digitalWrite(LED2, LOW);
  digitalWrite(LED3, LOW);
  digitalWrite(LED4, LOW);
  digitalWrite(LED5, LOW);
  digitalWrite(LED6, LOW);
}

/* Funciones para subir y bajar la entrada */
//Sube/Baja la entrada en ciclos de 10ms
void subirEntrada() {
  for (int pos = POSI_SERVO; pos <= 100; pos += 1) {
    servoE.write(pos);
    delay(10);
  }
}
void bajarEntrada() {
  for (int pos = 100; pos >= POSI_SERVO; pos -= 1) {
    servoE.write(pos);
    delay(10);
  }
}

/* Función de mostrar tiempo */
/* Calcula el tiempo total de estancia del inquilino
desde el momento que se le asigna una habitación hasta el
momento en el que la abandona */
void imprimirTiempoEstancia() {
  switch (habitacionS) {
    case 1:
      tTotal = tSalida1 - tEntrada1;
      break;
    case 2:
      tTotal = tSalida2 - tEntrada2;
      break;
    case 3:
      tTotal = tSalida3 - tEntrada3;
      break;
    case 4:
      tTotal = tSalida4 - tEntrada4;
      break;
    case 5:
      tTotal = tSalida5 - tEntrada5;
      break;
    case 6:
      tTotal = tSalida6 - tEntrada6;
      break;
  }
  Serial.print("La habitación ");
  Serial.print(habitacionS);
  Serial.print(" ha sido ocupada durante ");
  Serial.print(tTotal / 1000);
  Serial.println(" segundos.");
}

/* Función que genera un recibo mostrado por consola */
void checkoutxSerial(int habitacionS) {
  unsigned long precioSEG = tTotal * 0.5;
  Serial.println("===========================================");
  Serial.println("    CHECKOUT  ");
  Serial.print("Habitación a liberar: ");
  Serial.println(habitacionS);
  Serial.print("Tiempo de estancia del huésped: ");
  Serial.print(tTotal / 1000); 
  Serial.println(" segundos");
  Serial.print("TOTAL A PAGAR: ");
  Serial.println(precioSEG / 1000);
  Serial.println("===========================================");
}

PROBLEMAS Y SOLUCIONES

El primer y mayor problema que tuvimos al crear este proyecto fue el uso de una pantalla LCD que permitiera que el sistema interactuase con el cliente. En un primer momento, nuestra idea era la de poder diferenciar entre habitaciones con diferentes capacidades y que fuera el propio sistema quien se lo preguntara y pudiera seleccionar una u otra habitación.

El problema en sí ha consistido en que, al conectarla con un módulo I2C, no llegaba a imprimir los mensajes; dividimos en 16 columnas y 2 filas la pantalla y únicamente se distinguía sin problema la fila superior pero aún así no lográbamos que imprimiera mensajes. También tratamos de ajustar el contraste de la pantalla a través de la ranura que tiene integrado el módulo I2C pero no sirvió para nada. Hemos probado a conectar el módulo I2C a la placa Protoboard y sacarle conexiones hacia la pantalla LCD pero tampoco nos funcionó. Finalmente invertimos en tratar de solucionar este problema alrededor de 5 días y al no conseguir avance alguno decidimos no utilizar la pantalla LCD, ni el módulo que adquirimos para ella.

Como solución a este problema, decidimos utilizar la pantalla Serial del propio IDE de Arduino para mostrar información y comunicarnos con el cliente, pero este sería uno de los principales problemas a resolver de cara a una futura segunda versión. La pantalla LCD también era una parte importante para la salida de los clientes, donde éstos debían ingresar su numero de habitación después de que se lo pidiéramos a través de la pantalla; esto lo hemos solucionado implementado la funcionalidad de las salidas a través del mando, al pulsar el botón 1, la habitación 1 se libera.

A su vez, también tuvimos problemas con el sensor receptor de infrarrojos que venía en nuestro starter pack de Arduino; estuvimos probando un par de días con dicho sensor y descubrimos que podría estar defectuoso debido a que las señales que recibía no eran constantes. Tras esto, decidimos comprar nuestro propio sensor de infrarrojos y al conectarlo nos dimos cuenta de que estábamos en lo cierto, el primer sensor estaba defectuoso y no era por un problema ni de librerías, ni de código como pensamos en un primer momento. Al probar el sensor que compramos en casa, no obtuvimos ningún problema de señal, el funcionamiento era totalmente correcto, pero al comprobar su funcionamiento al día siguiente en la biblioteca, nos dimos cuenta de la cantidad de interferencias que había y, aunque continuaba funcionando bien, no era al 100% certero. Suponemos que el día de la exposición podremos experimentar alguna de estas interferencias dado que se llevará a cabo cerca de dicha biblioteca.

DEMOSTRACIÓN

CONCLUSIÓN

Tras no haber podido implementar la práctica en su totalidad como queríamos en un principio, no estamos del todo contentos con el resultado, pero a su vez estamos muy satisfechos con el resultado final teniendo en cuenta que es una primera versión. Somos conscientes que todo aquello que se nos ha ocurrido durante el proceso, podría llegar a implementarse en futuras versiones, mejorando el proyecto y dándole una verdadera autonomía al funcionamiento del hotel. También hemos mejorado nuestro manejo con los componentes estudiados en clase, comprendiendo mejor sus conexiones físicas y su funcionamiento a través de las librerías y la documentación de éstas. En cuanto al reparto de las tareas, no ha existido un reparto estricto para el montaje del proyecto; durante un par de semanas hemos estado trabajando en las salas reservadas para los trabajos en grupos de la biblioteca y algunos días en el aula durante las horas de clase, realizando todo el trabajo entre los 3, salvo la compra del material y la creación de la documentación necesaria para la entrega.

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 *