#include <SPI.h>
#include <MFRC522.h>
#include <LiquidCrystal.h>
#define SS_PIN 10
#define RST_PIN 9
#define CLK_PIN 2
#define DT_PIN 3
#define SW_PIN 4
LiquidCrystal lcd(5, 6, 7, 8, A3, A4);
#define LED_VERMELHO A0
#define LED_VERDE A1
#define BUZZER_PIN A2
MFRC522 rfid(SS_PIN, RST_PIN);
enum Estado {
DESLIGADO,
LOOP_INICIAL,
AJUSTANDO_TEMPO,
CONTAGEM_REGRESSIVA,
MENU_CONTAGEM,
TEMPO_ESGOTADO,
CONFIRMACAO_PRESENCA,
ATE_MAIS
};
Estado estadoAtual = DESLIGADO;
int tempoSelecionadoMin = 0;
long tempoRestanteSegundos = 0;
unsigned long ultimoSegundo = 0;
unsigned long tempoEstado = 0;
unsigned long ultimaInteracao = 0;
unsigned long trocaMensagem = 0;
unsigned long ultimoBuzzer = 0;
bool mensagemBemVindo = true;
bool buzzerLigado = false;
bool respostaPresenca = true;
bool opcaoMenuContagem = true;
int ultimoCLK = HIGH;
void atualizarLEDs() {
if (estadoAtual == DESLIGADO) {
digitalWrite(LED_VERMELHO, HIGH);
digitalWrite(LED_VERDE, LOW);
}
else {
digitalWrite(LED_VERMELHO, LOW);
digitalWrite(LED_VERDE, HIGH);
}
}
void mostrarDesligado() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Aproxime o cartao");
lcd.setCursor(0, 1);
lcd.print("para iniciar");
}
void mostrarBemVindo() {
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Bem vindo!");
}
void mostrarQuantoTempo() {
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Quanto tempo vais");
lcd.setCursor(0, 2);
lcd.print("ficar aqui?");
}
void mostrarTempoSelecionado() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Tempo escolhido:");
lcd.setCursor(0, 1);
lcd.print(tempoSelecionadoMin);
lcd.print(" min");
lcd.setCursor(0, 3);
lcd.print("Aperte p/ OK");
}
void mostrarTempoRestante() {
lcd.clear();
long horas = tempoRestanteSegundos / 3600;
long minutos = (tempoRestanteSegundos % 3600) / 60;
long segundos = tempoRestanteSegundos % 60;
lcd.setCursor(0, 0);
lcd.print("Tempo restante");
lcd.setCursor(0, 2);
if (horas < 10) lcd.print("0");
lcd.print(horas);
lcd.print(":");
if (minutos < 10) lcd.print("0");
lcd.print(minutos);
lcd.print(":");
if (segundos < 10) lcd.print("0");
lcd.print(segundos);
}
void mostrarMenuContagem() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Deseja alterar o");
lcd.setCursor(0, 1);
lcd.print("tempo informado");
lcd.setCursor(0, 2);
lcd.print("ou sair?");
lcd.setCursor(0, 3);
if (opcaoMenuContagem)
lcd.print("Alterar tempo");
else
lcd.print("Sair");
}
void mostrarTempoEsgotado() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Ainda esta aqui?");
lcd.setCursor(0, 1);
lcd.print("Vai permanecer");
lcd.setCursor(0, 2);
lcd.print("ou vai sair?");
lcd.setCursor(0, 3);
lcd.print("Permanecer");
}
void mostrarPresenca() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Ainda esta aqui?");
lcd.setCursor(0, 1);
lcd.print("Vai permanecer");
lcd.setCursor(0, 2);
lcd.print("ou vai sair?");
lcd.setCursor(0, 3);
if (respostaPresenca)
lcd.print("Permanecer");
else
lcd.print("Sair");
}
void mostrarAteMais() {
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Ate mais!");
}
void irParaDesligado() {
estadoAtual = DESLIGADO;
noTone(BUZZER_PIN);
buzzerLigado = false;
atualizarLEDs();
mostrarDesligado();
}
bool cartaoRFIDLido() {
if (!rfid.PICC_IsNewCardPresent())
return false;
if (!rfid.PICC_ReadCardSerial())
return false;
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
return true;
}
int lerEncoderPasso() {
int clkAtual = digitalRead(CLK_PIN);
int passo = 0;
if (clkAtual != ultimoCLK && clkAtual == LOW) {
if (digitalRead(DT_PIN) != clkAtual)
passo = 1;
else
passo = -1;
}
ultimoCLK = clkAtual;
return passo;
}
bool botaoEncoderPressionado() {
static int leituraAnterior = HIGH;
static int estadoEstavel = HIGH;
static unsigned long ultimaMudanca = 0;
bool pressionou = false;
int leitura = digitalRead(SW_PIN);
if (leitura != leituraAnterior)
ultimaMudanca = millis();
if (millis() - ultimaMudanca > 35) {
if (leitura != estadoEstavel) {
estadoEstavel = leitura;
if (estadoEstavel == LOW)
pressionou = true;
}
}
leituraAnterior = leitura;
return pressionou;
}
void setup() {
pinMode(CLK_PIN, INPUT_PULLUP);
pinMode(DT_PIN, INPUT_PULLUP);
pinMode(SW_PIN, INPUT_PULLUP);
pinMode(LED_VERMELHO, OUTPUT);
pinMode(LED_VERDE, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
lcd.begin(20, 4);
SPI.begin();
rfid.PCD_Init();
atualizarLEDs();
mostrarDesligado();
}
void loop() {
int passoEncoder = lerEncoderPasso();
bool botao = botaoEncoderPressionado();
if (passoEncoder != 0 || botao) {
ultimaInteracao = millis();
}
atualizarLEDs();
switch (estadoAtual) {
case DESLIGADO:
if (cartaoRFIDLido()) {
estadoAtual = LOOP_INICIAL;
ultimaInteracao = millis();
trocaMensagem = millis();
mensagemBemVindo = true;
mostrarBemVindo();
}
break;
case LOOP_INICIAL:
if (millis() - ultimaInteracao >= 60000) {
irParaDesligado();
break;
}
if (mensagemBemVindo &&
millis() - trocaMensagem >= 2000) {
mensagemBemVindo = false;
trocaMensagem = millis();
mostrarQuantoTempo();
}
else if (!mensagemBemVindo &&
millis() - trocaMensagem >= 5000) {
mensagemBemVindo = true;
trocaMensagem = millis();
mostrarBemVindo();
}
if (passoEncoder != 0) {
tempoSelecionadoMin = 0;
if (passoEncoder > 0)
tempoSelecionadoMin = 1;
estadoAtual = AJUSTANDO_TEMPO;
mostrarTempoSelecionado();
}
break;
case AJUSTANDO_TEMPO:
if (millis() - ultimaInteracao >= 60000) {
estadoAtual = LOOP_INICIAL;
trocaMensagem = millis();
mensagemBemVindo = true;
mostrarBemVindo();
break;
}
if (passoEncoder != 0) {
tempoSelecionadoMin += passoEncoder;
if (tempoSelecionadoMin < 0)
tempoSelecionadoMin = 0;
if (tempoSelecionadoMin > 120)
tempoSelecionadoMin = 120;
mostrarTempoSelecionado();
}
if (botao) {
tempoRestanteSegundos =
(long)tempoSelecionadoMin * 60L;
estadoAtual = CONTAGEM_REGRESSIVA;
ultimoSegundo = millis();
mostrarTempoRestante();
}
break;
case CONTAGEM_REGRESSIVA:
if (passoEncoder != 0) {
opcaoMenuContagem = true;
estadoAtual = MENU_CONTAGEM;
mostrarMenuContagem();
break;
}
if (millis() - ultimoSegundo >= 1000) {
ultimoSegundo = millis();
if (tempoRestanteSegundos > 0) {
tempoRestanteSegundos--;
mostrarTempoRestante();
}
else {
estadoAtual = TEMPO_ESGOTADO;
tempoEstado = millis();
ultimoBuzzer = millis();
mostrarTempoEsgotado();
}
}
break;
case MENU_CONTAGEM:
if (passoEncoder != 0) {
opcaoMenuContagem = !opcaoMenuContagem;
mostrarMenuContagem();
}
if (botao) {
if (opcaoMenuContagem) {
tempoSelecionadoMin =
(tempoRestanteSegundos + 59) / 60;
estadoAtual = AJUSTANDO_TEMPO;
mostrarTempoSelecionado();
}
else {
estadoAtual = ATE_MAIS;
tempoEstado = millis();
mostrarAteMais();
}
}
break;
case TEMPO_ESGOTADO:
if (millis() - tempoEstado >= 60000) {
irParaDesligado();
break;
}
if (millis() - ultimoBuzzer >= 1000) {
ultimoBuzzer = millis();
buzzerLigado = !buzzerLigado;
if (buzzerLigado)
tone(BUZZER_PIN, 1000);
else
noTone(BUZZER_PIN);
}
if (passoEncoder != 0) {
noTone(BUZZER_PIN);
buzzerLigado = false;
respostaPresenca = false;
estadoAtual = CONFIRMACAO_PRESENCA;
mostrarPresenca();
}
break;
case CONFIRMACAO_PRESENCA:
if (passoEncoder != 0) {
respostaPresenca = !respostaPresenca;
mostrarPresenca();
}
if (botao) {
if (respostaPresenca) {
tempoSelecionadoMin = 0;
estadoAtual = AJUSTANDO_TEMPO;
mostrarTempoSelecionado();
}
else {
estadoAtual = ATE_MAIS;
tempoEstado = millis();
mostrarAteMais();
}
}
break;
case ATE_MAIS:
if (millis() - tempoEstado >= 60000) {
irParaDesligado();
}
break;
}
}