//Universidad del Valle de Guatemala
//Abril 2023
//Proyecto 1 Electrónica Digital
//MÁQUINA EXPENDEDORA DE BEBIDAS
//Adriana Girón 21201
#include <LiquidCrystal.h>
#include <Servo.h> //Se utilizan las librerías correspondientes al lcd y al servo
//Se definen las entradas de la pantalla y el servo motor
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
Servo servoMotor;
//Se definen las entradas de los leds
int led1 = 6;
int led2 = 7;
int led3 = 8;
int led4 = 9;
int led5 = 13;
//Se definen las entradas de los botones
int btnCocaCola = A0;
int btnPepsi = A1;
int btn7Up = A2;
int btnMountainDew = A3;
int btnBlanco = A4;
int btnVb = A5;
// Se definen los estados de la FSM
enum states {
REPOSO, //Sucede cuando la máquina no ha empezado a trabajar
BIENVENIDA, //Da la bienvenida al usuario
DINERO, //El usuario "ingresa dinero" presionando un botón, la máquina solo permite Q10.00
SELECCION, //El usuario escoge la bebida
DISPENSANDO, //Se dispensa la bebida y se simula con el servo
DISPENSADO, //La bebida ha sido dispensada
VUELTO, //El lcd manda un mensaje con el vuelto correspondiente, todas las bebidas valen Q5.00
DESPEDIDA //Se despide del usuario y le agradece por su compra
};
//Registra que bebida ha sido seleccionada y el tiempo que es dispensada
states currentState = BIENVENIDA;
int selectedDrink = 0; //selección
int dispenseTime = 0; //tiempo
void setup() {
//Se declara la función de cada componente
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(led5, INPUT); //Este led es una entrada ya que se debe realizar una acción para que se apague
pinMode(btnCocaCola, INPUT_PULLUP);
pinMode(btnPepsi, INPUT_PULLUP);
pinMode(btn7Up, INPUT_PULLUP);
pinMode(btnMountainDew, INPUT_PULLUP);
pinMode(btnBlanco, INPUT_PULLUP);
pinMode(btnVb, INPUT_PULLUP);
lcd.begin(16, 2); //Se inicia el lcd
Serial.begin(9600); //Se inicia el servo
servoMotor.attach(10); //Pin correspondiente al servo
}
void loop() {
//Se programa la máquina de estados finitos (Máquina Expendedora de Bebidas)
switch(currentState) {
case BIENVENIDA:
digitalWrite(led5, HIGH); //Indica que no se ha ingresado dinero
lcd.clear(); //Limpia cualquier mensaje previo en el LCD
lcd.print("Bienvenido!");
delay(2000); //Espera 2 segundos antes de cambiar de mensaje
lcd.clear();
lcd.print("Ingrese dinero:");
delay(1000); // 1 seg
currentState = DINERO; //Cambia al estado DINERO
break;
case DINERO:
if (digitalRead(btnBlanco) == LOW) { //Se presiona el botón para simular el ingreso de dinero
delay(1000); //1 seg
lcd.clear();
lcd.print("Cantidad: Q10.00");
digitalWrite(led5, HIGH);
delay(2000); //2 seg
currentState = SELECCION; //Cambia al estado de SELECCION
digitalWrite(led5, LOW); //El led de reposo se apaga indicando inicio de la acción
lcd.clear();
lcd.print("Seleccione su");
lcd.setCursor(0,1);
lcd.print("bebida:");
currentState = DISPENSANDO; //Luego de seleccionar, pasa al estado DISPENSADO
}
break;
case DISPENSANDO:
// Espera a que seleccione una bebida
if (digitalRead(btnCocaCola) == LOW) {
selectedDrink = 1;
dispenseTime = 3000; //Tarda 3 segundos en dispensar la bebida
currentState = DISPENSANDO;
lcd.clear();
lcd.print("Dispensando...");
digitalWrite(led1, HIGH); //Los leds 1, 2, 3 y 4 simulan la bebida seleccionada al encenderse
servoMotor.write(0); //posición cero grados del servo
delay(2000); //espera 2 segundos antes de girar
servoMotor.write(180); //Da un giro de 180 grados simulando una máquina expendedora de verdad
lcd.clear();
lcd.print("Coca Cola");
lcd.setCursor(0,1);
lcd.print("Dispensada");
delay(2000);
currentState = DISPENSADO; //cambia al estado DISPENSADO
} else if (digitalRead(btnPepsi) == LOW) { //la lógica es la misma para las cuatro bebidas
selectedDrink = 2;
dispenseTime = 3000;
currentState = DISPENSANDO;
lcd.clear();
lcd.print("Dispensando...");
digitalWrite(led2, HIGH);
servoMotor.write(0);
delay(2000);
servoMotor.write(180);
lcd.clear();
lcd.print("Pepsi");
lcd.setCursor(0,1);
lcd.print("Dispensada");
delay(2000);
currentState = DISPENSADO;
} else if (digitalRead(btn7Up) == LOW) {
selectedDrink = 3;
dispenseTime = 3000;
currentState = DISPENSANDO;
lcd.clear();
lcd.print("Dispensando...");
digitalWrite(led3, HIGH);
servoMotor.write(0);
delay(2000);
servoMotor.write(180);
lcd.clear();
lcd.print("7 Up");
lcd.setCursor(0,1);
lcd.print("Dispensada");
delay(2000);
currentState = DISPENSADO;
} else if (digitalRead(btnMountainDew) == LOW) {
selectedDrink = 4;
dispenseTime = 3000;
currentState = DISPENSANDO;
lcd.clear();
lcd.print("Dispensando...");
digitalWrite(led4, HIGH);
servoMotor.write(0);
delay(2000);
servoMotor.write(180);
lcd.clear();
lcd.print("Mountain Dew");
lcd.setCursor(0,1);
lcd.print("Dispensada");
delay(2000);
currentState = DISPENSADO;
}
break;
//El "else if" simplemente indica la selección de una bebida distinta a la anterior
case DISPENSADO:
// Procede a dispensar la bebida seleccionada y manda el mensaje para tomarla
lcd.clear();
lcd.print("Tome su");
lcd.setCursor(0,1);
lcd.print("bebida");
delay(1000);
if (digitalRead(btnVb) == LOW) {
//Simula cuando la persona toma la bebida presionando el botón durante un segundo
currentState = VUELTO;
}
break;
case VUELTO:
lcd.clear();
lcd.print("Vuelto: Q5.00"); //Devuelve la diferencia del valor ingresado al usuario
delay(3000);
currentState = DESPEDIDA;
break;
case DESPEDIDA: //La máquina ha completado todos los estados y agradece al usuario
lcd.clear();
lcd.print("Gracias por");
lcd.setCursor(0,1);
lcd.print("preferirnos!");
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
digitalWrite(led4, LOW);
digitalWrite(led5, HIGH); //El led de reposo vuelve a encenderce indicando que esta lista para iniciar de nuevo
selectedDrink = 0;
dispenseTime = 0;
currentState = BIENVENIDA;
delay(5000); //Espera 5 segundo antes de volver a iniciar el ciclo
break;
}
}