Problema con codigo para control de acceso por teclado y lcd con dos claves.

Buenas.

Pues veréis, tengo un problema con un código, que no consigo dar con la tecla para que funcione.

Busque un código en la red y lo adapte a mis necesidades.

Se trata de un control para una puerta, con teclado de 3x4 y lcd de 2x16.

El código con una sola clave funciona correctamente, pero a mí me hacen falta dos claves de acceso, para activar diferentes salidas según que clave y es aquí donde no me funciona el tema.

He intentado muchas cosas, pero nada de nada. Os dejo los dos códigos, el que funciona con una sola clave y el que no funciona con dos claves.

Luego está el asunto de introducir en el código un menú para el lcd para el cambio de claves a través de un código maestro, pero esto es otra historia que no me preocupa tanto…

En fin, a ver si me podéis orientar un poco con el asunto.

Un saludo a todos.

/*
1 clave
 password_lcd.pde

Basado en artículos de la red.

Modificado y adaptado el 07.11.2011 por V. Garcia.
Para hispavila.com

Utilizamos las librerías: [Password.h LiquidCrystal.h Keypad.h]
que puede encontrar en: http://hispavila.com/3ds/atmega/clavenum.html

Usando el actual ejemplo de hardware se pueden activa algo o desactivar
mediante el teclado - emulando lo que se puede encontrar en algunos
sistemas de alarma y así­ sucesivamente. Nuestro objetivo con este ejemplo
es muy simple. Un sistema de espera para obtener un PIN que se especifique
previamente. Si el PIN es correcto, hacer algo. Si el PIN es incorrecto,
hacer otra cosa. Lo que las acciones pueden llegar a hacer. Con el proyecto
vamos a activar o desactivar una salida digital. Este ejemplo es para
darle un concepto y un marco para adaptar o construir ideas propias.

Usa 4654 bytes con el IDE v. 00013
*/

/* 

Control de acceso.

Programacion modificada del original, el 14 de agosto del 2014.

*/

#include <Password.h>
#include <LiquidCrystal.h>
#include <Keypad.h>

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
Password password = Password( "9756" ); // Aquí puede poner su pasword.
const byte ROWS = 4; // Cuatro rows
const byte COLS = 3; // Tres columns

// Define el Keymap del teclado
char keys[ROWS][COLS] = {
 {'1','2','3',},
 {'4','5','6',},
 {'7','8','9',},
 {'*','0',' ',}
};
// Conectar keypad ROW0, ROW1, ROW2 y ROW3 a los pines de Arduino.
byte rowPins[ROWS] = {5, 4, 3, 2}; // pines a conectar los row del teclado.
byte colPins[COLS] = {A0, A1, A2}; // AN0, AN1 y AN2. Por falta de pines
 
const int buttonPin = 6; //

int buttonState = 0;
int i;
//int puerta = A7; // pin 6 salida a rele


// Crear el Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

#define ledVerde 13
#define ledRojo A3
#define luz A4
#define puerta A5
#define luzteclado A7

void setup(){
 pinMode(buttonPin, INPUT);
 pinMode(puerta, OUTPUT);
 pinMode(ledVerde, OUTPUT);
 pinMode(ledRojo, OUTPUT);
 pinMode(luz, OUTPUT);
 pinMode(luzteclado, OUTPUT);
digitalWrite(luzteclado, HIGH);
 
 lcd.begin(16, 2);
 
 digitalWrite(ledVerde, LOW);   // pone el LED en off
 digitalWrite(ledRojo, LOW);
 digitalWrite(puerta, HIGH);
 
 Serial.begin(9600);
 keypad.addEventListener(keypadEvent); //añad. evento listener al keypad
 keypad.setDebounceTime(250);
 
 lcd.clear();     //Borra el LCD
 lcd.setCursor(2,0);
 lcd.print("Pulse");
 lcd.setCursor(2,1);
 lcd.print("Codigo: ");
}


void loop(){
 keypad.getKey();
 buttonState = digitalRead(buttonPin);
 if (buttonState == HIGH) {
  lcd.clear();
 }
}

