Coffeeto
Proyecto desarrollado por Sara Gallego Trigal para la asignatura de Diseño de Sistemas Empotrados.
1. Sobre el proyecto.
El objetivo inicial del proyecto era diseñar un robot asistente que mejorara la experiencia de preparar bebidas calientes, como café e infusiones, empleando únicamente parte de los componentes que contenía el kit Elegoo UNO R3 Super Starter; ni uno más, ni uno menos.
Así, el robot debía ser capaz de realizar tareas como servir agua caliente, medir la temperatura, remover los ingredientes, y controlar el tiempo de reposo mediante un temporizador, asegurando precisión y comodidad para el usuario.
De estas ideas surgió Coffeeto, un robot que no solo automatiza pasos clave, sino que también añade un toque de personalización con opciones de temperatura y alertas visuales.
Coffeeto se presenta como un simpático aliado en la cocina, con una estructura sencilla pero eficaz que promete una bebida perfecta en cada preparación.
2. Implementación.
Coffeeto se compone de diversos componentes electrónicos integrados en un diseño funcional:
- Placa Elegoo UNO R3: El cerebro del robot, donde se controla toda la lógica.
- Pantalla LCD: Sirve como interfaz para el usuario, mostrando mensajes y guías para este.
- Sensor de humedad y temperatura (DHT11): Mide la temperatura para alcanzar el valor deseado.
- Sensor ultrasónico (HC-SR04): Detecta la presencia y posición de la taza para garantizar su correcta colocación.
- Microservo (VarSpeedServo): Controla el movimiento del brazo que remueve la bebida.
- Motor DC (L293D): Remueve los ingredientes con precisión.
- Módulo receptor IR y mando: Permite navegar por los menús con un control remoto.
- LED amarillo: Sirve como indicador visual cuando la bebida está lista y para la correcta colocación de la taza.
Cada componente fue elegido con el objetivo de garantizar funcionalidad, facilidad de uso y un montaje sencillo.
3. Los pasos dados.
El desarrollo de Coffeeto se realizó en varias etapas cuidadosamente planificadas para garantizar un avance estructurado y eficiente (y que surgieran la menor cantidad de problemas posibles):
1. Planificación.
En esta fase inicial, se definieron los objetivos principales y las funciones clave que debía tener el robot: medir la temperatura, remover los ingredientes, controlar el tiempo de reposo y ofrecer alertas visuales y sonoras.
Además, se realizaron bocetos preliminares de lo que podría ser la estructura del robot. Se barajaron varias opciones, incluyendo un diseño compacto con un brazo articulado y una estructura modular que integrara todos los componentes. Finalmente, se optó por un diseño sencillo que cumpliera con las funcionalidades básicas, asegurando estabilidad y “facilidad” de montaje.
2. Diseño del circuito.
Una vez definidos los objetivos, se procedió al diseño del circuito con todos los componentes principales:
- Placa Elegoo UNO R3 como núcleo del robot.
- Sensores (ultrasónico y DHT11), encargados de detectar la posición de la taza y medir la temperatura.
- Actuadores, como el microservo y el motor DC para el movimiento del brazo y el dispositivo removedor.
- Pantalla LCD para la interacción con el usuario.
- Módulo receptor IR y control remoto para la navegación por los menús.
- Buzzer y LED, para proporcionar alertas visuales y sonoras durante el proceso de preparación de bebidas.
En el circuito, aparece un potenciómetro. Esto en realidad se utiliza para representar el sensor de temperatura y humedad DHT11, ya que en la plataforma de Tinkercad no existe este elemento.
Antes de montar el circuito, se probó cada componente de manera individual para verificar su correcto funcionamiento. Estas pruebas incluyeron:
- Detectar la distancia con el sensor ultrasónico.
- Comprobar el correcto funcionamiento de la pantalla LCD.
- Calcular la temperatura con el sensor DHT11 y asegurar su precisión.
- Verificar los movimientos del microservo y del motor DC.
- Confirmar la recepción de señales IR mediante el control remoto.
Y es aquí donde empezaron a surgir los primeros problemas, ya que muchos cables de la caja no funcionaban correctamente, y algunos de los componentes estaban estropeados, como el receptor de señales IR, que, sí que recibía señales, pero aleatorias, mostrando para un mismo botón códigos diferentes en cada pulsación.
Así, estas pruebas permitieron identificar y solucionar fallos en componentes específicos, como los cables defectuosos que fueron reemplazados por otros en buen estado, y el sensor IR, que se cambió por otro.
4. Montaje del circuito inicial.
Una vez asegurado que los componentes funcionaban correctamente, se procedió al montaje físico del circuito para poder realizar las pruebas pertinentes tras implementar el código con el comportamiento del robot.
5. Definición del comportamiento de Coffeeto (flujo).
Para comenzar con la etapa de programación e implementación del código, se realizó un documento en el que se describía exactamente el flujo de información y comportamiento de Coffeeto con el objetivo de simplificar el proceso.
6. Integración y programación del código.
Una vez asegurado que los componentes funcionaban correctamente y definido el flujo de comportamiento, se programaron las funciones del robot para trabajar de manera conjunta. Fue en esta etapa cuando surgieron conflictos con los temporizadores (timers), ya que tanto el sensor IR como el microservo y el buzzer intentaban utilizar el mismo recurso del microcontrolador, causando errores en su funcionamiento.
Tras intentar solucionarlo por todos los medios posibles (cambiando las librerías que empleaban los componentes implicados, cambiando los pines) y no obtener resultado, se optó por eliminar el buzzer y utilizar una biblioteca específica para el microservo que evitara estos conflictos (VarSpeedServo.h).
6.1. Rediseño del circuito.
Tras eliminar el buzzer, se realizó un rediseño del circuito quitando elementos que ya no eran necesarios, quedando de la siguiente forma
En el circuito, aparece un potenciómetro. Esto en realidad se utiliza para representar el sensor de temperatura y humedad DHT11, ya que en la plataforma de Tinkercad no existe este elemento.
7. Depuración del código.
Tras las modificaciones realizadas en el circuito, se ajustó este para optimizar su funcionamiento y se resolvieron problemas estructurales.
8. Montaje de Coffeeto.
En esta etapa, se pasó al montaje de la estructura y circuito finales de Coffeeto.
Primero, se realizó la estructura del robot. Para ello, se emplearon dos cajas (una para el cuerpo y otra que encajaba perfectamente en la estructura donde se situaría el circuito). Estas se pintaron a mano con pintura acrílica (🐮muuuchas muchas capas de pintura) y se les realizaron las perforaciones pertinentes en los lugares donde irían algunos de los componentes, como el agujerito para el LED amarillo, la pantalla LCD, el receptor IR o el brazo con el servo y el motor. Además, se diseñó una estructura rectangular para tapar donde iría el brazo removedor y dar una apariencia más limpia al robot.
Todo esto se pegó y decoró para darle el toque final al aspecto de Coffeeto, intentando aportarle una apariencia simpática y agradable.
Después, se desmontó el circuito completo que se había empleado para probar el código fuera de la estructura, y se comenzó a montarlo dentro de la estructura final del robot empleando cables más largos y adaptando la estructura a las necesidades de cada uno de los componentes.
9. Presentación final.
En la etapa final, una vez integrado todo en una misma estructura, Coffeeto fue sometido a pruebas completas, ejecutando tanto funciones manuales como automáticas. El robot demostró (tras unos cuantos ajustes y retoques) ser capaz de preparar café e infusiones, llevando a cabo las tareas para las que fue creado, como medir la temperatura, controlar el tiempo de reposo y remover los ingredientes de forma precisa.
El resultado fue un prototipo funcional que cumplió con casi todos los objetivos iniciales del proyecto, listo para ser presentado y utilizado.
4. Reparto de tareas.
En este proyecto, al ser realizado por una única persona todas las tareas fueron realizadas por mí, lo que implicó asumir múltiples roles a lo largo del desarrollo.
Desde el planteamiento inicial, pasando por el diseño y montaje, hasta las pruebas y la depuración, cada paso requirió una planificación cuidadosa y una ejecución meticulosa. En particular, el desarrollo del código fue un aspecto clave y un desafío, ya que debía coordinar el funcionamiento de diversos componentes electrónicos y superar problemas técnicos, como los conflictos de temporizadores entre el microservo, el buzzer y el sensor IR.
Desde mi punto de vista, aunque en algunos momentos la carga de trabajo puede haber resultado pesada al haber decidido realizar el proyecto sola, ha resultado en una experiencia enriquecedora y gratificante, ya que una vez se tiene el proyecto finalizado y funcionando correctamente, se siente una gran satisfacción al ver materializado todo el esfuerzo y dedicación invertidos.
5. Costes de materiales.
Como se ha comentado anteriormente, desde un principio se quería realizar un proyecto empleando únicamente componentes incluidos en el Kit Elegoo UNO R3 Super Starter, y, aunque algunos componentes de los que venían no funcionaban correctamente, se pudieron sustituir por otros iguales que fueron prestados por amigos.
A continuación, se detalla una tabla con todos los componentes empleados, su procedencia y coste:
6. Problemas y soluciones encontradas.
Durante el desarrollo surgieron varios retos:
6.1. Conflictos de temporizadores.
El microservo, el buzzer y el sensor IR dependían del mismo temporizador interno, lo que generaba fallos en su funcionamiento, como ya se ha mencionado anteriormente.
Tras buscar soluciones cambiando de librerías y pines, y no encontrar ninguna, se optó por eliminar el buzzer y utilizar bibliotecas alternativas que resolvieran el conflicto entre el microservo y el sensor IR.
6.2. Cables defectuosos.
Algunos cables del kit no funcionaban correctamente, por lo que se cambiaron los cables los cables dañados por otros en buen estado que habían sido prestados por amigos.
6.3. Diseño estructural – brazo removedor.
El brazo que remueve la bebida no tenía la estabilidad necesaria y a veces se atascaba al bajar o al subir la cuchara. Por ello se añadieron estructuras auxiliares para mejorar la funcionalidad y mitigar estos problemas.
7. Código y casos de uso.
El código implementado en el robot Coffeeto combina múltiples funcionalidades para lograr un sistema automatizado y eficiente de preparación de bebidas calientes.
7.1. Sobre el código.
7.1.1. Estructura general.
Librerías:
Se incluyen librerías necesarias para manejar los componentes: LiquidCrystal para la pantalla LCD, DHT para el sensor de temperatura y humedad, VarSpeedServo para el servo motor, e IRremote para el receptor de infrarrojos.
Definición de pines:
Se configuran los pines correspondientes para conectar cada componente, como el sensor ultrasónico, el motor DC, el LED y el receptor IR.
Declaración de variables:
Variables globales como currentMenu permiten gestionar el menú, y otras como tiempoRemover y tiempoTemporizador establecen valores predeterminados para las funciones específicas.
7.1.2. Fases principales del código.
Setup.
-Inicialización:
Se configura el LCD, el servo, el sensor DHT11, y el receptor IR, y se muestran mensajes iniciales en la pantalla LCD para guiar al usuario.
-Caracteres especiales:
Se crean flechas personalizadas para mejorar la experiencia visual en el desplazamiento lateral entre los menús.
Loop:
-Recepción de señales IR:
El código espera entradas desde el control remoto IR. Según el botón pulsado, se llama a la función procesarEntradaIR(), que maneja la navegación entre menús y la ejecución de funciones.
Gestión del menú.
-Menú principal:
Permite elegir entre los modos manual y automático:
- Manual: Ejecuta funciones específicas como remover, medir temperatura o usar el temporizador.
- Automático: Realiza un flujo completo de preparación de café o infusión, que incluye medir temperatura y remover para la preparación de cafés, y lo mismo para las infusiones pero agregando la función de temporizador.
-Funciones auxiliares:
- mostrarMensajeLCD() para mostrar mensajes en la pantalla.
- beepError() para alertar al usuario mediante el LED (se nombró así porque en un principio, además de alertar visualmente mediante el led, se hacía mediante el buzzer).
- esperarTaza() para verificar la posición correcta de la taza con el sensor ultrasónico.
7.1.3. Funciones principales.
Medir temperatura:
Utiliza el sensor DHT11 para medir la temperatura actual de la bebida y compara los valores con el rango seleccionado por el usuario.
Remover:
Activa el motor DC y mueve el servo para simular el movimiento de una cuchara que remueve los ingredientes durante el tiempo configurado.
Temporizador:
Realiza una cuenta regresiva visible en la pantalla LCD. Es útil para controlar el tiempo de reposo en infusiones.
Preparación automática:
Incluye un flujo completo que integra las funciones anteriores para preparar café o infusión según la selección del usuario.
7.2. Casos de uso
Modo manual.
- Remover: El usuario puede usar el control remoto para activar esta función cuando quiera mezclar los ingredientes de forma precisa.
- Medir temperatura: El robot muestra por pantalla la temperatura de la bebida actual, una vez colocada en la posición correcta. Así, el usuario se puede asegurar fácilmente de que la bebida alcance la temperatura deseada.
- Temporizador: Útil para controlar el tiempo de reposo de las infusiones.
Modo automático.
- Café: El robot mide la temperatura, espera a que sea la adecuada según la seleccionada por el usuario, y remueve la bebida tras detectar que la taza está en su lugar.
- Infusión: Incluye un temporizador inicial y luego sigue el flujo para verificar la temperatura según la seleccionada por el usuario y así remover la bebida finalmente.
// Librerías
#include <LiquidCrystal.h>
#include <DHT.h>
#include <VarSpeedServo.h>
#include <IRremote.h>
// Pines
const int piezoPin = 6;
const int trigPin = 4;
const int echoPin = 3;
const int motorPin1 = 9;
const int motorPin2 = 6;
const int ledPin = 11;
const int pinDHT11 = 10;
const int IR_PIN = 2;
// Configuración del LCD
LiquidCrystal lcd(A0, A1, A5, A4, A3, A2);
// Configuración del Servo
VarSpeedServo myServo;
// Configuración del sensor DHT11
#define DHTTYPE DHT11
DHT dht(pinDHT11, DHTTYPE);
// Inicializa el receptor IR
void procesarEntradaIR(int boton);
// Variables del sensor ultrasónico
long duration;
int distance;
// Variables del menú
int currentMenu = 0;
int tiempoRemover = 10; // Tiempo predeterminado en segundos para remover
int tiempoTemporizador = 20; // Tiempo predeterminado en segundos para el temporizador
int tempSeleccionadaMin = 0; // Temperatura mínima del rango
int tempSeleccionadaMax = 0; // Temperatura máxima del rango
// Funciones
void procesarEntradaIR(int boton);
void ejecutarManual(int opcion);
void prepararBebida(bool esCafe);
void medirDistancia();
void mostrarMensajeLCD(const char* linea1, const char* linea2);
void beepError();
void esperarTaza();
void medirTemperatura();
void temporizador(int segundos);
void remover();
void indicarFinDeFase();
int mapCodeToButton(unsigned long code);
void configurarTiempo(int* tiempo);
// Caracter especial ->
byte flechaDerecha[] = {
B00000,
B00100,
B00010,
B11111,
B00010,
B00100,
B00000,
B00000
};
// Caracter especial <-
byte flechaIzquierda[] = {
B00000,
B00100,
B01000,
B11111,
B01000,
B00100,
B00000,
B00000
};
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
lcd.print("Iniciando...");
pinMode(piezoPin, OUTPUT);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(motorPin1, OUTPUT);
pinMode(motorPin2, OUTPUT);
pinMode(ledPin, OUTPUT);
myServo.attach(7);
IrReceiver.begin(IR_PIN, ENABLE_LED_FEEDBACK);
dht.begin();
delay(2000);
lcd.createChar(0, flechaDerecha);
lcd.createChar(1, flechaIzquierda);
myServo.write(80, 90);
lcd.clear();
lcd.setCursor(15, 0);
lcd.write(byte(0));
mostrarMensajeLCD("Bienvenido", "Seleccione menu");
}
void loop() {
if (IrReceiver.decode()) {
unsigned long code = IrReceiver.decodedIRData.decodedRawData;
int button = mapCodeToButton(code);
if (button != -1) {
Serial.print(F("Botón presionado: "));
Serial.println(button);
procesarEntradaIR(button);
} else {
Serial.println(F("Código IR no reconocido"));
}
IrReceiver.resume();
}
}
void procesarEntradaIR(int boton) {
switch (currentMenu) {
// Menú principal
case 0:
// Manual
if (boton == 1) {
currentMenu = 1;
lcd.clear();
lcd.setCursor(15, 0);
lcd.write(byte(0));
mostrarMensajeLCD("1-Remover", "2-Temperatura");
// Automático
} else if (boton == 2) {
currentMenu = 2;
lcd.clear();
mostrarMensajeLCD("1-Cafe", "2-Infusion");
// Inicio derecha
} else if (boton == 15) {
lcd.clear();
lcd.setCursor(15, 0);
lcd.write(byte(1));
mostrarMensajeLCD("1-Manual", "2-Automatico");
// Inicio izquierda
} else if (boton == 13) {
lcd.clear();
lcd.setCursor(15, 0);
lcd.write(byte(0));
mostrarMensajeLCD("Bienvenido", "Seleccione menu");
}
break;
// Menú manual
case 1:
// Manual izquierda
if (boton == 13) {
lcd.clear();
lcd.setCursor(15, 0);
lcd.write(byte(0));
mostrarMensajeLCD("1-Remover", "2-Temperatura");
// Manual derecha
} else if (boton == 15) {
lcd.clear();
lcd.setCursor(15, 1);
lcd.write(byte(1));
mostrarMensajeLCD("3-Temporizador", "");
// Remover, temperatura, temporizador
} else if (boton >= 1 && boton <= 3) {
ejecutarManual(boton); // Ejecuta la opción seleccionada
currentMenu = 0;
lcd.clear();
lcd.setCursor(15, 0);
lcd.write(byte(0));
mostrarMensajeLCD("Bienvenido", "Seleccione menu");
// Volver menú
} else if (boton == 0) {
lcd.clear();
mostrarMensajeLCD("Volviendo", "al menu...");
delay(500);
lcd.clear();
lcd.setCursor(15, 0);
lcd.write(byte(0));
mostrarMensajeLCD("Bienvenido", "Seleccione menu");
currentMenu = 0;
}
break;
// Menú automático
case 2:
// Café
if (boton == 1) {
ejecutarAuto(true);
currentMenu = 0;
lcd.clear();
lcd.setCursor(15, 0);
lcd.write(byte(0));
mostrarMensajeLCD("Bienvenido", "Seleccione menu");
// Infusión
} else if (boton == 2) {
ejecutarAuto(false);
currentMenu = 0;
lcd.clear();
lcd.setCursor(15, 0);
lcd.write(byte(0));
mostrarMensajeLCD("Bienvenido", "Seleccione menu");
// Volver menú
} else if (boton == 0) {
lcd.clear();
mostrarMensajeLCD("Volviendo", "al menu...");
delay(500);
lcd.clear();
lcd.setCursor(15, 0);
lcd.write(byte(0));
mostrarMensajeLCD("Bienvenido", "Seleccione menu");
currentMenu = 0;
}
break;
}
}
void ejecutarManual(int opcion) {
switch (opcion) {
// Remover
case 1:
limpiarBufferIR();
esperarTaza();
configurarTiempo(&tiempoRemover);
remover();
break;
// Temperatura
case 2:
esperarTaza();
medirTemperatura();
break;
// Temporizador
case 3:
limpiarBufferIR();
configurarTiempo(&tiempoTemporizador);
temporizador();
break;
}
}
void ejecutarAuto(bool esCafe) {
limpiarBufferIR();
// Café
if (esCafe) {
esperarTaza();
seleccionarTemperatura();
bool midiendoTemperatura = true;
while (midiendoTemperatura) {
float temperatura = dht.readTemperature();
//float humedad = dht.readHumidity();
if (!isnan(temperatura)) {
//if (!isnan(temperatura) && !isnan(humedad)) {
lcd.clear();
mostrarMensajeLCD("Temperatura:", (String(temperatura) + " g. celsius").c_str());
delay(1000);
} else {
mostrarMensajeLCD("Error", "DHT11");
}
if (IrReceiver.decode()) {
unsigned long c = IrReceiver.decodedIRData.decodedRawData;
int b = mapCodeToButton(c);
if (b == 0) {
midiendoTemperatura = false;
return;
}
IrReceiver.resume();
}
if (temperatura >= tempSeleccionadaMin && temperatura <= tempSeleccionadaMax) {
midiendoTemperatura = false;
}
}
esperarRetiroTaza();
delay(3000);
esperarTaza();
delay(4000);
remover();
// Infusión
} else {
temporizador();
esperarTaza();
seleccionarTemperatura();
bool midiendoTemperatura = true;
while (midiendoTemperatura) {
float temperatura = dht.readTemperature();
//float humedad = dht.readHumidity();
if (!isnan(temperatura)) {
//if (!isnan(temperatura) && !isnan(humedad)) {
lcd.clear();
mostrarMensajeLCD("Temperatura:", (String(temperatura) + " g. celsius").c_str());
delay(1000);
} else {
mostrarMensajeLCD("Error", "DHT11");
}
if (IrReceiver.decode()) {
unsigned long c = IrReceiver.decodedIRData.decodedRawData;
int b = mapCodeToButton(c);
if (b == 0) {
midiendoTemperatura = false;
return;
}
IrReceiver.resume();
}
if (temperatura >= tempSeleccionadaMin && temperatura <= tempSeleccionadaMax) {
midiendoTemperatura = false;
}
}
esperarRetiroTaza();
delay(3000);
esperarTaza();
delay(4000);
remover();
}
}
void mostrarMensajeLCD(const char* linea1, const char* linea2) {
lcd.setCursor(0, 0);
lcd.print(linea1);
lcd.setCursor(0, 1);
lcd.print(linea2);
Serial.print("LCD: ");
Serial.print(linea1);
Serial.print(" | ");
Serial.println(linea2);
}
void beepError() {
//tone(piezoPin, 1000, 500);
for (int i = 0; i < 4; i++) {
digitalWrite(ledPin, HIGH);
delay(100);
digitalWrite(ledPin, LOW);
delay(100);
}
}
void indicarFinDeFase() {
//tone(piezoPin, 1000, 1000); // Beep de 1 segundo
digitalWrite(ledPin, HIGH);
delay(500); // Mantiene el LED encendido y el buzzer sonando por un tiempo
digitalWrite(ledPin, LOW);
}
void medirDistancia() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = duration * 0.034 / 2;
}
void esperarTaza() {
do {
medirDistancia();
if (distance < 2 || distance > 4) {
lcd.clear();
mostrarMensajeLCD("Coloque la taza", "en su lugar");
beepError();
}
} while (distance < 2 || distance > 4);
}
void esperarRetiroTaza() {
do {
medirDistancia();
if (distance >= 2 && distance <= 4) {
lcd.clear();
mostrarMensajeLCD("Retire la taza y", "eche endulzante");
beepError();
}
} while (distance >= 2 && distance <= 4);
}
void seleccionarTemperatura() {
lcd.clear();
mostrarMensajeLCD("Seleccione Temp", "1-F 2-T 3-C");
bool esperandoSeleccion = true;
while (esperandoSeleccion) {
if (IrReceiver.decode()) {
unsigned long code = IrReceiver.decodedIRData.decodedRawData;
int boton = mapCodeToButton(code);
if (boton == 1) {
// Frío: menor que 20°C
tempSeleccionadaMin = 0; // No hay un límite mínimo específico, cualquier valor menor que 20
tempSeleccionadaMax = 19; // Limite superior es 19°C
esperandoSeleccion = false;
lcd.clear();
mostrarMensajeLCD("Temperatura", "Frio");
delay(2000);
} else if (boton == 2) {
// Templado: entre 20°C y 40°C
tempSeleccionadaMin = 20; // Límite inferior es 20°C
tempSeleccionadaMax = 40; // Límite superior es 40°C
esperandoSeleccion = false;
lcd.clear();
mostrarMensajeLCD("Temperatura", "Templado");
delay(2000);
} else if (boton == 3) {
// Caliente: mayor que 40°C
tempSeleccionadaMin = 41; // Límite inferior es 41°C
tempSeleccionadaMax = 100; // Limite superior arbitrario (podría ser cualquier valor mayor que 40°C)
esperandoSeleccion = false;
lcd.clear();
mostrarMensajeLCD("Temperatura", "Caliente");
delay(2000);
} else if (boton == 0) {
lcd.clear();
mostrarMensajeLCD("Volviendo", "al menu...");
delay(500);
currentMenu = 0;
esperandoSeleccion = false;
}
IrReceiver.resume();
}
}
}
void medirTemperatura() {
float temperatura = dht.readTemperature();
float humedad = dht.readHumidity();
if (!isnan(temperatura) && !isnan(humedad)) {
lcd.clear();
mostrarMensajeLCD("Temperatura:", (String(temperatura) + " g. celsius").c_str());
delay(5000);
} else {
mostrarMensajeLCD("Error", "DHT11");
}
}
void temporizador() {
for (int i = tiempoTemporizador; i >= 0; i--) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Tiempo restante:");
lcd.setCursor(0, 1);
lcd.print(i);
delay(1000);
}
indicarFinDeFase();
}
void remover() {
lcd.clear();
mostrarMensajeLCD("Removiendo", "...");
myServo.write(0, 90);
delay(2000);
//digitalWrite(motorPin1, HIGH);
analogWrite(motorPin1, 255);
// Bucle para mostrar el tiempo restante en la pantalla LCD
for (int i = tiempoRemover; i > 0; i--) {
lcd.clear();
mostrarMensajeLCD("Removiendo:", String(i).c_str());
delay(1000); // Espera 1 segundo entre cada decremento
}
//digitalWrite(motorPin1, LOW); // Apagar el motor cuando el tiempo se agota
analogWrite(motorPin1, 0); // Apagar el motor cuando el tiempo se agota
myServo.write(90, 90); // Detener el servo motor
indicarFinDeFase(); // Indicar que la fase ha terminado
}
void limpiarBufferIR() {
// Asegúrate de que no hay datos residuales del IR
while (IrReceiver.decode()) {
IrReceiver.resume(); // Ignorar el valor actual
}
}
void configurarTiempo(int* tiempo) {
lcd.clear();
mostrarMensajeLCD("Tiempo en seg:", String(*tiempo).c_str());
bool firstTime = true;
while (true) {
if (IrReceiver.decode()) {
unsigned long codigo = IrReceiver.decodedIRData.decodedRawData;
int boton = mapCodeToButton(codigo);
// Si el botón es un número del 0 al 9
if (boton >= 0 && boton <= 9 && firstTime) {
firstTime = false;
*tiempo = 0;
*tiempo = (*tiempo * 10) + boton; // Construir el número de tiempo
lcd.clear();
mostrarMensajeLCD("Tiempo en seg:", String(*tiempo).c_str());
} else if (boton >= 0 && boton <= 9) {
*tiempo = (*tiempo * 10) + boton; // Construir el número de tiempo
lcd.clear();
mostrarMensajeLCD("Tiempo en seg:", String(*tiempo).c_str());
} else if (boton == 14) { // Botón OK para confirmar
lcd.clear();
mostrarMensajeLCD("Tiempo fijado:", String(*tiempo).c_str());
delay(2000);
break; // Salir del bucle cuando el usuario confirma
}
IrReceiver.resume();
}
}
}
int mapCodeToButton(unsigned long code) {
switch (code) {
case 0xE916FF00: return 0; // Botón "0"
case 0xF30CFF00: return 1; // Botón "1"
case 0xE718FF00: return 2; // Botón "2"
case 0xA15EFF00: return 3; // Botón "3"
case 0xF708FF00: return 4; // Botón "4"
case 0xE31CFF00: return 5; // Botón "5"
case 0xA55AFF00: return 6; // Botón "6"
case 0xBD42FF00: return 7; // Botón "7"
case 0xAD52FF00: return 8; // Botón "8"
case 0xB54AFF00: return 9; // Botón "9"
case 0xBA45FF00: return 10; // Botón "Apagar/Encender"
case 0xB946FF00: return 11; // Botón "Subir volumen"
case 0xB847FF00: return 12; // Botón "FUNC/STOP"
case 0xBB44FF00: return 13; // Botón "LEFT"
case 0xBF40FF00: return 14; // Botón "OK"
case 0xBC43FF00: return 15; // Botón "RIGHT"
case 0xF807FF00: return 16; // Botón "DOWN"
case 0xEA15FF00: return 17; // Botón "Bajar volumen"
case 0xF609FF00: return 18; // Botón "UP"
case 0xE619FF00: return 19; // Botón "EQ"
case 0xF20DFF00: return 20; // Botón "ST/REP"
default: return -1; // Código no reconocido
}
}