#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Endereço e dimensões do LCD (verifique o endereço I2C)
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Pinos de entrada
int botaoMoeda = 12; // Pino para simular botão de crédito
int botaoDispensa = 2; // Pino para botão de dispensar manualmente
int botaoCachacaNormal = 3; // Pino para selecionar cachaça normal
int botaoCachacaPremium = 4; // Pino para selecionar cachaça premium
int botaoCachacaEspecial = 5; // Pino para selecionar cachaça especial
// Pinos de saída (motores representados por LEDs)
int motorCachacaNormalPin = 6; // Pino para motor de cachaça normal (LED)
int motorCachacaPremiumPin = 7; // Pino para motor de cachaça premium (LED)
int motorCachacaEspecialPin = 8; // Pino para motor de cachaça especial (LED)
// Pinos de saída para LEDs
int creditLedPin = 9; // Pino para LED de crédito
int variableBlinkLedPin = 10; // Pino para LED que pisca com intervalos variáveis
// Variáveis de controle
int precoDose = 100; // Preço de uma dose de cachaça em centavos
int saldo = 0;
int tipoCachaca = -1; // -1: Nenhuma, 0: Cachaça Normal, 1: Cachaça Premium, 2: Cachaça Especial
// Variáveis para debounce
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
// Variáveis para estado dos botões
int lastBotaoMoedaState = HIGH;
int lastBotaoDispensaState = LOW;
int lastBotaoNormalState = LOW;
int lastBotaoPremiumState = LOW;
int lastBotaoEspecialState = LOW;
// Variáveis para verificar mudanças de estado
int previousSaldo = -1;
int previousTipoCachaca = -1;
// Variáveis para controle de LED de crédito
unsigned long previousMillis = 0;
const long ledBlinkInterval = 500; // Intervalo de piscada do LED de crédito
bool ledState = LOW; // Estado atual do LED de crédito
// Variáveis para controle de LED com piscada variável
unsigned long previousVariableBlinkMillis = 0;
int blinkIntervals[] = {100, 200, 300}; // Intervalos de piscada do LED variável
int currentIntervalIndex = 0;
long variableBlinkInterval = blinkIntervals[currentIntervalIndex];
bool variableBlinkLedState = LOW; // Estado atual do LED variável
// Variável para ajuste de velocidade do LED variável
int blinkSpeed = 0; // 0: 100ms, 1: 200ms, 2: 300ms
void setup() {
// Inicializa o LCD
lcd.init();
lcd.backlight();
// Configura pinos de entrada e saída
pinMode(botaoMoeda, INPUT_PULLUP);
pinMode(botaoDispensa, INPUT_PULLUP);
pinMode(botaoCachacaNormal, INPUT_PULLUP);
pinMode(botaoCachacaPremium, INPUT_PULLUP);
pinMode(botaoCachacaEspecial, INPUT_PULLUP);
pinMode(motorCachacaNormalPin, OUTPUT);
pinMode(motorCachacaPremiumPin, OUTPUT);
pinMode(motorCachacaEspecialPin, OUTPUT);
// Configura os pinos dos LEDs
pinMode(creditLedPin, OUTPUT);
pinMode(variableBlinkLedPin, OUTPUT);
// Inicializa a comunicação serial para depuração
Serial.begin(9600);
// Exibe a mensagem inicial no LCD
displayInfo();
}
void loop() {
unsigned long currentTime = millis();
// Lê o estado de cada botão
int leituraMoeda = digitalRead(botaoMoeda);
int leituraBotaoDispensa = digitalRead(botaoDispensa);
int leituraBotaoNormal = digitalRead(botaoCachacaNormal);
int leituraBotaoPremium = digitalRead(botaoCachacaPremium);
int leituraBotaoEspecial = digitalRead(botaoCachacaEspecial);
// Detecta a inserção de moeda com debouncing
if (leituraMoeda == LOW && lastBotaoMoedaState == HIGH && (currentTime - lastDebounceTime) > debounceDelay) {
saldo += 100; // Adiciona 1 real ao saldo
Serial.println("Crédito adicionado: R$ 1,00");
lastDebounceTime = currentTime; // Atualiza o tempo de debounce
}
lastBotaoMoedaState = leituraMoeda;
// Verifica se o botão de dispensar foi pressionado
if (leituraBotaoDispensa == HIGH && lastBotaoDispensaState == LOW && saldo >= precoDose) {
dispensarDose();
}
lastBotaoDispensaState = leituraBotaoDispensa;
// Verifica a seleção de cachaça
if (leituraBotaoNormal == HIGH && lastBotaoNormalState == LOW) {
selecionarTipoCachaca(0); // Cachaça Normal
}
lastBotaoNormalState = leituraBotaoNormal;
if (leituraBotaoPremium == HIGH && lastBotaoPremiumState == LOW) {
selecionarTipoCachaca(1); // Cachaça Premium
}
lastBotaoPremiumState = leituraBotaoPremium;
if (leituraBotaoEspecial == HIGH && lastBotaoEspecialState == LOW) {
selecionarTipoCachaca(2); // Cachaça Especial
}
lastBotaoEspecialState = leituraBotaoEspecial;
// Atualiza o display do LCD apenas se houver mudança no saldo ou tipo de cachaça
if (saldo != previousSaldo || tipoCachaca != previousTipoCachaca) {
displayInfo();
previousSaldo = saldo;
previousTipoCachaca = tipoCachaca;
}
// Atualiza o LED de crédito
updateCreditLed(currentTime);
// Atualiza o LED que pisca com intervalos variáveis
blinkVariableLed(currentTime);
}
void dispensarDose() {
int motorPin;
int duracao;
// Determina o motor e a duração com base no tipo de cachaça selecionado
switch (tipoCachaca) {
case 0:
motorPin = motorCachacaNormalPin;
duracao = 2000;
break;
case 1:
motorPin = motorCachacaPremiumPin;
duracao = 2500;
break;
case 2:
motorPin = motorCachacaEspecialPin;
duracao = 3000;
break;
default:
Serial.println("Nenhum tipo de cachaça selecionado.");
return; // Se nenhum tipo de cachaça estiver selecionado, não faz nada
}
// Atualiza o display do LCD para mostrar "Servindo..."
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Servindo...");
// Ativa o motor para dispensar a dose
Serial.print("Dispensando cachaça tipo ");
Serial.println(tipoCachaca);
digitalWrite(motorPin, HIGH);
delay(duracao); // Espera o tempo necessário para dispensar a dose
digitalWrite(motorPin, LOW);
// Deduz o preço da dose do saldo
saldo -= precoDose;
Serial.println("Dose dispensada");
// Atualiza o display do LCD para mostrar o saldo restante
displayInfo();
}
void selecionarTipoCachaca(int tipo) {
tipoCachaca = tipo;
Serial.print("Tipo de cachaça selecionado: ");
if (tipo == 0) Serial.println("Normal");
else if (tipo == 1) Serial.println("Premium");
else if (tipo == 2) Serial.println("Especial");
}
void displayInfo() {
lcd.clear();
lcd.setCursor(0, 0);
String tipo;
// Determina a mensagem a ser exibida com base no tipo de cachaça selecionado
switch (tipoCachaca) {
case 0:
tipo = "Normal";
break;
case 1:
tipo = "Premium";
break;
case 2:
tipo = "Especial";
break;
default:
tipo = "Nenhuma";
break;
}
lcd.print("Cachaca: " + tipo);
lcd.setCursor(0, 1);
lcd.print("Saldo: R$");
lcd.print(saldo / 100.0, 2);
}
void updateCreditLed(unsigned long currentTime) {
if (saldo > 0) {
// Verifica se é hora de mudar o estado do LED
if (currentTime - previousMillis >= ledBlinkInterval) {
previousMillis = currentTime;
ledState = !ledState;
digitalWrite(creditLedPin, ledState);
}
} else {
// Desliga o LED se não houver crédito
digitalWrite(creditLedPin, LOW);
}
}
void blinkVariableLed(unsigned long currentTime) {
// Verifica se é hora de mudar o estado do LED
if (currentTime - previousVariableBlinkMillis >= variableBlinkInterval) {
previousVariableBlinkMillis = currentTime;
variableBlinkLedState = !variableBlinkLedState;
digitalWrite(variableBlinkLedPin, variableBlinkLedState);
// Muda o intervalo de piscada
currentIntervalIndex = (currentIntervalIndex + 1) % 3;
variableBlinkInterval = blinkIntervals[currentIntervalIndex];
}
}