// atender algunos eventos especiales
void keypadEvent(KeypadEvent eKey){
  switch (keypad.getState()){
   case PRESSED:
   lcd.print(eKey);
   switch (eKey){
    case ' ': guessPassword();
    break;
    default:
    password.append(eKey);
    digitalWrite(luz, HIGH);
    digitalWrite(luzteclado, HIGH);
  }
 }
}

void guessPassword(){
  if (password.evaluate()){
    digitalWrite(puerta, LOW); // activa relé1 de la puerta
    digitalWrite(ledVerde,HIGH); // activa el LED de la puerta .5 seg.
    delay(1000);
    digitalWrite(puerta, HIGH);  // desactiva relé2 de la puerta
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("CODIGO CORRECTO"); //
    password.reset(); // resetea password despues de entrada correcta
    delay(1000);
    lcd.setCursor(0,1);
    lcd.print("PASE, POR FAVOR");
 // delay(1000);
 // for (int positionCounter = 0; positionCounter < 22; positionCounter++)
    delay(7000); // espera 35 segundos antes de volver añ inicio
    digitalWrite(ledVerde,LOW); // desactiva LED de la puerta
    setup(); // al inicio
 }

  else{
    i = i++;
    
    digitalWrite(ledRojo,HIGH);
    lcd.clear();
    lcd.print("CODIGO INVALIDO");
    password.reset(); //resets password after INCORRECT entry
    //delay(3000); // tiempo de retardo
    //lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Pruebe de nuevo");
    delay(5000);
    digitalWrite(ledRojo, LOW);
    setup(); // al inicio

  }
    digitalWrite(luz, LOW);
    digitalWrite(luzteclado, LOW);
}
/* 
2 claves
password_lcd.pde

Basado en artículos de la red.

Modificado y adaptado el 07.11.2011 por V. Garcia.
Para hispavila.com

Utilizamos las librerías: [Password.h LiquidCrystal.h Keypad.h]
que puede encontrar en: http://hispavila.com/3ds/atmega/clavenum.html

Usando el actual ejemplo de hardware se pueden activa algo o desactivar
mediante el teclado - emulando lo que se puede encontrar en algunos
sistemas de alarma y así­ sucesivamente. Nuestro objetivo con este ejemplo
es muy simple. Un sistema de espera para obtener un PIN que se especifique
previamente. Si el PIN es correcto, hacer algo. Si el PIN es incorrecto,
hacer otra cosa. Lo que las acciones pueden llegar a hacer. Con el proyecto
vamos a activar o desactivar una salida digital. Este ejemplo es para
darle un concepto y un marco para adaptar o construir ideas propias.

Usa 4654 bytes con el IDE v. 00013
*/

 /* 

Control de acceso.

Programacion modificada del original, el 14 de agosto del 2014.

*/
// Librerias:
#include <Password.h>
#include <LiquidCrystal.h>
#include <Keypad.h>

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
Password password1 = Password( "1" );    // pasword.
Password password2 = Password( "2" );
const byte ROWS = 4;                       // numero de filas del teclado.
const byte COLS = 3;                       // numero de columnas del teclado.

// Define el Keymap del teclado
char keys[ROWS][COLS] = {
 {'1','2','3',},
 {'4','5','6',},
 {'7','8','9',},
 {'*','0',' ',}
};

// pines del teclado:
byte rowPins[ROWS] = {5, 4, 3, 2};         // pines de las filas. 1,2,3,4.
byte colPins[COLS] = {A0, A1, A2};         // pines de las columnas. AN0, AN1 y AN2 por falta de pines digitales. 1,2,3
 
// Variables:
int buttonState = 0;
//int i;



// Crear el Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

// asigna los pines:
#define ledVerde           A7 
#define ledRojo            A6
#define luzlcd             A4
#define relepuerta         A5
#define luzteclado         13

void setup(){
  
// define los tipos de pines:
 pinMode(relepuerta,       OUTPUT);
 pinMode(ledVerde,         OUTPUT);
 pinMode(ledRojo,          OUTPUT);
 pinMode(luzlcd,           OUTPUT);
 pinMode(luzteclado,       OUTPUT);
 
 
 lcd.begin(16, 2);
 
 // define los pines en el arranque:
 digitalWrite(ledVerde,    LOW);
 digitalWrite(ledRojo,     LOW);
 digitalWrite(luzteclado,  LOW);
 digitalWrite(relepuerta,  HIGH);
 
 
 Serial.begin(9600);
 keypad.addEventListener(keypadEvent);     // añad. evento listener al keypad
 keypad.setDebounceTime(250);
 
 lcd.clear();                              // borra el lcd.
 lcd.setCursor(2,0);                       // posicion donde empieza a escribir.
 lcd.print("Pulse");
 lcd.setCursor(2,1);
 lcd.print("Codigo: ");
}

