BAR MACHINE
1. Introducción
1.1. Integrantes
del Grupo
Real” realizado por el grupo 8 del campus de Vicálvaro. Los integrantes que
componen el grupo son:
Adrián López Balboa
Carlos Caro Giménez
David Clemente Ancos
1.2. Objetivo
del Proyecto
servicio de cócteles y bebidas refrescantes, accionado tanto de forma manual
mediante un display integrado en el chasis, como de forma remota a través de un
controlador integrado en un sistema móvil que funciona vía bluetooth.
y modularidad ofreciendo al usuario un servicio cómodo y a su medida gracias a
la diversidad que puede llegar a ofrecer.
1.3. Planificación
del Proyecto
bombas peristálticas, las cuales bombearán los distintos líquidos desde su
recipiente hasta el cóctel. Consideramos usar 4 bombas debido a que ofrece un
buen equilibrio entre portabilidad y flexibilidad ya que permite hacer
diferentes cócteles manteniendo un tamaño los suficientemente reducido para
permitir su manejo.
sistema, para facilitar su colocación y posterior reemplazo. El vaso de cóctel,
por su parte, se colocará en la parte delantera, que contará también con un
display y 2 botones que ofrecen una interfaz sencilla y directa entre usuario y
máquina.
como todo el circuito y cableado para su correcto funcionamiento, de esta
manera encapsulamos este para proporcionar al usuario un alto nivel de abstracción
sobre los componentes del sistema.
el acceso remoto desde un dispositivo móvil.
2. Materiales
Utilizados y Presupuesto
2.1. Listado
de Materiales Utilizados
-LED Verde.
-LED Blanco X4.
-Pintura Negra
3. Desarrollo
3.1. Preparación
del Proyecto
3.2. Primeros
Pasos
Posteriormente las montamos dejando un lado y la parte superior vacias para facilitar trabajar en el cableado posteriormente.
Una vez que tuvimos las piezas principales, se hizo lo mismo con las piezas complementarias, es decir, las piezas que forman el habitáculo del recipiente, y el panel donde está dispuesto el «display» y los botones de selección.
Ya con todas las piezas necesarias comenzamos a pintar y a montar el chasis, diseñando a la vez la disposición de los componentes hardware necesarios para su correcto funcionamiento.
Tras montar gran parte del chasis, de manera que nos permitiese trabajar dentro de él, lo primero fue preparar la disposición de los LED’s, el display y los botones. Los cables se midieron y soldaron a todos los LEDs y bombas para proporcionar al circuito de mayor robustez.
3.3. Montaje
y Cableado
Más tarde nos encargamos de montar los elementos que consideramos más sencillos, los LED’s blancos del panel horizontal, y los LED’s rojo y verde del frontal, cableando en la placa de inserción creando circuitos independientes para permitir una mayor luminosidad de cada elemento. Finalmente acoplamos los botones en la placa del display que permitirán su funcionamiento.
El circuito resultante es el siguiente:
3.4. Puesta
en Funcionamiento
Comprobación final tanto de las peticiones bluetooth, como del funcionamiento manual mediante el display y los botones.
3.5. Últimos
Retoques
En cuanto al software tuvimos que retocar el código ampliando la funcionalidad del sistema bluetooth, para que la propia aplicación desde la que nos podemos conectar nos exponga las diferentes opciones, y una agregación en el apartado de la actualización de estado de los botones para intentar evitar el «ruido» que a veces sucedían entre ellos.
4. Implementación
Software
4.1. Idea
de Funcionamiento y Especificación
Cada uno de los elementos tienen distinta funcionalidad, y se activan mediante distintos eventos, de manera que diseñamos cada uno por separado.
El funcionamiento de los LED’s consiste en 2 estados: Preparado y Ocupado. Cuando se encuentra en el estado preparado, tan sólo está activado el LED verde. En el estado Ocupado, se desconecta el LED verde y se encienden los LED’s rojo y blancos.
El funcionamiento de las bombas consisten en 2 estados: No Sirviendo y Sirviendo. Cuando se le manda una señal para cambiarlo al estado Sirviendo cada una de las bombas funcionará dependiendo de cual sea el pedido, y en el estado No Sirviendo simplemente están apagadas.
El funcionamiento del display y los botones es el apartado más complicado, debido a que el display siempre estará encendido, y mostrará las opciones que ofrece la máquina y el estado en el que se encuentre («Bienvenido», «Sirviendo», «Que aproveche!»), y los botones funcionan para navegar y seleccionar la opción elegida. El menú es simplemente un array de String con un índice que permite navegar por él.
Los cócteles se encuentran codificados en una matriz de tiempos donde se introduce el número de segundos que se desea que funcione cada bomba. Con tan solo modificar esta se pueden crear y cambiar los cócteles que la máquina puede hacer. Para esta demostración hemos añadido dos cócteles sin alcohol:
- Roy Rogers: 6 partes de Coca-Cola y 1 de granadina
- Resplandor Crepuscular: 3 partes de zumo de piña, 4 partes de zumo de naranja y 1 de granadina
Además de los cócteles se introducen 3 funcionalidades adicionales necesarias para el correcto funcionamiento de la máquina:
- Inicio: Las bombas actúan brevemente para rellenar los tubos de líquido y prepararse para servir cócteles.
- Vaciado: Las bombas funcionan en sentido inverso devolviendo el líquido de los tubos a las botellas para poder extraerlas.
- Limpieza: Las bombas funcionan durante 30seg con la finalidad de colocar agua en lugar de las bebidas y limpiar así tubos y bombas.
Por último, el sistema Bluetooth tiene la funcionalidad de recibir y mandar datos, concretamente envía las opciones que ofrece la máquina y permite recibir una respuesta recibiendo el número del menu correspondiente a cada funcionalidad.
4.2. Código
Final
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
//Declaramos los pins de los botones del frontal
int const botonSig = 30;
int const botonServir = 35;
//Pins de los LEDs
int const ledRojo = 41;
int const ledVerde = 40;
int const ledBlanco1 = 50;
int const ledBlanco2 = 51;
int const ledBlanco3 = 52;
int const ledBlanco4 = 53;
//Declaramos las 4 bombas
AF_DCMotor motor1(1);
AF_DCMotor motor2(2);
AF_DCMotor motor3(3);
AF_DCMotor motor4(4);
//Declaramos el display
LiquidCrystal_I2C lcd(0x27,16,2);
//Variables
int const maxMenu = 5;
int cursorMenu;
String menu[5];
char btdata;
boolean botonSigPulsado;
boolean botonServirPulsado;
boolean servirBT;
int tiempos[5][4];
void inicializarTiempos(){
//Roy Rogers
tiempos[0][0] = 0;
tiempos[0][1] = 0;
tiempos[0][2] = 20;
tiempos[0][3] = 120;
//Resplandor Crepuscular
tiempos[1][0] = 60;
tiempos[1][1] = 80;
tiempos[1][2] = 20;
tiempos[1][3] = 0;
//Inicializar
tiempos[2][0] = 9;
tiempos[2][1] = 9;
tiempos[2][2] = 9;
tiempos[2][3] = 9;
//Limpieza
tiempos[3][0] = 30;
tiempos[3][1] = 30;
tiempos[3][2] = 30;
tiempos[3][3] = 30;
//Vaciado
tiempos[4][0] = 15;
tiempos[4][1] = 15;
tiempos[4][2] = 15;
tiempos[4][3] = 15;
}
void setup() {
inicializarTiempos();
//Inicialización de los LEDs
pinMode(40,OUTPUT);
pinMode(41,OUTPUT);
pinMode(50,OUTPUT);
pinMode(51,OUTPUT);
pinMode(52,OUTPUT);
pinMode(53,OUTPUT);
//Inicialización de los botones
pinMode(30,INPUT);
pinMode(35,INPUT);
//Los motores irán a máxima velocidad
motor1.setSpeed(255);
motor2.setSpeed(255);
motor3.setSpeed(255);
motor4.setSpeed(255);
//Inicialización del display
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(3,0);
lcd.print(«Bienvenido»);
lcd.setCursor (2,1);
lcd.print(«BAR MACHINE»);
//Inicialización bluetooth
pinMode(19,INPUT_PULLUP);
Serial1.begin(9600);
//Inicialización del menú
cursorMenu = 0;
menu[0] = «Roy Rogers»;
menu[1] = «Resp Crepuscular»;
menu[2] = «Iniciar»;
menu[3] = «Limpieza»;
menu[4] = «Vaciado»;
btdata=’0′;
botonSigPulsado = false;
botonServirPulsado = false;
servirBT = false;
Serial1.println(«—————————n1: Roy Rogersn2: Resplandor Crepuscularn3: Iniciarn4: Limpiezan5: Vaciadon—————————«);
delay(2000);
}
void encenderBlancos(){
digitalWrite(ledBlanco1,HIGH);
digitalWrite(ledBlanco2,HIGH);
digitalWrite(ledBlanco3,HIGH);
digitalWrite(ledBlanco4,HIGH);
}
void apagarBlancos(){
digitalWrite(ledBlanco1,LOW);
digitalWrite(ledBlanco2,LOW);
digitalWrite(ledBlanco3,LOW);
digitalWrite(ledBlanco4,LOW);
}
void siguiente(){
cursorMenu = (cursorMenu + 1) % maxMenu;
botonSigPulsado = false;
delay(3000);
}
void servir(){
lcd.clear();
lcd.setCursor (2,1);
lcd.print(«BAR MACHINE»);
lcd.setCursor(3,0);
lcd.print(«Sirviendo»);
digitalWrite(ledVerde,LOW);
digitalWrite(ledRojo,HIGH);
encenderBlancos();
if (cursorMenu !=4){
if (tiempos[cursorMenu][0] > 0){
motor1.run(FORWARD);
for(int i=0; i<tiempos[cursorMenu][0]/40;i++)
delay(39000);
delay(tiempos[cursorMenu][0]%40*1000);
motor1.run(RELEASE);
}
if (tiempos[cursorMenu][1] > 0){
motor2.run(FORWARD);
for(int i=0; i<tiempos[cursorMenu][1]/40;i++)
delay(39000);
delay(tiempos[cursorMenu][1]%40*1000);
motor2.run(RELEASE);
}
if (tiempos[cursorMenu][2] > 0){
motor3.run(FORWARD);
for(int i=0; i<tiempos[cursorMenu][2]/40;i++)
delay(39000);
delay(tiempos[cursorMenu][2]%40*1000);
motor3.run(RELEASE);
}
if (tiempos[cursorMenu][3] > 0){
motor4.run(FORWARD);
for(int i=0; i<tiempos[cursorMenu][3]/40;i++)
delay(39000);
delay(tiempos[cursorMenu][3]%40*1000);
motor4.run(RELEASE);
}
}else{
if (tiempos[cursorMenu][0] > 0){
motor1.run(BACKWARD);
for(int i=0; i<tiempos[cursorMenu][0]/40;i++)
delay(39000);
delay(tiempos[cursorMenu][0]%40*1000);
motor1.run(RELEASE);
}
if (tiempos[cursorMenu][1] > 0){
motor2.run(BACKWARD);
for(int i=0; i<tiempos[cursorMenu][1]/40;i++)
delay(39000);
delay(tiempos[cursorMenu][1]%40*1000);
motor2.run(RELEASE);
}
if (tiempos[cursorMenu][2] > 0){
motor3.run(BACKWARD);
for(int i=0; i<tiempos[cursorMenu][2]/40;i++)
delay(39000);
delay(tiempos[cursorMenu][2]%40*1000);
motor3.run(RELEASE);
}
if (tiempos[cursorMenu][3] > 0){
motor4.run(BACKWARD);
for(int i=0; i<tiempos[cursorMenu][3]/40;i++)
delay(39000);
delay(tiempos[cursorMenu][3]%40*1000);
motor4.run(RELEASE);
}
}
digitalWrite(ledVerde,HIGH);
digitalWrite(ledRojo,LOW);
lcd.clear();
lcd.setCursor(1,0);
lcd.print(«Que aproveche!»);
lcd.setCursor (2,1);
lcd.print(«BAR MACHINE»);
delay(5000);
apagarBlancos();
botonServirPulsado = false;
}
void servirBluetooth(){
lcd.clear();
lcd.setCursor (2,1);
lcd.print(«BAR MACHINE»);
lcd.setCursor(3,0);
lcd.print(«Sirviendo»);
int seleccion = (int) btdata – 49;
digitalWrite(ledVerde,LOW);
digitalWrite(ledRojo,HIGH);
encenderBlancos();
if (seleccion != 4){
if (tiempos[seleccion][0] > 0){
motor1.run(FORWARD);
for(int i=0; i<tiempos[seleccion][0]/40;i++)
delay(39000);
delay(tiempos[seleccion][0]%40*1000);
motor1.run(RELEASE);
}
if (tiempos[seleccion][1] > 0){
motor2.run(FORWARD);
for(int i=0; i<tiempos[seleccion][1]/40;i++)
delay(39000);
delay(tiempos[seleccion][1]%40*1000);
motor2.run(RELEASE);
}
if (tiempos[seleccion][2] > 0){
motor3.run(FORWARD);
for(int i=0; i<tiempos[seleccion][2]/40;i++)
delay(39000);
delay(tiempos[seleccion][2]%40*1000);
motor3.run(RELEASE);
}
if (tiempos[seleccion][3] > 0){
motor4.run(FORWARD);
for(int i=0; i<tiempos[seleccion][3]/40;i++)
delay(39000);
delay(tiempos[seleccion][3]%40*1000);
motor4.run(RELEASE);
}
}else{
if (tiempos[seleccion][0] > 0){
motor1.run(BACKWARD);
for(int i=0; i<tiempos[seleccion][0]/40;i++)
delay(39000);
delay(tiempos[seleccion][0]%40*1000);
motor1.run(RELEASE);
}
if (tiempos[seleccion][1] > 0){
motor2.run(BACKWARD);
for(int i=0; i<tiempos[seleccion][1]/40;i++)
delay(39000);
delay(tiempos[seleccion][1]%40*1000);
motor2.run(RELEASE);
}
if (tiempos[seleccion][2] > 0){
motor3.run(BACKWARD);
for(int i=0; i<tiempos[seleccion][2]/40;i++)
delay(39000);
delay(tiempos[seleccion][2]%40*1000);
motor3.run(RELEASE);
}
if (tiempos[seleccion][3] > 0){
motor4.run(BACKWARD);
for(int i=0; i<tiempos[seleccion][3]/40;i++)
delay(39000);
delay(tiempos[seleccion][3]%40*1000);
motor4.run(RELEASE);
}
}
digitalWrite(ledVerde,HIGH);
digitalWrite(ledRojo,LOW);
lcd.clear();
lcd.setCursor(1,0);
lcd.print(«Que aproveche!»);
lcd.setCursor (2,1);
lcd.print(«BAR MACHINE»);
delay(5000);
apagarBlancos();
btdata = ‘0’;
servirBT = false;
}
void loop() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print(menu[cursorMenu]);
lcd.setCursor (2,1);
lcd.print(«BAR MACHINE»);
digitalWrite(ledVerde,HIGH);
Serial1.println(«—————————n1: Roy Rogersn2: Resplandor Crepuscularn3: Iniciarn4: Limpiezan5: Vaciadon—————————«);
while(!servirBT && !botonSigPulsado && !botonServirPulsado){
if (Serial1.available() > 0){
btdata = Serial1.read();
if (btdata>=’1′ && btdata<=’5′)
servirBT = true;
}
if (digitalRead(botonSig) == HIGH){ //Se hace una doble comprobación para evitar pulsaciones falsar por ruido
delay(50);
if (digitalRead(botonSig) == HIGH){
botonSigPulsado = true;
}
}else if (digitalRead(botonServir) == HIGH){ //Se hace una doble comprobación para evitar pulsaciones falsar por ruido
delay(50);
if (digitalRead(botonServir) == HIGH){
botonServirPulsado = true;
}
}
}
if (botonSigPulsado){
siguiente();
}else{
if (botonServirPulsado){
servir();
}else{
servirBluetooth();
}
}
}
5. En
Funcionamiento
6. Problemas durante
el montaje
Los mayores problemas encontrados fueron en el funcionamiento del módulo bluetooth, y de los botones. El sistema bluetooth conseguimos solucionarlo dado que simplemente consistía en re implementar el código para recibir bien los datos, aunque seguimos teniendo problemas con la aplicación oficial del dispositivo dado que no está demasiado optimizada. En cuanto a los botones, encontramos un problema de «ruido» que se producía entre ellos. Revisamos tanto el circuito como el software correspondiente, pero lamentablemente no encontramos ningún problema, por tanto, mediante un módulo de comprobación que implementamos conseguimos estabilizar los resultados.
Por último, observamos que al hacer un delay() superior a 40seg el arduino se bloqueba completamente no parando nunca de servir el cóctel. Para solucionar esto dividimos los tiempos superiores a 40 seg en grupos de 39 para hacer distintas llamadas a delay() y solventar el problema.