#include <Servo.h> // Incluímos la librería para poder controlar el servo
#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
//------------------------------------------------------------//
//-------------------------- 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
//------------------------------------------------------------//
//-----NOVEDAD: Sensores Infrarrojos---//
//-----Primero necesitamos definir los pines donde se conectarán estos sensores y luego agregar la lógica para leer su estado.//
//-----Si una papelera está llena, el sensor (IR) correspondiente devolverá un valor que indicará que la papelera está llena.//
//-----En ese caso, no se abrirá la tapa de la papelera, incluso si se detecta proximidad-----//
const int irSensorCardboard = A0; // Sensor IR para la papelera de cartón
const int irSensorPlastic = A1; // Sensor IR para la papelera de plástico
//------------------------------------------------------------//
//-- 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() {
// Abrimos el puerto serie
Serial.begin(115200);
// 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
pinMode(irSensorCardboard, INPUT); // Sensor IR de cartón como entrada
pinMode(irSensorPlastic, INPUT); // Sensor IR de plástico 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();
}
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
distanceCm = (duration / 2) / 29.1; // Convertimos a distancia en cm
return distanceCm;
}
void openByProximity() {
int cm1 = calculateDistance(triggerPin1, echoPin1);
if (cm1 < LIMIT && !isCardboardFull()) {
openCardboard();
}
int cm2 = calculateDistance(triggerPin2, echoPin2);
if (cm2 < LIMIT && !isPlasticFull()) {
openPlastic();
}
}
bool isCardboardFull() {
int irValue = analogRead(irSensorCardboard);
return irValue > 500; // Ajusta este valor según la sensibilidad del sensor IR
}
bool isPlasticFull() {
int irValue = analogRead(irSensorPlastic);
return irValue > 500; // Ajusta este valor según la sensibilidad del sensor IR
}
void openCardboard() {
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() {
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() {
if (isCardboardOpen) {
currentMillisCardboardOpen = millis();
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
} else if ((currentMillisCardboardOpen - lcdMillisCardboardOpen) >= SECOND) {
lcdMillisCardboardOpen = millis();
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() {
if (isPlasticOpen) {
currentMillisPlasticOpen = millis();
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
} else if ((currentMillisPlasticOpen - lcdMillisPlasticOpen) >= SECOND) {
lcdMillisPlasticOpen = millis();
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) {
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) {
servoMotor.write(0); // Desplazamos el servo a la posición 0º
}
void openLid(Servo servoMotor) {
servoMotor.write(180); // Desplazamos el servo a la posición 180º
}