
Registro de Entrada por Número PIN.
Con teclado matricial 4×4 con LCD.
PROLOGO.
En otro artículo sobre teclados ya vimos un ejemplo de cómo crear un acceso mediante un PIN a una estancia, en aquella ocasión utilizábamos un teclado de 3×4 y un LCD numérico de 20×4, ambos muy conocidos. se servían de unas librerías que actualmente se han mejorado. En esta ocasión vamos a utilizar el mismo ejemplo y las herramientas o mejor dicho los dispositivos los hemos actualizado para que el interesado pueda extraer mejores resultados y utilice los nuevos dispositivos y librerías.
El display empleado es el mismo un LCD de 4 lineas y 20 dígitos, en esta ocasión con la ayuda de un adaptador serial comercial y por otra parte un teclado de 4×4 por adaptarse bien al proyecto y ser muy económico ambos los vemos a continuación.
El convertidor o mochila serie lo aplicaremos al display para reducir los puertos o pines del Arduino, además se muestra un PCB de un adaptador mediante un PCF8574A para el teclado matricial, que puede realizar con el pdf adjunto.
Fig. 2 PCB del convertidor de 8Bits.
También puede adquirir un convertidor comercial como el mostrado en la siguiente figura.
Fig. 3 Convertidor de 8Bits comercial.
En cualquiera de los dos casos, no olvide declarar la dirección del conversor, usted puede elegir entre las posibles.
Por otra parte hemos dispuestos las nuevas librerías necesarias para el actualizado código para manejar la entrada del PIN mediante el teclado matricial. El primer cambio esta en la declaración del teclado:
// (Adds,En,Rw,Rs,D4,D5,D6,D7)
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3,POSITIVE);
El segundo cambio esta en la declaración del passwor, como ya se vio en el anterior artículo tenemos que crear una clave, el código que introduzca el usuario:
Password password = Password("123A4566"); // entre su passwor
El siguiente cambio esta en la declaración del mapeado del teclado:
#include "Keypad.h" const byte ROWS = 4; //four rows const byte COLS = 4; //four columns char keys[ROWS][COLS] = { {'1','2','3','A'}, {'4','5','6','B'}, {'7','8','9','C'}, {'*','0','#','D'} };
Donde hacemos constar que son 4 filas y 4 columnas, en la declaración del mapa del teclado añadimos las teclas de la cuarta columna A, B, C y D. También declaramos los pines del mapa del teclado.
// vigile el orden de los pines. byte rowPins[ROWS] = {9, 8, 7, 6}; // pines digitales - filas byte colPins[COLS] = {5, 4, 3, 2}; // pines digitales - columnas
Debemos declarar el segundo I2C que utilizaremos para el teclado.
int i2caddress = 0x38; // por ej.
Ahora es el momento de ‘crear’ el teclado propiamente dicho, es decir, con una sentencia, el programa generará una matriz que verá como un teclado, al que se remitirá, cuando tenga que representar un dígito. Esto se consigue con la siguiente línea:
// Secuencia para crear la matriz del teclado (Keypad)
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
En el caso de disponer de un convertidor I2C que contiene al chip PCF8574, lo podemos utilizar para el teclado con la siguiente línea:
Keypad_I2C kpd = Keypad_I2C( makeKeymap(keys), rowPins, colPins, ROWS, COLS, i2caddress );
El resto del código lo hemos mejorado sólo un poco. En el setup() se incluye la sentencia lcd.setBacklight(HIGH); // para activar el backlight para lo que se indica en ella. El resto de del código es bastante explicito por lo que sólo se comentará algo cuando se crea de interés. Por ejemplo, en el loop(), se han añadido las siguientes líneas:
if (buttonState == LOW) { Serial.println("Ha pulsado el boton ...."); for(int z=0; z<6; z++){ lcd.setCursor(1,3); lcd.print("ALARMA ACTIVADA!"); delay(1000); lcd.setCursor(1,3); lcd.print(" "); delay(500); } setup(); //incorrectPIN();
Para presentar el estado de alarma en el caso de pulsar el botón dispuesto para tal fin. Ahora veamos el código completo en el que hemos dispuesto un sólo adaptador para el display.
// clave_pin_I2C.ino - keypad switch con ocho digitos para el PIN // // // clave_pin_lcd.pde - keypad switch con ocho digitos para el PIN // basado en el chapter 42 de // http://tronixstuff.wordpress.com/tutorials // /* El circuito: * LCD 20x4 basado en el HD44780 * 2 botones a los pines 6 y 7. Marcha/Paro y Puesta a Cero. * LED en pin 13 (opcional para indicar la pulsacion de los botones) PINES PINES LCD Arduino 4 7 5 GND 6 8 11 9 12 10 13 11 14 12 Definicion de funciones de control LCD printtime(); Escribe el tiempo clearLCD(); Borrar el LCD lcd.setCursor(0,0); columna -y- fila lcd.setCursor(0,0); Escribir en la columna 1, 1a linea lcd.setCursor(0,1); Escribir en la columna 1, 2a linea lcd.setCursor(2,2); Escribir en la columna 3, 3a linea lcd.setCursor(0,3); Escribir en la columna 1, 3a linea Usando hardware descrito, se pueden activa o desactivar algo mediante el teclado - reproduciendo lo que se puede encontrar en algunos sistemas de alarma y asi aplicar las sugerencias que se nos ocurran. El objetivo con este ejemplo es, simular - los sistemas de acceso para obtener un PIN previamente especifico. Si el PIN es correcto, hacer algo. Si el PIN no es correcto, hacer otra cosa. Las acciones que se puedan ocurrir, pero para el ejemplo vamos a activar o desactivar una salida digital. Este ejemplo es para aprender un concepto y un marco, para desarrollar ideas propias. Se utiliza una clave con seis dígitos para el PIN. El signo '#' del teclado, se emplea como la función ENTER. 09.11.2011 funciona bien. Usando IDE v.0013/0023 con 4506 bytes adaptado por V. García. para hispavila.com */ #include "Password.h" // lib. Password //#include "LiquidCrystal.h" // necesitamos esta lib. LiquidCrystal.h para los comandos de LCD #include "LiquidCrystal_I2C.h" // lib. LiquidCrystal_I2C.h para mochila I2C #include "Keypad_I2C.h" // lib. Keypad_I2C.h para módulo conversor #include "Keypad.h" // libreria Keypad.h para teclado // inicializa la libreria con los numeros de interface de los pines // lcd (RS,RW, E, D4,D5, D6, D7) // LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // **** si no usa I2C // El valor 0x27, debe adecuarse al elegido en los pines A0, A1 y A2 // del adaptador serie, este valor 0x27 corresponde a estos 3 pines a HIGH // LiquidCrystal_I2C lcd(0x27); // o 39. Set the LCD I2C address // set the LCD address to "0x27"(or "0x3f") for a 16 chars and 2 line display // set the LCD address to "0x3f"(or "0x27") for a 16 chars and 2 line display // En la versión LiquidCrystal_I2C de 2019, se debe usar como sigue: // (Adds,En,Rw,Rs,D4,D5,D6,D7) LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3,POSITIVE); Password password = Password("123A4566"); // entre su password const byte ROWS = 4; // Cuatro filas const byte COLS = 4; // Tres columns, cambio añado A B C D // Define el Keymap char keys[ROWS][COLS] = { {'1','2','3','A'}, {'4','5','6','B'}, {'7','8','9','C'}, {'*','0',' ','D'}}; // vigile el orden de los pines. byte rowPins[ROWS] = {11, 10, 9, 8}; // pines digitales - filas byte colPins[COLS] = {5, 4, 3, 2}; // pines analógicos - column (AN2, AN1 y AN0) const int buttonPin = 6; // pin 2 para un pulsador. int buttonState = 0; // Secuencia para crear el teclado (Keypad) Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); int ledPin = 13; // para uso indistinto. int sal1 = 12; // pin 10 digital. Rele de potencia //int sal2 = 12; // pin 11 digital. Rele de potencia void setup(){ // lcd.setBacklightPin(3,POSITIVE); // ya declarado lcd.setBacklight(HIGH); // para activar el backlight pinMode(buttonPin, INPUT); digitalWrite(buttonPin, HIGH); digitalWrite(ledPin, LOW); // pone el LED en off digitalWrite(sal1, LOW); buttonState = digitalRead(buttonPin); // lee el estado inicial pinMode(ledPin, OUTPUT); pinMode(sal1, OUTPUT); // pinMode(sal2, OUTPUT); Serial.begin(9600); lcd.begin(20, 4); keypad.addEventListener(keypadEvent); //add an event listener for this keypa keypad.setDebounceTime(250); // retardo anti-rebote Serial.println("clave_pin_i2c.ino Listo \n"); lcd.clear(); //Borra el LCD delay(500); lcd.setCursor(1,0); lcd.print("clave_pin_I2C.ino"); delay(2500); lcd.clear(); //Borra el LCD delay(500); lcd.setCursor(0,0); lcd.print("Entre secuencia PIN:"); lcd.setCursor(0,1); lcd.print(" 8 digitos + # "); // X X X X X X + # lcd.setCursor(0,2); lcd.print("Intentelo: "); // las 2 lineas que siguen aseguran los contactos de puertas digitalWrite(sal1, LOW); // desactiva un contacto // digitalWrite(sal2, HIGH); // activa un contacto } void loop(){ keypad.getKey(); buttonState = digitalRead(buttonPin); if (buttonState == LOW) { Serial.println("Ha pulsado el boton ...."); digitalWrite(buttonPin, HIGH); lcd.clear(); for(int z=0; z < 6; z++){ lcd.setCursor(0,2); lcd.print(" "); digitalWrite(ledPin, HIGH); delay(10); lcd.setCursor(0,2); lcd.print("ALARMA ACTIVADA! "); digitalWrite(ledPin, LOW); delay(10); delay(200); lcd.setCursor(0,2); lcd.print(" "); delay(100); } paraAlarma(); // setup(); //incorrectPIN(); } } void paraAlarma(){ // digitalWrite(buttonPin, LOW); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(0,2); lcd.print("Pulsa parar Alarma"); keypad.getKey(); buttonState = digitalRead(buttonPin); if (buttonState == HIGH) { // delay(2000); Serial.println("PIT-PIT"); return; } // } void correctPIN() // hacer esto. Si el PIN escrito es correcto { digitalWrite(sal1, HIGH); // activa un contacto pin 12 // digitalWrite(sal2, HIGH); // activa el contacto del pin 2 lcd.clear(); lcd.setCursor(2,1); // set cursor to column 2, row 0 (the first row) lcd.print("PASSWORD VALIDO!"); Serial.println("PASSWORD VALIDO"); // password.reset(); //resetea password después de entrada correcta delay(1000); lcd.setCursor(2,1); lcd.print(" "); for (int z=0; z>3; z++) { for (int positionCounter = 0; positionCounter < 21; positionCounter++) //desplaza text { lcd.setCursor(1,0); lcd.print("Bienvenido..."); lcd.setCursor(2,1); lcd.print(" "); // // scroll una posición a derecha: lcd.scrollDisplayRight(); // esperar un poco. delay(120); } } delay(5000); setup(); } void incorrectPIN() // hacer esto. Si el PIN escrito es incorrecto { digitalWrite(sal1, LOW); // desactiva un contacto // digitalWrite(sal2, HIGH); // activa un contacto lcd.clear(); lcd.setCursor(0,0); lcd.print("PASSWORD INVALIDO "); Serial.println("PASSWORD INVALIDO"); delay(1500); lcd.clear(); password.reset(); //resetea password después de entrada INCORRECTA delay(100); lcd.clear(); lcd.setCursor(0,0); lcd.print("Entre secuencia PIN:"); lcd.setCursor(0,2); lcd.print("Reintentar:"); } // atender algunos eventos especiales void keypadEvent(KeypadEvent eKey){ parpadea(); // parpadea switch (keypad.getState()){ case PRESSED: lcd.print(eKey); Serial.print(eKey); switch (eKey){ case ' ': guessPassword(); break; default: password.append(eKey); } } } void parpadea(){ digitalWrite(ledPin, HIGH); delay(10); digitalWrite(ledPin, LOW); } void guessPassword(){ if (password.evaluate()){ digitalWrite(ledPin,HIGH); //activa rele de la puerta delay(800); digitalWrite(ledPin,LOW); //desactiva rele de la puerta .5 sec correctPIN(); } else{ digitalWrite(ledPin,LOW); delay(500); digitalWrite(ledPin,HIGH); //desactiva rele de la puerta .5 sec incorrectPIN(); } }
Como de costumbre seleccione el código y guárdelo con un nombre apropiado, compílelo y súbalo al Arduino, para comprobar su efectividad. Es muy recomendable actualizar las librerías a la última versión para conseguir que todo vaya bien, si no se menciona lo contrario.
En el vídeo siguiente se puede apreciar que aún conservo el Arduino de cuando empecé (buena señal) y la efectividad del programa.
Vídeo
Si tiene alguna duda haga su pregunta, intentaré responder.
Más historias
Cómo construí mi CNC parte3.
Cómo construí mi CNC parte2.
Cómo construí mi CNC parte1