SmartBin – Papelera inteligente

Introducción

Este proyecto final de la asignatura de Sistemas Empotrados y de Tiempo Real, consiste en crear una estructura de reciclaje inteligente que permita a las personas reciclar de una forma rápida y sencilla. Esta estructura se compone de dos cubículos independientes, uno de ellos servirá para almacenar el plástico y el otro el cartón. Se van a utilizar dos formas que permitan a la persona abrir el cubículo correspondiente, una mediante la detección de aproximación y la otra mediante el reconocimiento de voz de dos palabras: “plástico” y “cartón”.

Para el primer método, se ha utilizado dos sensores ultrasonido colocados en cada papelera que detectarán si la distancia del objeto es menor a 10 centímetros y para la segunda forma, se ha usado un módulo de reconocimiento de voz que reconocerá los dos comandos entrenados previamente. Estos dos métodos, harán que actúe el mecanismo de apertura de cada papelera, donde tiene incorporado un servomotor, de manera que abrirá la tapa de la papelera correspondiente durante un periodo de 3 segundos. La pantalla LCD incorporada, mostrará los estados de las tapaderas correspondientes.

Herramientas

Herramientas utilizadas en el proceso de montaje (en el momento de realizar este proyecto, usar las herramientas que veáis necesarias en vuestro caso).

HerramientasUnidades
Pistola de silicona1
Taladro1
Alicates2
Cinta americana1
Cúter1
Soldador de estaño1

Materiales

Materiales usados para el proyecto, los componentes que no se indican en la tabla son aquellos que ya teníamos y no se han comprado.

MaterialUnidadesCoste
Placa Arduino UNO1
Escuadra2
Alambre2
Sensor ultrasonido HR-SR0429.99€
Reconocedor de voz V3 con micrófono130.99€
LCD + I2C16.99€
Tabla de corcho2
Servomotor2
Papelera212€

Total: 59.97€

Diseño inicial

La idea que teníamos en un principio era construir la estructura con dos papeleras situadas en los laterales de forma que se colocaban mirando a lados opuestos. Nuestra intención, era posicionar tanto el LCD como el módulo de reconocimiento de voz entre ambas papeleras, y próximas a la persona para que se pueda interactuar con mayor facilidad. Cada papelera tendrá un sensor ultrasónico en su parte frontal y a una altura elevada para comodidad de la persona. Por otro lado, se pensó en poner una estructura que tapará el mecanismo, de esta forma, pensamos en usar tabla de corcho, por su facilidad de corte y adhesividad.

Hardware

El hardware del proyecto se compone:

  • Placa Arduino UNO.
  • Dos servomotores para abrir las tapas de las papeleras, con 3 cables cada uno. Dos cables de alimentación (VCC y GND) y uno de señal, la cual, irá conectado al pin digital 7 en un servomotor y al pin digital 8 en el otro.
  • Dos sensores ultrasónicos para que las papeleras detecten un objeto/persona por proximidad. Cada sensor ultrasónico tiene 4 cables, 2 son para la alimentación (VCC y GND), y los otros dos, el Echo, para la entrada de datos, y Trigger, para la salida de datos.
  • Módulo de reconocimiento de voz además de los dos puertos de alimentación (VCC y GND), tiene el puerto TXD conectado con el pin digital 2 y RXD conectado con el pin digital 3 de la placa, que servirán para la comunicación serie bidireccional.
  • Pantalla LCD, la cual, dispone de un módulo adaptador de LCD a I2C para poder reducir el cableado de nuestra pantalla a 4 cables. Dos cables para la alimentación (VCC y GND), y los otros dos cables, para la transferencia de datos entre el dispositivo y la placa Arduino (cable SDA) conectada al pin analógico de entrada 4, y para sincronizar el sistema mediante los pulsos de reloj (cable SCL) conectada al pin analógico de entrada 5.

La toma VCC irá conectada al puerto de 5V de la placa Arduino (para la alimentación) y la toma GND irá conectada al puerto GND (tierra). La protoboard hará uso de estas conexiones para conectarlo con las tomas de los distintos módulos.

