#include <EEPROM.h>
#include <Wire.h>
const int EEPROM_SIZE = 5; // Tamaño de la memoria EEPROM para almacenar la contraseña (incluyendo el carácter nulo al final)
char dataToWrite[EEPROM_SIZE]= "1234";
bool passwordChanged = false; //mi banderota
int minumero, attempts=0;
int numerosecreto = 1234;
String datos;
#define ledexterno 19
int contador=0;
int contador1=0;
#define cerradura 2
int tecla2=0;
int blocked = 5;
int puntis = 1;
int ren[] = {27, 14, 12, 13}; // Pines para los renglones
int colum[] = {32, 33, 25, 26}; // Pines para las columnas
byte johnson;
byte tecla;
byte col = 0x0F;
byte PCF_addr = 0x27; // Dirección para la LCD
byte uni = 0;
byte dec = 0;
byte cen = 0;
byte miles= 0;
int boton;
bool teclaActiva = 0;
bool rw = 0; // LCD
bool rs; // LCD
bool LED = 1; // LCD
char conf[] = {3, 3, 3, 2, 2, 8, 0, 14, 0, 0x0F, 1, 0, 6}; // Configuración para la LCD
char tiempos[] = {15, 5, 1, 1, 1, 1, 1, 1};
char msj1[] = {"clave: "}; // Para la LCD
char msj2[] = {"BIENVENIDO "}; // Para LCD
char msj3[] = {"Ingrese su "};
char msj4[]= {"Puerta abierta "};
char msj5[]= {"codigo erroneo "};
char msj6[]={"BLOQUEADO " };
char msj7[]={"Entre "};
char msj8[]={"Cerrando puerta "};
char msj10[]={"Ingresa la "};
char msj11[]={"nueva clave "};
char msj12[]={"Actualizada "};
hw_timer_t *timer = NULL; // Inicializador del timer para el contador Johnson
void cnt_johnson() {
col = (digitalRead(colum[3]) << 3) | (digitalRead(colum[2]) << 2) | (digitalRead(colum[1]) << 1) | digitalRead(colum[0]);
if (col == 0x0F) {
byte m, j, i;
teclaActiva = 0;
johnson = (johnson << 1) | 0x01;
// Regresar el contador Johnson a su valor inicial
if (johnson == 0xEF)
johnson = 0xFE;
m = 3;
for (i = 0; i <= 3; i++) {
j = pow(2, m);
digitalWrite(ren[i], (johnson & j));
m--;
}
}
}
void send_byte(char N) {
byte carac = N >> 4;
send_Nibble(carac, LED, rw, rs);
send_Nibble(N, LED, rw, rs);
}
void send_Nibble(byte N, byte L, byte W, byte S) {
byte dato = (N << 4) | (L << 3) | 0x04 | (W << 2) | S;
Wire.beginTransmission(PCF_addr);
Wire.write(dato);
Wire.endTransmission();
delay(10);
dato = dato & 0xFB;
Wire.beginTransmission(PCF_addr);
Wire.write(dato);
Wire.endTransmission();
}
void setup() {
Serial.begin(9600);
pinMode(cerradura, OUTPUT); // Configura el pin del LED como salida
pinMode(ledexterno, OUTPUT); // Configura el pin del LED como salida
for (byte i = 0; i <= 3; i++) {
pinMode(ren[i], OUTPUT);
pinMode(colum[i], INPUT_PULLUP);
}
johnson = 0xFE;
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, cnt_johnson, true);
timerAlarmWrite(timer, 20000, true);
timerAlarmEnable(timer);
Wire.begin();
rs = 0;
for (byte i = 0; i <= 11; i++) {
delay(tiempos[i]);
send_Nibble(conf[i], LED, rs, rw);
}
//incializar la memoria flash
EEPROM.begin(EEPROM_SIZE);
//escribir en la memoria flash-----------------
Serial.println("escribiendo en la memoria flash");
for (int i = 0; i < EEPROM_SIZE; ++i) {
EEPROM.write(i, dataToWrite[i]);
}
EEPROM.commit(); // Guardar los datos en la EEPROM
Serial.println("Datos escritos en la EEPROM.");
for (int i = 0; i < EEPROM_SIZE; ++i) {
dataToWrite[i] = EEPROM.read(i);
Serial.print(dataToWrite[i]);
}
//----------------------------------------------
send_byte(0x80);
rs = 1;
for (byte i = 0; i <= 10; i++) {
send_byte(msj2[i]);
}
rs=0;
send_byte(0xc0);
points(puntis);
rs = 0;
rs = 0;
send_byte(0x80);
rs=1;
for (byte i = 0; i <= 10; i++) {
send_byte(msj3[i]);
}
rs = 1;
for (byte i = 0; i <= 6; i++) {
send_byte(msj1[i]);
}
rs=0;
send_byte(0xc0);
}
// Funcion para mostrar caracteres en vez de delays feos...
void points(int cantidad) {
char punticos[] = {". . . "};
char renglones[]= {"- - -"};
for (int i = 0; i < cantidad; i++) {
rs = 1;
for (byte j = 0; j <= 5; j++) {
send_byte(punticos[j]);
delay(400);
}
delay(10);
rs = 0;
//send_byte(0x01);//borrar todo
delay(1);
send_byte(0xc0);//primera linea
rs=1;
for (byte j = 0; j <= 4; j++) {
send_byte(renglones[j]);
delay(400);
}
rs=0;
send_byte(0x01); //borrar todo.
}
}
void loop() {
if (col != 0x0f) {// Verifica si la variable col no es igual a 0x0f (15 en decimal).
if (teclaActiva == 0) { //Verifica si la variable teclaActiva es igual a 0.
teclaActiva = 1;
byte rengcol = (johnson << 4) | col;
switch (rengcol) { //inicializar los casos
case 0b11101110: // La letra A funciona como nuestro botón de enter
char buffer[5];//almacenar en buffer
boton= (miles*1000)+(cen*100)+(dec*10)+uni; //alamcenar en boton los valores en el teclado
itoa(boton,buffer,10); //convertir de entero a caracteres...
Serial.print("La contrasena escrita es:");
Serial.println(boton);
if (strcmp(buffer,dataToWrite) ==0 ) { // si la contrasena es igual a la ya registrada entonces iniciar el proceso
attempts = 0; //reiniciar el contador del bloqueo
rs = 0;
send_byte(0x01); // Borrar todo
send_byte(0x80); // Posicionarse en el primer renglón, primera línea
rs = 1;
//mostrar mensajesss
for (byte i = 0; i <= 14; i++) {
send_byte(msj4[i]);
delay(10);
}
delay(3000);
rs = 0;
send_byte(0x01); // Borrar todo
send_byte(0x80); // Posicionarse en el primer renglón, primera línea
rs=1;
for (byte i = 0; i <= 5; i++) {
send_byte(msj7[i]);
delay(1);
}
delay(3000);
rs = 0;
send_byte(0xc0);
rs=1;
for (byte i = 0; i <= 15; i++) {
send_byte(msj8[i]);
delay(200);
}
digitalWrite(cerradura, LOW);
rs = 0;
send_byte(0x80);
rs = 1;
for (byte i = 0; i <= 10; i++) {
send_byte(msj3[i]);
}
rs = 0;
send_byte(0xc6);
rs = 1;
for (byte i = 0; i <= 6; i++) {
send_byte(msj1[i]);
}
rs=0;
send_byte(0xc0);
rs = 1;
for (byte i = 0; i <= 15; i++) {
send_byte(0x20);
delay(10);
}
rs = 0;
send_byte(0xc6);
rs = 1;
for (byte i = 0; i <= 6; i++) {
send_byte(msj1[i]);
}
rs = 0;
send_byte(0xc0); //enviar cursor al segundo renglon...
//reinciar valores en el teclado....
miles=0;
cen=0;
dec=0;
uni=0;
}
// si la contrasena no coincide con la actual, entonces se inicia
else {
digitalWrite(ledexterno,HIGH);
delay(100);
digitalWrite(ledexterno,LOW);
attempts++; // aumentar contador de bloqueos
if (attempts == 3) { // si el contador de bloqueos llega a 3, incia el proceso de bloqueo...
rs = 0;
send_byte(0xC0);
//mostrando mensjaes y moviendo cursor...
rs = 0;
send_byte(0x80);
rs = 1;
for (byte i = 0; i <= 15; i++) {
send_byte(0x20);
delay(70);
}
rs=0;
send_byte(0xC0);
rs=1;
for (byte i = 0; i <= 15; i++) {
send_byte(0x20);
delay(60);
}
rs = 0;
send_byte(0x80);
rs=1;
for (byte i = 0; i <= 9; i++) {
send_byte(msj6[i]);
}
delay(1000);
rs=0;
send_byte(0x01);
send_byte(0x80);
points(blocked); // Llama a la función de animación con los caracteres y una duración de 10 segundos
attempts = 0;
rs = 0;
send_byte(0x80);
rs = 1;
for (byte i = 0; i <= 10; i++) {
send_byte(msj3[i]);
}
rs = 0;
send_byte(0xc6);
rs = 1;
for (byte i = 0; i <= 6; i++) {
send_byte(msj1[i]);
}
rs=0;
send_byte(0xc0);
//reinciciar los valores
miles=0;
cen=0;
dec=0;
uni=0;
} else {rs = 0;
digitalWrite(ledexterno,HIGH);
delay(100);
digitalWrite(ledexterno,LOW);
// realizar barrido para que se vea cool...
send_byte(0xC0);
rs = 1;
for (byte i = 0; i <= 15; i++) {
send_byte(0x20);
delay(10);
}
//reposicionar y mostrar mensajes...
rs=0;
send_byte(0xC0);
rs=1;
for (byte i = 0; i <= 14; i++) {
send_byte(msj5[i]);
delay(350);
}
rs = 0;
send_byte(0x80);
rs=1;
for (byte i = 0; i <= 15; i++) {
send_byte(0x20);
delay(10);
}
rs = 0;
send_byte(0xC0);
rs = 1;
for (byte i = 0; i <= 15; i++) {
send_byte(0x20);
delay(10);
}
rs = 0;
rs = 0;
send_byte(0x80);
rs=1;
for (byte i = 0; i <= 10; i++) {
send_byte(msj3[i]);
}
rs = 1;
for (byte i = 0; i <= 6; i++) {
send_byte(msj1[i]);
}
//reinciar los valores.
miles=0;
cen=0;
dec=0;
uni=0;
//reposicionar cursor en la seg. linea
rs = 0;
send_byte(0xC0);
}
}
break;
case 0b11101101: // Número 3
miles= cen;
cen = dec;
dec = uni;
uni = 0x03;
break;
case 0b11101011: // Número 2
miles = cen;
cen = dec;
dec = uni;
uni = 0x02;
break;
case 0b11100111: // Número 1
miles = cen;
cen = dec;
dec = uni;
uni = 0x01;
break;
case 0b11011110: // Letra B
tecla2 = tecla2 +1; //aumentar contador de eventos en 1 si la tecla B es presionada
char buffer2[5]; // declarar arreglo de caracteres ....
boton= (miles*1000)+(cen*100)+(dec*10)+uni; // volver a adquirir las variables en un solo integer.//
itoa(boton,buffer2,10); //convertir de integer a caracteres y almacenarlos en buffer
Serial.print("La contrasena escrita es:");
Serial.println(boton);
if (strcmp(buffer2,dataToWrite) ==0 ) { // si la buffer es igual a la contrasena actual, se inicia el evento de cambio de contrasena
passwordChanged = true;// bandera
digitalWrite(cerradura, HIGH);
delay(500);
digitalWrite(cerradura, LOW);
rs = 0;
send_byte(0x01); // Borrar todo
send_byte(0x80); // Posicionarse en el primer renglón, primera línea
rs=1;
for (byte i = 0; i <= 10; i++) {
send_byte(msj10[i]);
delay(1);
}
rs = 0;
send_byte(0xc0);
rs=1;
for (byte i = 0; i <= 11; i++) {
send_byte(msj11[i]);
delay(1);
}
delay(3000);
rs = 0;
send_byte(0x01); // Borrar todo
send_byte(0x80); // Posicionarse en el primer renglón, primera línea
rs=1;
for (byte i = 0; i <= 11; i++) {
send_byte(msj11[i]);
delay(1);}
}
Serial.println(passwordChanged);
Serial.println(tecla2);
if ( tecla2 >= 3 && passwordChanged == true) { //verificar que los eventos hayan ocurrido para empezar con el cambio de contreasena
Serial.println(contador);
Serial.println(passwordChanged);
tecla2 =0;
passwordChanged = false;
//reiniciar contador de eventos
char buffer3[6]; // Tamaño 6 para incluir el carácter nulo '\0'
itoa(boton, buffer3, 10);
// Copiar cada carácter del buffer3 a dataToWrite
for (int i = 0; i < EEPROM_SIZE; ++i) {
dataToWrite[i] = buffer3[i];
}
// Escribir los datos en la EEPROM
for (int i = 0; i < EEPROM_SIZE; ++i) {
EEPROM.write(i, dataToWrite[i]);
}
EEPROM.write(EEPROM_SIZE, '\0'); // Escribir el carácter nulo al final de la cadena
EEPROM.commit();
Serial.print("Tu nueva contrasena es: ");
for (int i = 0; i < EEPROM_SIZE; ++i) {
dataToWrite[i] = EEPROM.read(i); // leer de localidad a localidad de memoria el contenido de esta
Serial.print(dataToWrite[i]); // imprimir en serial la nueva contrasena
}
//reposcicionar cursor y enviar mensajes...
rs=0;
send_byte(0x80);
rs = 1;
for (byte i = 0; i <= 6; i++) {
send_byte(msj1[i]);
}
rs=0;
send_byte(0x85);
rs = 1;
for (byte i = 0; i <= 12; i++) {
send_byte(msj12[i]);
} rs = 0;
send_byte(0x80);
rs = 1;
for (byte i = 0; i <= 15; i++) {
send_byte(0x20); }
rs = 0;
send_byte(0x80);
rs=1;
for (byte i = 0; i <= 10; i++) {
send_byte(msj3[i]);
}
rs = 1;
for (byte i = 0; i <= 6; i++) {
send_byte(msj1[i]);
}
rs=0;
send_byte(0xc0);
passwordChanged = false;
attempts=0;
}
if (strcmp(buffer2, dataToWrite) != 0) { // si el buffer es dif a la contrasena actual entonces inciar con los eventos..
attempts++;
tecla2=0;
Serial.println("ADVERTENCIA, ATTEMPT A AUMENTADO");
digitalWrite(ledexterno,HIGH);
delay(100);
digitalWrite(ledexterno,LOW);
if (attempts == 3) {
rs = 0;
send_byte(0xC0);
rs = 1;
for (byte i = 0; i <= 9; i++) {
send_byte(msj6[i]);
}
delay(1000);
rs=0;
send_byte(0x01);
send_byte(0x80);
points(blocked); // Llama a la función de animación con los caracteres y una duración de 10 segundos
attempts = 0;
rs = 0;
send_byte(0x80);
rs = 1;
for (byte i = 0; i <= 10; i++) {
send_byte(msj3[i]);
}
rs = 1;
for (byte i = 0; i <= 6; i++) {
send_byte(msj1[i]);
}
rs=0;
send_byte(0xc0);
miles=0;
cen=0;
dec=0;
uni=0;
} else {
digitalWrite(ledexterno,HIGH);
delay(100);
digitalWrite(ledexterno,LOW);
rs = 0;
send_byte(0xC0);
rs = 1;
for (byte i = 0; i <= 15; i++) {
send_byte(0x20);
delay(10);
}
rs=0;
send_byte(0xC0);
rs=1;
for (byte i = 0; i <= 14; i++) {
send_byte(msj5[i]);
delay(350);
}
rs = 0;
send_byte(0xC0);
rs = 1;
for (byte i = 0; i <= 15; i++) {
send_byte(0x20);
delay(1);
}
miles=0;
cen=0;
dec=0;
uni=0;
rs = 0;
send_byte(0xC0);
}
}
tecla2 = tecla2+1;
break;
case 0b11011101: // Número 6
miles = cen;
cen = dec;
dec = uni;
uni = 0x06;
break;
case 0b11011011: // Número 5
miles = cen;
cen = dec;
dec = uni;
uni = 0x05;
break;
case 0b11010111: // Número 4
miles = cen;
cen = dec;
dec = uni;
uni = 0x04;
break;
case 0b10111110: // Tecla C para borrar datos
miles = 0;
cen = 0;
dec = 0;
uni = 0;
break;
case 0b10111101: // Número 9
miles = cen;
cen = dec;
dec = uni;
uni = 0x09;
break;
case 0b10111011: // Número 8
miles = cen;
cen = dec;
dec = uni;
uni = 0x08;
break;
case 0b10110111: // Número 7
miles = cen;
cen = dec;
dec = uni;
uni = 0x07;
break;
case 0b01111110: // Letra D
tecla = 0x0D;
break;
case 0b01111101: // Símbolo #
tecla = 0x0F;
break;
case 0b01111011: // Número 0
miles = cen;
cen = dec;
dec = uni;
uni = 0x00;
break;
case 0b01110111: // Símbolo *
tecla = 0x0E;
break;
}
}
}
rs = 0; // para enviar codigos de instrucciones.
send_byte(0xc0); // enviar cursor al primer rengflon
rs = 1; // para enviar mensajes
if (miles == 0) {
send_byte(0x20); // Si el valor de miles es 0, enviar un espacio en blanco
} else {
send_byte(0x30 | miles); // Si miles no es 0, enviar el valor de miles como un carácter ASCII
}
if(miles==0 & cen==0){
send_byte(0x20);
}
else{
send_byte(0x30|cen);
}
if (cen == 0 && dec == 0) {
send_byte(0x20); // Si centenas y decenas son 0, enviar un espacio en blanco
} else {
send_byte(0x30 | dec); // Enviar el valor de decenas como un carácter ASCII
}
send_byte(0x30 | uni); // Enviar el valor de unidades como un carácter ASCII
}
void animacionLCD(const char* caracteres, int duracionSegundos) {
unsigned long tiempoInicio = millis(); // Obtiene el tiempo actual en milisegundos
unsigned long duracionMillis = duracionSegundos * 1000; // Convierte la duración de segundos a milisegundos
int numCaracteres = strlen(caracteres); // Obtiene la longitud de la cadena de caracteres
while (millis() - tiempoInicio < duracionMillis) {
for (int i = 0; i < numCaracteres; ++i) {
rs = 0;
send_byte(0x01); // Limpiar la pantalla LCD
send_byte(0x80); // Establecer la posición del cursor en la primera fila
rs = 1;
send_byte(caracteres[i]); // Imprimir el carácter en la LCD
delay(500); // Pausa de 0.5 segundos entre cada carácter
}
}
}