#include <Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
// Configurações do LCD
LiquidCrystal_I2C lcd(0x27, 16, 2); // Endereço I2C do LCD pode variar
// Configurações do teclado 4x4
const byte ROWS = 4; // Quatro linhas
const byte COLS = 4; // Quatro colunas
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; // Pinos conectados às linhas do teclado
byte colPins[COLS] = {5, 4, 3, 2}; // Pinos conectados às colunas do teclado
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Configurações dos servos
Servo servos[40]; // Array para 40 servos
int servoPins[40] = {22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, A0, A1, A2, A3, A4, A5, A6, A7};
// Pinos do moedeiro e botão de confirmação
const int coinPin = 18; // Pino para o botão/moedeiro
const int confirmPin = 19; // Pino para o botão de confirmação
// Pinos dos botões do menu
const int menuButtonPin = 10;
const int selectButtonPin = 11;
const int increaseButtonPin = 12;
const int decreaseButtonPin = 13;
const int changeNameButtonPin = 14;
// Estados do menu
enum MenuState { MENU_OFF, MENU_ON, SELECTING, CHANGING_PRICE, CHANGING_NAME };
MenuState menuState = MENU_OFF;
int selectedProduct = 0; // Produto atualmente selecionado para ajuste
// Mapeamento de pinos de servo para valores em reais
float valoresProdutos[40] = {
1.00, 2.00, 3.00, 4.00, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00,
11.00, 12.00, 13.00, 14.00, 15.00, 16.00, 17.00, 18.00, 19.00, 20.00,
21.00, 22.00, 23.00, 24.00, 25.00, 26.00, 27.00, 28.00, 29.00, 30.00,
31.00, 32.00, 33.00, 34.00, 35.00, 36.00, 37.00, 38.00, 39.00, 40.00
};
// Nomes dos produtos
String nomesProdutos[40] = {
"chocolate", "oleo", "acucar", "leite", "deterjente",
"feijao", "farinha", "azeite", "sal", "sabao em po",
"vinagre", "bolacha", "macarrao", "tang", "azeitona",
"pao de forma", "pimenta", "agua de coco", "suco de uva", "cafe",
"azeitona", "maioneze", "leite em po", "carvao", "carne seca",
"suco laranja", "esponja de aco", "miogo", "creme dental", "amaciante",
"barra chocolate", "sal grosso", "camizinha", "cotonete sabonete", "shampo",
"cigarro 1", "cigarro 2", "cigarro 3", "isqueiro", "cigarro solto"
};
// Mapeamento de números para letras
const char* numeroParaLetras[] = {
" ", // 0
" ", // 1 (normalmente não usado para letras)
"ABC", // 2
"DEF", // 3
"GHI", // 4
"JKL", // 5
"MNO", // 6
"PQRS", // 7
"TUV", // 8
"WXYZ" // 9
};
// Variáveis globais
float valorInserido = 0.0;
int produtoSelecionado = -1; // Inicializa sem nenhum produto selecionado
String entradaProduto = ""; // Armazena a entrada do número do produto
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50; // 50 ms para debounce
bool lastCoinButtonState = HIGH;
bool coinButtonPressed = false;
bool lastConfirmButtonState = HIGH;
bool confirmButtonPressed = false;
String novoNomeProduto = ""; // Variável para armazenar o novo nome do produto
int letrasIndex = 0; // Índice para letras mapeadas
void setup() {
Serial.begin(9600); // Inicializa comunicação serial para depuração
lcd.begin(16, 2); // Inicializa o LCD com 16 colunas e 2 linhas
lcd.backlight();
lcd.print("COLOQUE CREDITO:");
// Configuração dos pinos do moedeiro, botão de confirmação e botões do menu
pinMode(coinPin, INPUT_PULLUP); // Usa pull-up interno para evitar flutuações
pinMode(confirmPin, INPUT_PULLUP); // Usa pull-up interno para evitar flutuações
pinMode(menuButtonPin, INPUT_PULLUP);
pinMode(selectButtonPin, INPUT_PULLUP);
pinMode(increaseButtonPin, INPUT_PULLUP);
pinMode(decreaseButtonPin, INPUT_PULLUP);
pinMode(changeNameButtonPin, INPUT_PULLUP);
}
void loop() {
char key = keypad.getKey();
if (key != NO_KEY) {
if (isdigit(key) && menuState != CHANGING_NAME) { // Verifica se a tecla pressionada é um dígito
entradaProduto += key; // Adiciona o dígito à entrada do produto
int produtoTemp = entradaProduto.toInt() - 1; // Converte a entrada para número do produto
if (produtoTemp >= 0 && produtoTemp < 40) {
lcd.clear();
lcd.print("Produto N="); // Exibe "Produto N=" na linha superior
lcd.print(entradaProduto); // Exibe o número do produto
lcd.setCursor(0, 1);
lcd.print(nomesProdutos[produtoTemp]); // Exibe o nome do produto
lcd.print(" R$");
lcd.print(valoresProdutos[produtoTemp], 2); // Exibe o valor do produto
} else {
lcd.clear();
lcd.print("Prod Inválido"); // Exibe mensagem de produto inválido
}
} else if (key == '#') { // Apaga o número digitado em caso de erro
entradaProduto = "";
lcd.clear();
lcd.print("Produto: ");
lcd.print(entradaProduto);
lcd.setCursor(0, 1);
lcd.print("CREDITO: ");
lcd.print(valorInserido);
} else if (menuState == CHANGING_NAME) {
if (key == '#') {
// Confirmar o novo nome
nomesProdutos[selectedProduct] = novoNomeProduto;
menuState = MENU_ON;
novoNomeProduto = "";
lcd.clear();
lcd.print("Nome Alterado");
delay(1000);
lcd.clear();
} else if (key == '*') {
// Apagar o último caractere
if (novoNomeProduto.length() > 0) {
novoNomeProduto.remove(novoNomeProduto.length() - 1);
}
} else {
// Adicionar o caractere ao novo nome
int numero = key - '0'; // Converte a tecla pressionada para o número correspondente
if (letrasIndex < strlen(numeroParaLetras[numero])) {
novoNomeProduto += numeroParaLetras[numero][letrasIndex];
letrasIndex++;
} else {
letrasIndex = 0;
novoNomeProduto += numeroParaLetras[numero][letrasIndex];
}
}
lcd.clear();
lcd.print("Novo Nome:");
lcd.setCursor(0, 1);
lcd.print(novoNomeProduto);
}
}
bool coinButtonState = digitalRead(coinPin);
if (coinButtonState != lastCoinButtonState) {
lastDebounceTime = millis(); // Reseta o tempo de debounce
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (coinButtonState == LOW && !coinButtonPressed) { // Moeda inserida
valorInserido += 0.25; // Valor por exemplo, ajustar conforme necessário
lcd.clear();
lcd.print("CREDITO: ");
lcd.print(valorInserido, 2);
coinButtonPressed = true;
} else if (coinButtonState == HIGH && coinButtonPressed) {
coinButtonPressed = false; // Moeda liberada
}
}
lastCoinButtonState = coinButtonState;
bool confirmButtonState = digitalRead(confirmPin);
if (confirmButtonState != lastConfirmButtonState) {
lastDebounceTime = millis(); // Reseta o tempo de debounce
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (confirmButtonState == LOW && !confirmButtonPressed) { // Botão foi pressionado
if (entradaProduto.length() > 0) {
produtoSelecionado = entradaProduto.toInt() - 1; // Converte a entrada para número do produto
}
if (produtoSelecionado >= 0 && produtoSelecionado < 40) {
lcd.clear();
lcd.print("LIBERANDO ");
lcd.print(nomesProdutos[produtoSelecionado]);
lcd.setCursor(0, 1);
lcd.print("VALOR: R$ ");
lcd.print(valoresProdutos[produtoSelecionado], 2);
Serial.print("Valor do produto: ");
Serial.println(valoresProdutos[produtoSelecionado]); // Imprime valor do produto para depuração
if (valorInserido >= valoresProdutos[produtoSelecionado]) {
Serial.println("Saldo suficiente, acionando servo."); // Depuração
servos[produtoSelecionado].attach(servoPins[produtoSelecionado]); // Ativa o servo
servos[produtoSelecionado].write(180);
delay(1000);
servos[produtoSelecionado].write(0);
delay(500); // Espera meio segundo antes de desligar o servo
servos[produtoSelecionado].detach(); // Desativa o servo
valorInserido -= valoresProdutos[produtoSelecionado];
lcd.clear();
lcd.print("CREDITO: ");
lcd.print(valorInserido);
produtoSelecionado = -1; // Reseta a seleção de produto
entradaProduto = "";
} else {
lcd.clear(); // Limpa o LCD antes de mostrar a mensagem
lcd.print("Saldo insuficiente");
Serial.println("Saldo insuficiente."); // Depuração
}
} else {
lcd.clear(); // Limpa o LCD antes de mostrar a mensagem
lcd.print("Prod Inválido");
Serial.println("Produto inválido."); // Depuração
produtoSelecionado = -1; // Reseta a seleção de produto
}
confirmButtonPressed = true;
} else if (confirmButtonState == HIGH && confirmButtonPressed) {
confirmButtonPressed = false; // Botão foi liberado
}
}
lastConfirmButtonState = confirmButtonState;
// Lógica do menu
if (digitalRead(menuButtonPin) == LOW) {
if (menuState == MENU_OFF) {
menuState = MENU_ON;
lcd.clear();
lcd.print("Menu Ligado");
delay(1000);
lcd.clear();
} else {
menuState = MENU_OFF;
lcd.clear();
lcd.print("Menu Desligado");
delay(1000);
lcd.clear();
}
delay(500); // Debounce delay
}
if (menuState != MENU_OFF) {
if (digitalRead(selectButtonPin) == LOW) {
if (menuState == MENU_ON) {
menuState = SELECTING;
lcd.clear();
lcd.print("Selecionando:");
lcd.setCursor(0, 1);
lcd.print(nomesProdutos[selectedProduct]);
lcd.print(" R$");
lcd.print(valoresProdutos[selectedProduct], 2);
} else if (menuState == SELECTING) {
menuState = CHANGING_PRICE;
lcd.clear();
lcd.print("Alterar Preco");
lcd.setCursor(0, 1);
lcd.print(nomesProdutos[selectedProduct]);
lcd.print(" R$");
lcd.print(valoresProdutos[selectedProduct], 2);
} else if (menuState == CHANGING_PRICE) {
menuState = CHANGING_NAME;
lcd.clear();
lcd.print("Alterar Nome");
lcd.setCursor(0, 1);
lcd.print(nomesProdutos[selectedProduct]);
} else if (menuState == CHANGING_NAME) {
menuState = MENU_ON;
lcd.clear();
lcd.print("Menu Ligado");
delay(1000);
lcd.clear();
}
delay(500); // Debounce delay
}
if (menuState == SELECTING || menuState == CHANGING_PRICE || menuState == CHANGING_NAME) {
if (digitalRead(increaseButtonPin) == LOW) {
if (menuState == SELECTING) {
selectedProduct = (selectedProduct + 1) % 40;
lcd.clear();
lcd.print("Selecionando:");
lcd.setCursor(0, 1);
lcd.print(nomesProdutos[selectedProduct]);
lcd.print(" R$");
lcd.print(valoresProdutos[selectedProduct], 2);
} else if (menuState == CHANGING_PRICE) {
valoresProdutos[selectedProduct] += 0.5; // Incrementa o valor em 0.5 reais
lcd.clear();
lcd.print("Alterar Preco");
lcd.setCursor(0, 1);
lcd.print(nomesProdutos[selectedProduct]);
lcd.print(" R$");
lcd.print(valoresProdutos[selectedProduct], 2);
}
delay(500); // Debounce delay
}
if (digitalRead(decreaseButtonPin) == LOW) {
if (menuState == SELECTING) {
selectedProduct = (selectedProduct - 1 + 40) % 40; // Decrementa com wrap-around
lcd.clear();
lcd.print("Selecionando:");
lcd.setCursor(0, 1);
lcd.print(nomesProdutos[selectedProduct]);
lcd.print(" R$");
lcd.print(valoresProdutos[selectedProduct], 2);
} else if (menuState == CHANGING_PRICE) {
valoresProdutos[selectedProduct] -= 0.5; // Decrementa o valor em 0.5 reais
if (valoresProdutos[selectedProduct] < 0) valoresProdutos[selectedProduct] = 0; // Evita valores negativos
lcd.clear();
lcd.print("Alterar Preco");
lcd.setCursor(0, 1);
lcd.print(nomesProdutos[selectedProduct]);
lcd.print(" R$");
lcd.print(valoresProdutos[selectedProduct], 2);
}
delay(500); // Debounce delay
}
if (menuState == CHANGING_NAME) {
if (digitalRead(changeNameButtonPin) == LOW) {
// Botão de mudança de nome não faz nada neste estado
delay(500); // Debounce delay
}
}
}
}
}