Software

/**
 * Proyecto: Papelera inteligente que se abre por aproximación y reconocimiento de voz
 * Autores: Jose Luis Sierra Benito y Marcos Ruiz Muñoz
*/

//------------------------ Librerías -------------------------//

#include <Servo.h> // Incluímos la librería para poder controlar el servo
#include <SoftwareSerial.h> //Para permitir la comunicación serie en otros pines digitales, a parte de los pines 0 y 1
#include "VoiceRecognitionV3.h" // Esta librería nos permite utilizar el módulo de reconocimiento de voz
#include <LiquidCrystal_I2C.h> // Para usar el LCD conectado al dispositivo I2C
#include <Wire.h> // Nos permite la comunicación con el dispositivo I2C

//------------------------------------------------------------//

//----------------------- Constantes -------------------------//

#define CARDBOARD 0 // Asignamos un valor númerico a la papelera de cartón
#define PLASTIC 1 // Asignamos un valor numérico a la papelera de plástico
#define LIMIT 10 // Distancia desde la cual se reconoce por proximidad (cm)
#define SECOND 1000 // 1 segundo para utilizarlo en la cuenta atrás del lcd
#define TIMEOPEN 3000 // Tiempo que mantenemos la tapa abierta (3 segundos)

//------------------------------------------------------------//

//------------------------ Servomotor ------------------------//

// Declaramos las variables para controlar los 2 servos
Servo servoMotor1; // Servo de la papelera de cartón
Servo servoMotor2; // Servo de la papelera de plástico

//------------------------------------------------------------//

//------------------ Reconocimiento de Voz -------------------//

/**
  Conexión
  Arduino    Módulo de reconocimiento de voz
   2   ------->     TX (Transmisión)
   3   ------->     RX (Recepción)
*/
VR myVR(2, 3); // Creamos el objeto para el reconocimiento de voz

uint8_t buf[64]; // Buffer para el módulo de reconocimiento de voz

//------------------------------------------------------------//

//-------------------------- LCD -----------------------------//

LiquidCrystal_I2C lcd(0x27, 16, 2); // Creamos objeto que representa el LCD: dirección 0x27 y 16 columnas x 2 filas

//------------------------------------------------------------//

//------------------- Sensor ultrasónico ---------------------//

const int echoPin1 = 4; // Echo del sensor de cartón en pin digital 4
const int triggerPin1 = 5; // Trigger del sensor de cartón en pin digital 5

const int echoPin2 = 11; // Echo del sensor de plástico en pin digital 11
const int triggerPin2 = 12; // Trigger del sensor de plástico en pin digital 12

//------------------------------------------------------------//

//-- Variables para la apertura y cerrado de las papeleras ---//

unsigned long initMillisCardboardOpen = 0; // Momento en el que se abre la tapa de la papelera de cartón
unsigned long currentMillisCardboardOpen = 0; // Para comprobar si ha pasado el tiempo para cerrar la tapa de la papelera de cartón
unsigned long lcdMillisCardboardOpen = 0; // Instante para comprobar cuando podemos reducir la cuenta atrás en la papelera de cartón

unsigned long initMillisPlasticOpen = 0; // Momento en el que se abre la tapa de la papelera de plástico
unsigned long currentMillisPlasticOpen = 0; // Para comprobar si ha pasado el tiempo para cerrar la tapa de la papelera de plástico
unsigned long lcdMillisPlasticOpen = 0; // Instante para comprobar cuando podemos reducir la cuenta atrás en la papelera de plástico

boolean isCardboardOpen = false; // Variable booleana para saber si la tapa de cartón está abierta
boolean isPlasticOpen = false; // Variable booleana para saber si la tapa de plástico está abierta

int countdownCardboard = 0; // Cuenta atrás de la tapa abierta de la papelera del cartón
int countdownPlastic = 0; // Cuenta atrás de la tapa abierta de la papelera del plástico

//------------------------------------------------------------//