void loop(){
 keypad.getKey();
 }


// atender algunos eventos especiales
void keypadEvent(KeypadEvent eKey){
  switch (keypad.getState()){
   case PRESSED:
   lcd.print(eKey);
   switch (eKey){
    case ' ': guessPassword();
    break;
    default:
    password1.append(eKey);
    password2.append(eKey);
    digitalWrite(luzlcd, HIGH);
    digitalWrite(luzteclado, HIGH);
  }
 }
}

void guessPassword(){
  
  if (password1.evaluate()){
    digitalWrite(relepuerta, LOW); // activa relé1 de la puerta
//    digitalWrite(ledVerde,HIGH); // activa el LED de la puerta .5 seg.
    delay(1000);
    digitalWrite(relepuerta, HIGH);  // desactiva relé2 de la puerta
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("CODIGO CORRECTO"); //
    password1.reset(); // resetea password despues de entrada correcta
    delay(1000);
    lcd.setCursor(0,1);
    lcd.print("PASE, POR FAVOR");
//  delay(1000);
//  for (int positionCounter = 0; positionCounter < 22; positionCounter++)
    delay(2000); // espera 35 segundos antes de volver añ inicio
//    digitalWrite(ledVerde,LOW); // desactiva LED de la puerta
    setup(); // al inicio
 }
 
  else if (password2.evaluate()){
   //i = i++;
   
    digitalWrite(relepuerta, LOW); // activa relé1 de la puerta
 //   digitalWrite(ledVerde,HIGH); // activa el LED de la puerta .5 seg.
    delay(1000);
    digitalWrite(relepuerta, HIGH);  // desactiva relé2 de la puerta
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("CODIGO CORRECTO"); //
    password2.reset(); // resetea password despues de entrada correcta
    delay(1000);
    lcd.setCursor(0,1);
    lcd.print("PASE, POR FAVOR");
 // delay(1000);
 // for (int positionCounter = 0; positionCounter < 22; positionCounter++)
    delay(2000); // espera 35 segundos antes de volver añ inicio
 //   digitalWrite(ledVerde,LOW); // desactiva LED de la puerta
    setup(); // al inicio
 
 }
 
  else{
//    i = i++;
    
    digitalWrite(ledRojo,HIGH);
    lcd.clear();
    lcd.print("CODIGO INVALIDO");
    password2.reset(); //resets password after INCORRECT entry
    //delay(3000); // tiempo de retardo
    //lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Pruebe de nuevo");
    delay(5000);
    digitalWrite(ledRojo, LOW);
    setup(); // al inicio
    
  }
    
    delay(2000);
    digitalWrite(luzlcd, LOW);
    digitalWrite(luzteclado, LOW);
 
 }

Saludos
Tienes en tu Sketch varias cosas que son molestas, por ejemplo el uso de delay
Segundo, para que funcione bien debes reiniciar los password (ambos) en cada comparación, así te eliminas dos problemas, el que tienes que solo funciona a veces, y otra que no te adivinen la clave al ir presionando una por una.

Le hice unas modificaciones a tu sketch para que corra de una forma que mas me gusta a mi. y para adaptarlo a una tarjeta Mega.

