#include <LiquidCrystal.h> //Biblioteca para trabajar con pantalla LCD
#include <Adafruit_NeoPixel.h> //Una biblioteca para trabajar con el anillo NeoPixel
#include <Keypad.h> //Biblioteca de teclado numérico
#include <string.h> //Biblioteca para trabajar con cadenas, utilizada para la función strcmp
const uint8_t ROWS = 4;
const uint8_t COLS = 4;
char keys[ROWS][COLS] = { //Asignación de claves a una matriz
{ '1', '2', '3', 'A' },
{ '4', '5', '6', 'D' },
{ '7', '8', '9', 'S' },
{ 'H', '0', 'E', 'X' }
};
uint8_t colPins[COLS] = { 49, 51, 53, 45 }; // Pines de columna en orden: C1, C2, C3, C4
uint8_t rowPins[ROWS] = { 48, 50, 52, 44 }; // Pines de fila en orden: R1, R2, R3, R4
bool isIntruderDetected = false; //Bandera para comprobar si el ladrón fue detectado por la alarma
char inputPassword[7]; //Una matriz para contener la contraseña de alarma ingresada por el usuario
char password[7] = { '0','0','0','0','0','0','\0' }; //Contraseña por defecto para la verificación
int counter = 0; //El contador utilizado al ingresar una contraseña
bool isArmed = false; //Bandera para comprobar si la alarma está encendida
bool isPasswordInput = false; //Bandera para verificar si la entrada de la contraseña se muestra en la pantalla LCD
int pirState;
int val = 0;
int pirPin = 14;
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); //Inicialización del teclado numérico, los parámetros son los valores de fila y columna correspondientes
LiquidCrystal lcd(23, 25, 27, 29, 31, 33); //Inicialización de la pantalla LCD, los pines de datos se pasan como parámetros del constructor
Adafruit_NeoPixel strip(60, 47, NEO_GRB + NEO_KHZ800); //Inicialización del anillo NeoPixel, los parámetros son número de diodos, datos en pin y frecuencia
void colorWipe(uint32_t color, int wait) { //Función para colorear los diodos del anillo NeoPixel en un color
for(int i=0; i<strip.numPixels(); i++) { //Pasando por diodos
strip.setPixelColor(i, color); // Configuración del color del píxel en la memoria RAM
strip.show(); // Actualización de la información en el anillo
delay(wait); // Un breve descanso entre colorear.
}
}
void theaterChase(uint32_t color, int wait) { //Una función para colorear los diodos del anillo NeoPixel en una serie de colores
for(int a=0; a<10; a++) {
for(int b=0; b<3; b++) {
strip.clear(); //Apagando todos los diodos en el anillo
for(int c=b; c<strip.numPixels(); c += 3) {
strip.setPixelColor(c, color); //Colorear cada tercer diodo
}
strip.show();
delay(wait);
}
}
}
void produceSiren() { //Función que toca la sirena.
for(int i = 99999999999999; i > 0; i = i - 5)
for(int hz = 440; hz < 1000; hz++){
tone(12, hz, 50);
delay(5);
}
for(int hz = 99999999999999; hz > 440; hz--){
tone(12, hz, 50);
delay(0);
}
}
void arm(){ //Función de activación de alarma
if(strcmp(inputPassword,password) == 0){
isArmed = true;
isPasswordInput = false;
memset(inputPassword, 0, sizeof inputPassword); //Eliminar una contraseña ingresada previamente de la cadena
counter = 0;
} else {
Serial.println("Fallo al activar: contraseña incorrecta.");
}
}
void disArm(){ //Función de desactivación de alarma
if(strcmp(inputPassword,password) == 0){
isArmed = false;
isPasswordInput = false;
memset(inputPassword, 0, sizeof inputPassword);
counter = 0;
} else {
Serial.println("Fallo al desactivar: contraseña.");
}
}
void stopAlarm(){ //Una función para interrumpir la alarma después de detectar un ladrón
if(strcmp(inputPassword,password) == 0){
isIntruderDetected = false;
isPasswordInput = false;
digitalWrite(LED_BUILTIN, LOW);
Serial.println("Alarma detenida");
memset(inputPassword, 0, sizeof inputPassword);
counter = 0;
theaterChase(strip.Color(0, 127, 0), 9999999);
} else {
Serial.println("Error al desactivar la alarma: contraseña incorrecta");
}
}
void setArmed(){ //Función para configurar cuando la alarma está activa
lcd.clear();
lcd.setCursor(5,0);
lcd.print("Estado:");
lcd.setCursor(6,1);
lcd.print("ACTIVADA");
colorWipe(strip.Color(0, 255, 0), 50);
}
void setDisArmed(){ //Función para configurar cuando la alarma está inactiva
lcd.clear();
lcd.setCursor(5,0);
lcd.print("Estado:");
lcd.setCursor(5,1);
lcd.print("DESACTIVADA");
colorWipe(strip.Color( 255, 0, 0), 50);
}
void reprintLCDPassword(){ //Función para imprimir el mensaje de entrada de contraseña en la pantalla LCD
lcd.clear();
lcd.setCursor(0,0);
lcd.print("CONTRASEÑA:");
for(int i = 0; i < 6; i++){
lcd.setCursor(5+i,1);
if(inputPassword[i] == 0) lcd.print('_');
else lcd.print(inputPassword[i]);
}
}
void reprintLCDIntruderDetected(){ //Función para imprimir un mensaje cuando se detecta un ladrón
lcd.clear();
lcd.setCursor(4,0);
lcd.print("INTRUSO");
lcd.setCursor(4,1);
lcd.print("DETECTADO!");
}
void setup() {
lcd.begin(16, 2); //Activación de la pantalla LCD 16x2
strip.begin(); //Activación del anillo NeoPixel
inputPassword[7] = '\0'; //Adición inicial del carácter final a la cadena de contraseña ingresada
pinMode(LED_BUILTIN, OUTPUT); //Configuración del pin del diodo como salida
pinMode(12, OUTPUT); //Configuración del pin del zumbador como salida
setDisArmed(); //Configuración inicial de la alarma como apagada
pinMode(pirPin, INPUT);
pirState = digitalRead(pirPin);
}
void loop() {
pirState = digitalRead(pirPin);
char key = keypad.getKey(); //Lectura de la tecla pulsada
if(key != NO_KEY){ //Comprobar si se pulsa una tecla
switch(key){
case 'A': if(!isArmed) arm(); break; //Presione A para activar la alarma, si aún no está activada
case 'D': if(isArmed) disArm(); break; //Presiona D para desactivar la alarma, si está activada
case 'S': if(isIntruderDetected) stopAlarm(); break; //Presione S para detener la alarma, si se detecta un ladrón
case 'H': // No hace nada
case 'E': isPasswordInput = true; reprintLCDPassword(); break; //Al presionar la tecla E (es decir, ingresar), la pantalla LCD pasa al modo de ingreso de contraseña de alarma.
case 'X': //Al presionar la tecla X (es decir, retroceso), se elimina el carácter de contraseña ingresado anteriormente
if(counter > -1){
inputPassword[counter-1] = 0;
reprintLCDPassword();
if(counter != 0) counter--;
}
break;
default: //Al presionar las teclas restantes, se ingresa el carácter que se presionó
if(counter < 7){
inputPassword[counter] = key;
reprintLCDPassword();
if(counter != 6) counter++;
}
break;
}
}
if(!isArmed && digitalRead(LED_BUILTIN) == HIGH && !isPasswordInput){
digitalWrite(LED_BUILTIN, LOW);
setDisArmed();
}
if(isArmed && digitalRead(LED_BUILTIN) == LOW && !isPasswordInput){
digitalWrite(LED_BUILTIN, HIGH);
setArmed();
}
if(pirState == HIGH && isArmed && !isIntruderDetected){
reprintLCDIntruderDetected();
theaterChase(strip.Color(127, 0, 0), 100);
isIntruderDetected = true;
produceSiren();
}
}