void setup() {

  // Inicializamos el reconocimiento de voz
  myVR.begin(9600);

  // Abrimos el puerto serie
  Serial.begin(115200);

  // Cargamos los comandos que tenemos grabados
  myVR.load((uint8_t)CARDBOARD);
  myVR.load((uint8_t)PLASTIC);

  // Iniciamos el servo correspondiente a la papelera del cartón con el pin 7
  servoMotor1.attach(7);
  // Iniciamos el servo correspondiente a la papelera del plástico con el pin 8
  servoMotor2.attach(8);

  // Comprobamos que las dos papeleras están cerradas en el momento inicial
  closeLid(servoMotor1);
  closeLid(servoMotor2);

  pinMode(triggerPin1, OUTPUT); // TriggerPin1 se configura como salida
  pinMode(echoPin1, INPUT); // EchoPin1 se configura como entrada

  pinMode(triggerPin2, OUTPUT); // TriggerPin2 se configura como salida
  pinMode(echoPin2, INPUT); // EchoPin2 se configura como entrada

  // Se inicializa el LCD (y el I2C)
  lcd.init();

  // Se enciende la luz de fondo del LCD
  lcd.backlight();

  // Escribimos en el LCD
  lcd.print("Carton:cerrado");
  lcd.setCursor(0, 1); // Ubicamos el cursor del LCD en la primera posición (columna:0) de la segunda línea (fila:1)
  lcd.print("Plastico:cerrado");

}

void loop() {

  // Comprobar si tenemos que cerrar la tapa de la papelera de cartón
  checkCloseCardboard();

  // Comprobar si tenemos que cerrar la tapa de la papelera de plástico
  checkClosePlastic();

  // Reconocer por proximidad si tenemos que abrir alguna de las papeleras
  openByProximity();

  // Reconocer por voz si tenemos que abrir alguna de las papeleras
  openByVoice();

}

int calculateDistance(int TriggerPin, int EchoPin) {
  long duration, distanceCm;

  digitalWrite(TriggerPin, LOW);  // Se genera un pulso corto de 5µs + 10µs
  delayMicroseconds(5);
  digitalWrite(TriggerPin, HIGH); // El HC-SR04 entra en modo de ecolocalización enviando señales a 40kHz
  delayMicroseconds(10);          // Se espera 10µs para recibir la señal rebotada
  digitalWrite(TriggerPin, LOW);

  duration = pulseIn(EchoPin, HIGH);  // Se obtiene la duración del rebote de la señal del dispositivo en µs

  /*
     Fórmula de referencia:

     Velocidad del sonido = 343m/s
     343m/s * 100cm/m * 1/1000000s/µs = 1/29.1cm/µs

     Distancia = Tiempo * Velocidad / 2;

     Distancia(cm) = Tiempo(µs)/29.1*2 = (Tiempo(µs) / 2) / 29.1;
  */
  distanceCm = (duration / 2) / 29.1;   // Convertimos a distancia en cm
  return distanceCm;
}

void openByProximity() {
  /*
    Obtenemos la distancia a la que se encuentra la persona o el objeto del sensor ultrasónico.
    Si se encuentra a una distancia menor de 10 cm entonces abriremos la papelera correspondiente.
  */
  int cm1 = calculateDistance(triggerPin1, echoPin1);
  if (cm1 < LIMIT) {
    /** Abrir papelera de cartón */
    openCardboard();
  }

  int cm2 = calculateDistance(triggerPin2, echoPin2);
  if (cm2 < LIMIT) {
    /** Abrir papelera de plástico */
    openPlastic();
  }
}

void openByVoice() {
  /*
    Mediante voz, si la persona dice "cartón" o "plástico",
    abrirá la papelera asociada a ese comando.
  */
  int ret;
  // Si no reconoce ninguna palabra "recognize" devuelve -1, en caso contrario será superior a 0
  ret = myVR.recognize(buf, 50);
  if (ret > 0) {
    // El número asociado al comando se obtiene en "buf" en la posición 1
    switch (buf[1]) {
      case CARDBOARD:
        /** Abrir papelera de cartón */
        openCardboard();
        break;
      case PLASTIC:
        /** Abrir papelera de plástico */
        openPlastic();
        break;
      default:
        Serial.println("Comando no encontrado");
        break;
    }
  }
}