/* 
2 claves
password_lcd.pde

Basado en artículos de la red.

Modificado y adaptado el 07.11.2011 por V. Garcia.
Para hispavila.com

Utilizamos las librerías: [Password.h LiquidCrystal.h Keypad.h]
que puede encontrar en: http://hispavila.com/3ds/atmega/clavenum.html

Usando el actual ejemplo de hardware se pueden activa algo o desactivar
mediante el teclado - emulando lo que se puede encontrar en algunos
sistemas de alarma y así­ sucesivamente. Nuestro objetivo con este ejemplo
es muy simple. Un sistema de espera para obtener un PIN que se especifique
previamente. Si el PIN es correcto, hacer algo. Si el PIN es incorrecto,
hacer otra cosa. Lo que las acciones pueden llegar a hacer. Con el proyecto
vamos a activar o desactivar una salida digital. Este ejemplo es para
darle un concepto y un marco para adaptar o construir ideas propias.

Usa 7718 bytes con el IDE v. 00013
*/

 /* 

Control de acceso.

Programacion modificada del original, el 14 de agosto del 2014.

*/
// Librerias:
#include <Password.h>
#include <LiquidCrystal.h>
#include <Keypad.h>

LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);
Password password1 = Password( "8230553" );    // pasword.
Password password2 = Password( "14497039" );
const byte ROWS = 4; // Cuatro rows
const byte COLS = 4; // Tres columns

// Define el Keymap del teclado
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

// pines del teclado:
byte rowPins[ROWS] = { 30,32,34,36 };// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte colPins[COLS] = { 22,24,26,28 };// Connect keypad COL0, COL1 and COL2 to these Arduino pins. 
 
// Variables:
int buttonState = 0;
//int i;



// Crear el Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

// asigna los pines:
#define relepuerta1 A9
#define relepuerta2 A10
#define ledVerde A11
#define ledRojo A12
#define luz A13
#define puerta A14
#define luzteclado A15
#define luzlcd 10


unsigned long tiempo;
void setup(){
 pinMode(A8, OUTPUT);
 digitalWrite(A8,LOW);  
// define los tipos de pines:
 pinMode(relepuerta1,       OUTPUT);
 pinMode(relepuerta2,       OUTPUT); 
 pinMode(ledVerde,         OUTPUT);
 pinMode(ledRojo,          OUTPUT);
 pinMode(luzlcd,           OUTPUT);
 pinMode(luzteclado,       OUTPUT);
 digitalWrite(luzlcd, HIGH);
 
 lcd.begin(16, 2);
 
 // define los pines en el arranque:
 digitalWrite(ledVerde,    LOW);
 digitalWrite(ledRojo,     LOW);
 digitalWrite(luzteclado,  LOW);
 digitalWrite(relepuerta1,  LOW);
 digitalWrite(relepuerta2,  LOW); 
 
 
 Serial.begin(9600);
 keypad.addEventListener(keypadEvent);     // añad. evento listener al keypad
 keypad.setDebounceTime(250);
 
 lcd.clear();                              // borra el lcd.
 
 lcd.setCursor(2,0);                       // posicion donde empieza a escribir.
 lcd.print("Pulse Codigo");
 lcd.setCursor(0,1);
}

void loop(){
 keypad.getKey();
 }


// atender algunos eventos especiales
void keypadEvent(KeypadEvent eKey){
  switch (keypad.getState()){
   case PRESSED:
   switch (eKey){
    case '#': guessPassword();
    break;
    default:
      lcd.print('*');
      password1.append(eKey);
      password2.append(eKey);
      digitalWrite(luzlcd, HIGH);
      digitalWrite(luzteclado, HIGH);
      tiempo= millis();
  }
 }
}

void guessPassword(){
  
  if (password1.evaluate()){
    digitalWrite(relepuerta1, HIGH);  // desactiva relé2 de la puerta
    delay(500);
    digitalWrite(relepuerta1, LOW);  // desactiva relé2 de la puerta
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("CODIGO CORRECTO"); //
    reset_password(); //resets password after INCORRECT entry
    delay(1000);
    lcd.setCursor(0,1);
    lcd.print("PASE, POR FAVOR");
//  delay(1000);
//  for (int positionCounter = 0; positionCounter < 22; positionCounter++)
    delay(2000); // espera 35 segundos antes de volver añ inicio
//    digitalWrite(ledVerde,LOW); // desactiva LED de la puerta
    setup(); // al inicio
 }
 
  else if (password2.evaluate()){
    digitalWrite(relepuerta2, HIGH);  // desactiva relé2 de la puerta
    delay(500);
    digitalWrite(relepuerta2, LOW);  // desactiva relé2 de la puerta

    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("CODIGO CORRECTO"); //
    reset_password(); //resets password after INCORRECT entry
    delay(1000);
    lcd.setCursor(0,1);
    lcd.print("PASE, POR FAVOR");
 // delay(1000);
 // for (int positionCounter = 0; positionCounter < 22; positionCounter++)
    delay(2000); // espera 35 segundos antes de volver añ inicio
 //   digitalWrite(ledVerde,LOW); // desactiva LED de la puerta
    setup(); // al inicio
 
 }
 
  else{
//    i = i++;
    
    digitalWrite(ledRojo,HIGH);
    lcd.clear();
    lcd.print("CODIGO INVALIDO");
    reset_password(); //resets password after INCORRECT entry
    //delay(3000); // tiempo de retardo
    //lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Pruebe de nuevo");
    delay(5000);
    digitalWrite(ledRojo, LOW);
    setup(); // al inicio
    
  }
  if (millis() -tiempo > 2000){    
    digitalWrite(luzlcd, LOW);
    digitalWrite(luzteclado, LOW);
  }
}


