/**
Cofre Eletrônico Arduino
Copyright (C) 2020, Uri Shaked.
Lançado sob a licença MIT.
*/
#include <LiquidCrystal.h>
#include <Keypad.h>
#include <Servo.h>
#include "SafeState.h"
#include "icons.h"
/* Definições do mecanismo de travamento */
#define PINO_SERVO 6
#define POS_TRAVADO 20
#define POS_DESTRAVADO 90
Servo servoTrava;
/* Display */
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
/* Configuração do Keypad */
const byte LINHAS_KEYPAD = 4;
const byte COLUNAS_KEYPAD = 4;
byte pinosLinhas[LINHAS_KEYPAD] = {5, 4, 3, 2};
byte pinosColunas[COLUNAS_KEYPAD] = {A3, A2, A1, A0};
char teclas[LINHAS_KEYPAD][COLUNAS_KEYPAD] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
Keypad teclado = Keypad(makeKeymap(teclas), pinosLinhas, pinosColunas, LINHAS_KEYPAD, COLUNAS_KEYPAD);
/* SafeState armazena o código secreto na EEPROM */
SafeState estadoCofre;
void travar() {
servoTrava.write(POS_TRAVADO);
estadoCofre.lock();
}
void destravar() {
servoTrava.write(POS_DESTRAVADO);
}
void mostrarMensagemInicial() {
lcd.setCursor(4, 0);
lcd.print("Bem-vindo!");
delay(1000);
lcd.setCursor(0, 1);
String mensagem = "ArduinoCofre v1.0";
for (byte i = 0; i < mensagem.length(); i++) {
lcd.print(mensagem[i]);
delay(100);
}
delay(500);
}
String inserirCodigoSecreto() {
lcd.setCursor(5, 1);
lcd.print("[____]");
lcd.setCursor(6, 1);
String resultado = "";
while (resultado.length() < 4) {
char tecla = teclado.getKey();
if (tecla >= '0' && tecla <= '9') {
lcd.print('*');
resultado += tecla;
}
}
return resultado;
}
void mostrarTelaEspera(int delayMillis) {
lcd.setCursor(2, 1);
lcd.print("[..........]");
lcd.setCursor(3, 1);
for (byte i = 0; i < 10; i++) {
delay(delayMillis);
lcd.print("=");
}
}
bool definirNovoCodigo() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Novo código:");
String novoCodigo = inserirCodigoSecreto();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Confirme o código");
String confirmarCodigo = inserirCodigoSecreto();
if (novoCodigo.equals(confirmarCodigo)) {
estadoCofre.setCode(novoCodigo);
return true;
} else {
lcd.clear();
lcd.setCursor(1, 0);
lcd.print("Código errado");
lcd.setCursor(0, 1);
lcd.print("Cofre não travado!");
delay(2000);
return false;
}
}
void mostrarMensagemDestravar() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.write(ICON_UNLOCKED_CHAR);
lcd.setCursor(4, 0);
lcd.print("Destravado!");
lcd.setCursor(15, 0);
lcd.write(ICON_UNLOCKED_CHAR);
delay(1000);
}
void logicaCofreDestravado() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.write(ICON_UNLOCKED_CHAR);
lcd.setCursor(2, 0);
lcd.print(" # p/ travar");
lcd.setCursor(15, 0);
lcd.write(ICON_UNLOCKED_CHAR);
bool novoCodigoNecessario = true;
if (estadoCofre.hasCode()) {
lcd.setCursor(0, 1);
lcd.print(" A = novo código");
novoCodigoNecessario = false;
}
auto tecla = teclado.getKey();
while (tecla != 'A' && tecla != '#') {
tecla = teclado.getKey();
}
bool prontoParaTravar = true;
if (tecla == 'A' || novoCodigoNecessario) {
prontoParaTravar = definirNovoCodigo();
}
if (prontoParaTravar) {
lcd.clear();
lcd.setCursor(5, 0);
lcd.write(ICON_UNLOCKED_CHAR);
lcd.print(" ");
lcd.write(ICON_RIGHT_ARROW);
lcd.print(" ");
lcd.write(ICON_LOCKED_CHAR);
estadoCofre.lock();
travar();
mostrarTelaEspera(100);
}
}
void logicaCofreTravado() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.write(ICON_LOCKED_CHAR);
lcd.print(" Cofre Travado ");
lcd.write(ICON_LOCKED_CHAR);
String codigoUsuario = inserirCodigoSecreto();
bool destravadoComSucesso = estadoCofre.unlock(codigoUsuario);
mostrarTelaEspera(200);
if (destravadoComSucesso) {
mostrarMensagemDestravar();
destravar();
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Acesso Negado!");
mostrarTelaEspera(1000);
}
}
void setup() {
lcd.begin(16, 2);
init_icons(lcd);
servoTrava.attach(PINO_SERVO);
/* Certificar que a trava física está sincronizada com o estado da EEPROM */
Serial.begin(115200);
if (estadoCofre.locked()) {
travar();
} else {
destravar();
}
mostrarMensagemInicial();
}
void loop() {
if (estadoCofre.locked()) {
logicaCofreTravado();
} else {
logicaCofreDestravado();
}
}