void openCardboard() {
  /*
    Abrimos la papelera de cartón.
    - En caso de que no esté la tapa levantada, declaramos en el código que la tapa
      esté como abierta, llamamos a la función que abre la tapa,
      e iniciamos el tiempo que la tapa estará abierta, junto a la cuenta atrás del LCD.
    - En caso de que la tapa ya estuviera abierta antes, resetearemos el tiempo de la apertura
      de la papelera para que se establezca otra vez en los 3 segundos,
      de igual manera, resetemos la cuenta atrás del LCD.
  */
  if (!isCardboardOpen) {
    isCardboardOpen = true; // Tapa abierta
    openLid(servoMotor1); // Llamamos a la función que abrirá la tapa correspondiente
  }
  initMillisCardboardOpen = millis(); // Momento inicial en el que se abre la papelera de cartón
  lcdMillisCardboardOpen = initMillisCardboardOpen; // Para usarlo en la cuenta atrás y actualizar el LCD cada segundo que pase
  countdownCardboard = 3; // Inicializamos la cuenta atrás
  printCountdown(0, 0, "Carton:", countdownCardboard); // Llamamos a la función que actualizará el LCD
  delay(150); // Tiempo de seguridad
}

void openPlastic() {
  /*
    Abrimos la papelera de plástico.
    - En caso de que no esté la tapa levantada, declaramos en el código que la tapa
      esté como abierta, llamamos a la función que abre la tapa,
      e iniciamos el tiempo que la tapa estará abierta, junto a la cuenta atrás del lcd.
    - En caso de que la tapa ya estuviera abierta antes, resetearemos el tiempo de la apertura
      de la papelera para que se establezca otra vez en los 3 segundos,
      de igual manera, resetemos la cuenta atrás del lcd.
  */
  if (!isPlasticOpen) {
    isPlasticOpen = true; // Tapa abierta
    openLid(servoMotor2); // Llamamos a la función que abrirá la tapa correspondiente
  }
  initMillisPlasticOpen = millis(); // Momento inicial en el que se abre la papelera de cartón
  lcdMillisPlasticOpen = initMillisPlasticOpen; // Para usarlo en la cuenta atrás y actualizar el LCD cada segundo que pase
  countdownPlastic = 3; // Inicializamos la cuenta atrás
  printCountdown(0, 1, "Plastico:", countdownPlastic); // Llamamos a la función que actualizará el LCD
  delay(150); // Tiempo de seguridad
}

void checkCloseCardboard() {
  /*
    En caso de que la papelera de cartón esté abierta:
    - Comprobamos si ya ha pasado el tiempo para cerrar la tapa de la papelera de cartón,
      en ese caso, lo pondremos en el código como cerrado, cerramos la tapa
      y ponemos en el LCD que la papelera de cartón está cerrada.
    - Cada vez que pase un segundo (si la tapa está abierta),
      vamos a reducir un segundo la cuenta atrás en el LCD.
  */
  if (isCardboardOpen) {
    currentMillisCardboardOpen = millis(); // Para saber si podemos cerrar la papelera y reducir la cuenta atrás
    // Comprobar si ha pasado el tiempo para cerrar la tapa de la papelera
    if ((currentMillisCardboardOpen - initMillisCardboardOpen) >= TIMEOPEN) {
      isCardboardOpen = false; // Tapa cerrada
      closeLid(servoMotor1); // Llamamos a la función que cerrará la tapa correspondiente
      printCountdown(0, 0, "Carton:", -1); // Llamamos a la función que actualizará el LCD
      delay(150); // Tiempo de seguridad
      // Comprobar si podemos reducir 1 segundo la cuenta atrás
    } else if ((currentMillisCardboardOpen - lcdMillisCardboardOpen) >= SECOND) {
      lcdMillisCardboardOpen = millis(); // Junto a "currentMillisCardboardOpen" para saber cuando pasará otro segundo
      countdownCardboard--; // Reducimos la cuenta atrás en un segundo
      printCountdown(0, 0, "Carton:", countdownCardboard); // Llamamos a la función que actualizará el LCD
    }
  }
}