void reset_password(){
    password1.reset(); // resetea password despues de entrada correcta    
    password2.reset(); // resetea password despues de entrada correcta
}

Muchas gracias por tu ayuda.

Según veo comparando los códigos, mi problema era que como bien dices, no reseteaba la clave, no?

Luego está lo de optimizar el código quitando los delay. Todavía me pierdo con los millis… (Como buen novato).

En fin, todavía tengo que aprender mucho.
Mi siguiente reto, el hacer un menú para cambiar las claves desde el teclado.

Un saludo.

Saludos.
Tambien soy un novato. Ahora me intereso tu proyecto y lo termine, ya hice la parte del cambio de clave por teclado, voy ahora a hacer la parte de guardar la clave en la eeprom para que no se pierda al reiniciar el arduino. Si quieres te la paso.

Se pierde la clave?

Yo apago y enciendo y la clave sigue guardada, no se si te refieres a eso?

Si. Si eres tan amable, pon tu codigo aquí y así tendré un muy buen ejemplo para aprender! !.

Un saludo.

Funciona de la siguiente manera: Presionas * durante tres segundos para entrar en cambio de clave. Al presionar * se marca en la pantalla espera que se apague el backlight y luego se enciende mostrando: "Cambio de clave" y después "Introduzca clave" Introduces la clave anterior y presionas #. Te muestra "Clave Nueva", introduces la clave nueva y presionas #, nuevamente aparece "Clave nueva", introduces de nuevo la clave y presionas #, si son iguales guarda la clave, si no muestra "DIferentes".

En tu caso no se pierde la clave porque no se modifica, es decir la colocas en el codigo, pero cuando la modificas y reinicas toma la primera de nuevo.

Password.ino (8.81 KB)

Buenas.

Pues no me sale lo de la eeprom, de hecho no sé si el mini que es el uso tiene eeprom para ello…

Otro problema que tengo es que las dos primeras teclas que pulso suelen ir bien, pero el resto no. Tengo que pulsar varias
veces la misma tecla para que la detecte.

No sé si es problema del teclado o yo que sé.

Uso dos teclados en paralelo como este: http://es.farnell.com/jsp/search/productdetail.jsp?SKU=1130817

Como tengo uno de ellos con el LCD, pues no hay problema, sabes si has pulsado o no, pero el otro que lo tengo sin LCD, al no saber si has pulsado o no, es imposible usarlo.

He pensado en pones un buzz en el teclado sin LCD.

¿Cómo lo veis?

Un saludo.

Saludos. Yo me di cuenta que la separacion entre teckas debe ser de un segundo, asumi que era cosa de la libreria.

Y lo mas facil para la que no tiene lcd seria un led.

Saludos
Con respecto al tiempo entre teclas ya lo resolví, la librería trae la función setDebounceTime que te permite modificar el tiempo entre teclas.

Para los que deseen aquí dejo el sketch, donde se graba la clave en la memoria EEPROM del Arduino, y se puede modificar. Se aceptan mejoras.

Password.ino (9.46 KB)

Muchas gracias max_saeta

Después de todo este tiempo, ahora voy a probar tu código…

Perdona mi ausencia en este y otros temas… he estado solucionando unos asuntos pendientes y he estado desconectado un tiempo.

Un saludo a todos.