//Nome: Jussara Miliano Soares
//Projeto 0407 - Sistema de Acesso
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <Servo.h>
#include <Wire.h>
#include <MPU6050.h>
//Pinos utilizados
#define SERVO_PIN 10
#define BUZZER_PIN 11
#define LED_ORANGE_PIN 12
#define LED_BLUE_PIN 13
#define LED_RED_PIN A0
// Configuracao do LCD I2C
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Configuracao do keypad
const byte ROWS = 4;
const byte COLS = 4;
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};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Configuracao do servo motor
Servo servoMotor;
// Configuracao do sensor MPU6050
MPU6050 mpu;
// Estados
enum State {
STATE_IDLE,
STATE_AUTH,
STATE_VERIFY,
STATE_MOTION_CHECK,
STATE_UNLOCK
};
// Variaveis
State currentState = STATE_IDLE;
String inputPassword = "";
const String correctPassword = "1234";
unsigned long stateTimer = 0;
unsigned long motionCheckStartTime = 0;
const unsigned long MOTION_CHECK_DURATION = 2000; // milisegundos - 2 segundos
const unsigned long UNLOCK_DURATION = 5000; // 5 segundos
const float MOTION_THRESHOLD = 1.5; // Limite de movimento (g)
// Variáveis para o MPU6050
int16_t ax, ay, az;
int16_t gx, gy, gz;
float axG, ayG, azG;
void setup() {
Serial.begin(9600);
// Start do LCD
lcd.init();
lcd.backlight();
// Start dos LEDs e Buzzer
pinMode(LED_ORANGE_PIN, OUTPUT);
pinMode(LED_BLUE_PIN, OUTPUT);
pinMode(LED_RED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
// Start do servo
servoMotor.attach(SERVO_PIN);
servoMotor.write(0); // Fechado na posicao inicial
// Start do MPU6050
Wire.begin();
mpu.initialize();
if (mpu.testConnection()) {
Serial.println("MPU6050 conectado");
} else {
Serial.println("Erro ao conectar MPU6050!");
}
// Apagar todos os LEDs
digitalWrite(LED_ORANGE_PIN, LOW);
digitalWrite(LED_BLUE_PIN, LOW);
digitalWrite(LED_RED_PIN, LOW);
// Estado inicial
enterIdleState();
}
//switch-case dos estados
void loop() {
char key = keypad.getKey();
switch (currentState) {
case STATE_IDLE:
handleIdleState(key);
break;
case STATE_AUTH:
handleAuthState(key);
break;
case STATE_VERIFY:
handleVerifyState();
break;
case STATE_MOTION_CHECK:
handleMotionCheckState();
break;
case STATE_UNLOCK:
handleUnlockState();
break;
}
}
void enterIdleState() {
currentState = STATE_IDLE;
inputPassword = "";
digitalWrite(LED_ORANGE_PIN, LOW);
digitalWrite(LED_BLUE_PIN, LOW);
digitalWrite(LED_RED_PIN, LOW);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Acesso restrito");
lcd.setCursor(0, 1);
lcd.print("Pressione *");
Serial.println("Estado atual: STATE_IDLE");
}
void handleIdleState(char key) {
if (key == '*') {
enterAuthState();
}
}
void enterAuthState() {
currentState = STATE_AUTH;
inputPassword = "";
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Digite a senha:");
lcd.setCursor(0, 1);
lcd.print("____");
Serial.println("Estado atual: STATE_AUTH");
}
void handleAuthState(char key) {
if (key && key != '*' && key != '#' && key != 'A' && key != 'B' && key != 'C' && key != 'D') {
if (inputPassword.length() < 4) {
inputPassword += key;
// Atualizar display
lcd.setCursor(inputPassword.length() - 1, 1);
lcd.print('*');
// verificando senha apos 4 digitos
if (inputPassword.length() == 4) {
delay(500); // Pequena pausa para visualizacao
enterVerifyState();
}
}
}
// Cancelar com '#' e volta para o estado Idle
//if (key == '#') {
//enterIdleState();
//}
}
void enterVerifyState() {
currentState = STATE_VERIFY;
Serial.println("Estado atual: STATE_VERIFY");
Serial.println("Senha digitada: " + inputPassword);
}
void handleVerifyState() {
if (inputPassword == correctPassword) {
// Senha correta
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Senha correta!");
lcd.setCursor(0, 1);
lcd.print("Verificando...");
delay(1000);
enterMotionCheckState();
} else {
// Senha incorreta
digitalWrite(LED_RED_PIN, HIGH);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Acesso negado");
lcd.setCursor(0, 1);
lcd.print("Senha incorreta");
// Buzzer de erro
tone(BUZZER_PIN, 1000, 500);
delay(2000);
digitalWrite(LED_RED_PIN, LOW);
enterIdleState();
}
}
void enterMotionCheckState() {
currentState = STATE_MOTION_CHECK;
motionCheckStartTime = millis();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Fique parado!");
lcd.setCursor(0, 1);
lcd.print("Verificando...");
Serial.println("Estado atual: STATE_MOTION_CHECK");
}
void handleMotionCheckState() {
unsigned long currentTime = millis();
if (currentTime - motionCheckStartTime >= MOTION_CHECK_DURATION) {
// Verificacao de movimento concluida
if (isOperatorStill()) {
// Operador parado
enterUnlockState();
} else {
// Operador em movimento
digitalWrite(LED_ORANGE_PIN, HIGH);
digitalWrite(LED_RED_PIN, HIGH);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Acesso negado");
lcd.setCursor(0, 1);
lcd.print("Em movimento!");
// Buzzer de alerta
tone(BUZZER_PIN, 800, 1000);
delay(2000);
digitalWrite(LED_ORANGE_PIN, LOW);
digitalWrite(LED_RED_PIN, LOW);
enterIdleState();
}
} else {
// Continuar verificando movimento
checkMotion();
}
}
bool isOperatorStill() {
// Leitursa do valores do MPU6050
int samples = 10;
float totalAcceleration = 0;
for (int i = 0; i < samples; i++) {
mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
axG = ax / 16384.0;
ayG = ay / 16384.0;
azG = az / 16384.0;
float magnitude = sqrt(axG*axG + ayG*ayG + azG*azG);
totalAcceleration += abs(magnitude - 1.0);
delay(50);
}
float averageAcceleration = totalAcceleration / samples;
Serial.print("Aceleracao media: ");
Serial.println(averageAcceleration);
return averageAcceleration < MOTION_THRESHOLD;
}
void checkMotion() {
mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
// Converter para g
axG = ax / 16384.0;
ayG = ay / 16384.0;
azG = az / 16384.0;
// Calcular magnitude da aceleracao
float magnitude = sqrt(axG*axG + ayG*ayG + azG*azG);
float motion = abs(magnitude - 1.0); // Subtrair 1g da gravidade
// Acender LED laranja se detectar movimento alto
if (motion > MOTION_THRESHOLD) {
digitalWrite(LED_ORANGE_PIN, HIGH);
tone(BUZZER_PIN, 500, 100);
} else {
digitalWrite(LED_ORANGE_PIN, LOW);
}
}
void enterUnlockState() {
currentState = STATE_UNLOCK;
stateTimer = millis();
digitalWrite(LED_BLUE_PIN, HIGH);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Acesso liberado!");
lcd.setCursor(0, 1);
lcd.print("Bem-vindo!");
// Movimentacao do servo para posicao aberta
servoMotor.write(90);
// Som de liberacao
tone(BUZZER_PIN, 1500, 200);
delay(300);
tone(BUZZER_PIN, 2000, 200);
Serial.println("Estado atual: STATE_UNLOCK");
}
void handleUnlockState() {
if (millis() - stateTimer >= UNLOCK_DURATION) {
// Retornar servo para posicao fechada
servoMotor.write(0);
digitalWrite(LED_BLUE_PIN, LOW);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Acesso fechado");
delay(1000);
enterIdleState();
} else {
// Mostrar tempo restante
unsigned long timeLeft = (UNLOCK_DURATION - (millis() - stateTimer)) / 1000;
lcd.setCursor(0, 1);
lcd.print("Tempo: ");
lcd.print(timeLeft);
lcd.print("s ");
}
}