void checkClosePlastic() {
  /*
    En caso de que la papelera de plástico esté abierta:
    - Comprobamos si ya ha pasado el tiempo para cerrar la tapa de la papelera de plástico,
      en ese caso, lo pondremos en el código como cerrado, cerramos la tapa
      y ponemos en el LCD que la papelera de plástico está cerrada.
    - Cada vez que pase un segundo (si la tapa está abierta),
      vamos a reducir un segundo la cuenta atrás en el LCD.
  */
  if (isPlasticOpen) {
    currentMillisPlasticOpen = millis(); // Para saber si podemos cerrar la papelera y reducir la cuenta atrás
    // Comprobar si ha pasado el tiempo para cerrar la tapa de la papelera
    if ((currentMillisPlasticOpen - initMillisPlasticOpen) >= TIMEOPEN) {
      isPlasticOpen = false; // Tapa cerrada
      closeLid(servoMotor2); // Llamamos a la función que cerrará la tapa correspondiente
      printCountdown(0, 1, "Plastico:", -1); // Llamamos a la función que actualizará el LCD
      delay(150); // Tiempo de seguridad
      // Comprobar si podemos reducir 1 segundo la cuenta atrás
    } else if ((currentMillisPlasticOpen - lcdMillisPlasticOpen) >= SECOND) {
      lcdMillisPlasticOpen = millis(); // Junto a "currentMillisPlasticOpen" para saber cuando pasará otro segundo
      countdownPlastic--; // Reducimos la cuenta atrás en un segundo
      printCountdown(0, 1, "Plastico:", countdownPlastic); // Llamamos a la función que actualizará el LCD
    }
  }
}

void printCountdown(int col, int row, String typeText, int countdown) {
  /*
    Escribimos en el LCD cada vez que tengamos que actualizar alguna información.
    - En caso de que "countdown" sea menor a 0, en el LCD ponemos que la papelera
      correspondiente está cerrada.
    - En caso de que "countdown" sea mayor a 0, [1,3] ponemos ese valor como la cuenta atrás
      en el LCD.
  */
  lcd.setCursor(col, row);
  lcd.print("                ");
  lcd.setCursor(col, row);
  String lcdText = "";
  if (countdown < 0) {
    lcdText = typeText + "cerrado";
  } else {
    lcdText = typeText + " " + countdown + " sg";
  }
  lcd.print(lcdText);
}

void closeLid(Servo servoMotor) {
  // Desplazamos el servo a la posición 0º
  servoMotor.write(0);
}

void openLid(Servo servoMotor) {
  // Desplazamos el servo a la posición 180º
  servoMotor.write(180);
}

Posibles mejoras

  • Añadir una interfaz configurable, mediante el LCD y unos botones/keypad, de tal forma, que el usuario pueda configurar aspectos del proyecto como, por ejemplo, el tiempo que tarda en cerrarse la tapa, añadir/borrar/modificar nuevas instrucciones de voz o modificar la distancia a la que se abren las papeleras.
  • Un micrófono que reconozca los comandos que se dictan a una mayor distancia.
  • Que los brazos de los servomotores fueran más largos para haber tenido una mayor amplitud en el momento de abrir la papelera.
  • Añadir movilidad poniendo ruedas a la estructura que forma las 2 papeleras, para que existiera la posibilidad de que la persona pueda lanzar la basura, y ésta, pueda seguir el objeto al lugar donde va a caer.

Video explicativo

En este vídeo, se muestra la explicación del funcionamiento con distintos casos de uso, y la explicación del hardware y del software. En caso de querer realizar este proyecto, el proceso de montaje se puede hacer de muchas formas, por lo que se deja libertad a la persona de hacerlo como prefiera.

Autores

  • Marcos Ruiz Muñoz
  • Jose Luis Sierra Benito

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 *