ARD13 – Teclados matriciales

Facebooktwittergoogle_pluslinkedinmailFacebooktwittergoogle_pluslinkedinmail

En este artículo vamos a aprender a manejar un teclado matricial. Se trata de una matriz de pulsadores, dispuestos “en cuadro”, de forma que hay tantos hilos de conexión como filas más columnas. Por ejemplo, supongamos el teclado típico de un cajero automático. Tiene 16 pulsadores distribuidos en cuatro filas y cuatro columnas. Por lo tanto, podemos identificar cada pulsador con una coordenada de fila y columna. Con un total de ocho hilos podemos identificar cada pulsador de forma inequívoca.

Figura 13.1. Un teclado matricial de 16 teclas.

Figura 13.1. Un teclado matricial de 16 teclas.

En este capítulo aprenderemos cómo funcionan este tipo de teclados, pero aprenderemos también mucho sobre Arduino, librerías externas, etc.

En la figura 13.1 vemos uno de los típicos teclados matriciales que se emplean con Arduino. Salvo que necesitáramos un teclado más “duro” (para intemperie, p.e.) este modelo nos valdrá perfectamente. Se vende en cualquier tienda de electrónica por cuatro o cinco euros.

El esquema de conexionado interno de los hilos es tal que cada uno de los cuatro primeros (de la izquierda del conector) está conectado a una fila de pulsadores. Cada uno de los cuatro últimos (de la derecha del conector) está conectado a una columna de pulsadores. De este modo, al pulsar cualquiera de las teclas, se identifica inequívocamente en qué fila y columna está la tecla pulsada. En la figura 13.2 puedes ver un esquema del conexionado interno de los ocho hilos en los dieciséis pulsadores.

Figura 13.2. Esquema de hilos de un teclado matricial de 16 teclas.

Figura 13.2. Esquema de hilos de un teclado matricial de 16 teclas.

Por ejemplo, si pulsas la tecla marcada con el 8 se cerrará el circuito entre los hilos 6 y 3. No se cerrará ningún otro circuito, y no hay ninguna manera de que se cierre el circuito entre esos dos hilos si no es pulsando exactamente esa tecla.

En este capítulo vamos a conectar un teclado matricial a nuestro Arduino Uno y veremos, en la consola serie cada tecla que pulsemos.

EL MONTAJE

El esquema electrónico del montaje es muy simple. Se trata de conectar los cuatro hilos de las filas (por ejemplo) a pines de salida, y los cuatro de las columnas a pines de entrada. Así, dando señal a cada pin de salida, y comprobando si la señal llega a cada pin de entrada, sabremos que tecla está pulsada.

Lo que haremos es que Arduino reconozca cada pulsación de una tecla del teclado matricial empleado. En este primer ejemplo no procesaremos las pulsaciones, es decir, no las usaremos para, por ejemplo, configurar una clave de acceso o ningún otro uso. Solo las registraremos. Más adelante, en este mismo artículo, veremos otro ejemplo más elaborado con esas pulsaciones. En la figura 13.3 ves el esquema completo.

Figura 13.3. El esquema teórico de este montaje.

Figura 13.3. El esquema teórico de este montaje.

En la figura 13.4 ves el montaje físico.

Figura 13.4. El montaje físico de este artículo.

Figura 13.4. El montaje físico de este artículo.

Como puedes ver, es simple y cómodo de montar. Ahora veamos el sketch.

EL SKETCH

Vamos a empezar como siempre, reproduciendo el listado completo y analizándolo teóricamente paso a paso. Si lo pruebas directamente, no te funcionará, porque antes es necesario un paso del que hablaremos enseguida, así que no seas impaciente y sigue leyendo.

El listado completo de este sketch aparece a continuación:

Lo primero que hacemos es incluir en el código una librería llamada Keypad, que implementa funcionalidades para facilitar la gestión de teclados.

Como ya hemos tenido ocasión de comprobar (y tendremos más en lo sucesivo), existen librerías específicas para facilitar la gestión de distintos dispositivos (servomotores, pantallas LCD y ahora los teclados son sólo algunos ejemplos).

En los casos anteriores, las librerías las incluíamos directamente, porque ya forman parte, por defecto, del IDE de Arduino. En el caso de la librería Keypad, aunque es oficial de Arduino, no forma parte de la instalación del IDE, por lo que es necesario descargarla e instalarla previamente. Por eso te decía hace unas líneas, que el sketch, si lo tecleas así, sin más, no te va a funcionar. En el próximo apartado vamos a ver como obtener librerías adicionales (bien sean oficiales de Arduino o de otros desarrolladores) e incorporarlas a nuestro IDE. Por ahora, para la explicación teórica, vamos a considerar que ya tenemos la librería instalada. Después que tú la instales, como te explicaré en este mismo capítulo, podrás probar el sketch y ver que efectivamente funciona sin problemas.

En la primera línea, incluimos la librería (suponiendo que ya la hayamos instalado), del modo habitual:

#include <Keypad.h>

Tenemos que definir el número de filas y columnas de nuestro teclado. Ten en cuenta que, en nuestro ejemplo, estamos usando un teclado matricial muy sencillito, para empezar a familiarizarnos con estas técnicas. Nuestro teclado es de dieciséis teclas, con cuatro filas y cuatro columnas. Sin embargo, lo que aquí aprendamos es perfectamente válido para cualquier teclado. Por ejemplo, un teclado de ordenador, con 108 teclas, distribuido en 10 filas y 11 columnas, podría gestionarse también de la misma forma (aunque el código, por supuesto, sería más engorroso).

const byte Filas = 4; //KeyPad de 4 filas
const byte Cols = 4; //y 4 columnas

SOBRE FILAS Y COLUMNAS. Cuando hablamos de un teclado matricial, con el conexionado de los cables en filas y columnas, estamos hablando de la forma en que los cables se conectan con los pulsadores, es decir, de la distribución lógica de los cables. En el ejemplo que estamos viendo, nuestro teclado tiene cuatro filas y cuatro columnas, y, físicamente, los botones están dispuestos de esa forma, pero esto no tiene por qué ser siempre así. Aunque los botones estén conectados en m filas y n columnas, físicamente pueden estar dispuestos en otra configuración. Tal es el caso de un teclado de ordenador. Suelen tener 106 o 108 teclas, y el cableado responde a una conexión matricial de 10 x 11, pero el teclado físico no está distribuido en esa disposición, sino de una forma que sea cómoda de manejar para el operador. A nosotros, a la hora de programar un teclado desde Arduino, la disposición física no nos importa. Lo que nos importa es la disposición cableada (lógica), es decir, cada tecla, con que fila y columna está conectada, con independencia de dónde esté físicamente.

Ahora debemos indicar a que pines de la placa Arduino irán conectados los hilos que corresponden a las filas, y los que corresponden a las columnas del teclado.

byte Pins_Filas[] = {13, 12, 11, 10}; //Pines para las filas.
byte Pins_Cols[] = {7, 6, 5, 4}; // Pines para las columnas.

Esto lo hacemos en dos matrices (una para los pines de las columnas y otra para los pines de las filas), porque así lo va a requerir luego el uso de la librería Keypad. Declararlo así nos facilitará luego enormemente la tareas de programación del teclado. Las matrices son de tipo byte. Aunque, en muchos casos, cuando definimos un pin lo hacemos como de tipo int, en realidad un dato de tipo byte es suficiente para almacenar números hasta 127 con signo, y ahorramos espacio en memoria (Arduino no tiene demasiada).

Presta especial atención al orden en que se disponen los números de los pines en las matrices. Si ves el conexionado del circuito, empezamos por la izquierda, tanto en las filas como en las columnas.

Definimos una variable llamada pulsacion, que contendrá un registro de la tecla que pulsemos en cada momento

char pulsacion;

Ahora definimos una matriz con los distintos caracteres que incorpora el teclado, así:

char Teclas [Filas][Cols] = {
    {'1','2','3','A'},
    {'4','5','6','B'},
    {'7','8','9','C'},
    {'*','0','#','D'}
};

Presta atención. Se trata de una matriz de dos dimensiones, que, hasta ahora, no habíamos empleado. Es una matriz de datos de tipo char, de modo que cada elemento de la misma tendrá un carácter. Como va a tener dos dimensiones, al declararla establecemos dos índices:

char Teclas [Filas][Cols]

Como las constantes Filas y Cols ya están previamente declaradas, esto sería equivalente a haber puesto:

char Teclas [4][4]

La cuestión es que la declaración que hemos empleado en el sketch es más clara a la hora de leer nosotros el código.

Una matriz de dos dimensiones es una matriz de matrices. Cada elemento de la primera matriz es, a su vez, una matriz:

{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}

En cada una de estas matrices, cada elemento es un carácter. Si te fijas, la primera matriz contiene los caracteres de la primera fila del teclado, la segunda matriz contiene los caracteres de la segunda fila del teclado, y así sucesivamente.

Para acceder a un elemento concreto de una matriz bidimensional debemos indicar el nombre de la matriz, y los dos índices, como unas coordenadas, teniendo en cuenta que, al igual que en las matices unidimensionales, los índices empiezan a contar desde cero. Por ejemplo, si accedemos al elemento Teclas[1][0], estaremos accediendo a la matriz unidimensional declarada en la posición uno, que es {'4','5','6','B'} y, dentro de esta, al elemento que hay en la posición 0, es decir, el 4.

Dicho de otro modo. Cada matriz unidimensional es un elemento de otra matriz más grande, que podríamos llamar global. Al especificar los índices, el primero se refiere a la matriz unidimensional dentro de la global, y el segundo se refiere al elemento dentro de la matriz unidimensional.

Fíjate cómo están dispuestos los caracteres en la matriz. La matriz que representa a la primera fila, {'1','2','3','A'}, no es la primera por casualidad. En la definición de pines, La primera fila es la que va conectada al pin 13, que, en la definición de pines de filas, es el que ocupa la primera posición. La segunda fila, {'4','5','6','B'}, contiene los caracteres que corresponden a la segunda fila del teclado. En el circuito, esta se halla conectada al pin 12, que es el que ocupa la segunda posición en la matriz Pins_Filas. El mismo criterio se emplea para las columnas. Dentro de cada fila, el carácter que aparece en primera posición es el que en el teclado está conectado al hilo de columna que va al pin que aparece en primera posición en la matriz Pins_Cols.

Este modo de disponer las definiciones del teclado y de cada tecla, en su sitio adecuado, puede parecer un poco engorrosa la primera vez que se ve (a mí, al menos, me costó bastante llegar a comprender toda la estructura globalmente). Sin embargo, una vez que se entiende es de una lógica tan simple como eficiente, y permite a la librería una buena gestión del teclado. Te recomiendo que, si no lo tienes muy claro (sobre todo, si no estás familiarizado con el uso de matrices bidimensionales), dediques unos minutos a analizar las declaraciones de datos y el texto, para que, al menos, pilles por donde van los tiros.

A continuación, debemos definir un objeto de la clase Keypad, que representará a nuestro teclado. Esto se hace empleando el constructor de la clase, así:

Keypad Teclado1 = Keypad(makeKeymap(Teclas), Pins_Filas, Pins_Cols, Filas, Cols);

El objeto, en este ejemplo, lo hemos llamado Teclado1. El constructor recibe cinco argumentos:

  • El primero es la función makeKeymap que, a su vez, recibe como argumento el nombre de la matriz bidimensional que hemos definido para los caracteres de las teclas. Esta función no es del núcleo del lenguaje Arduino, sino que se ha importado al incluir la clase Keypad. Hablaremos de esta función más adelante, en este mismo capítulo.
  • El segundo argumento en el nombre de la matriz que incluye los pines donde están conectadas las filas del teclado.
  • El tercer argumento en el nombre de la matriz que incluye los pines donde están conectadas las columnas del teclado.
  • El cuarto argumento es el número de filas.
  • El quinto y último es el número de columnas.

De este modo el constructor de la clase Keypad define un objeto que contiene todos los datos relativos al teclado y a la conexión con la placa Arduino.

Dentro de la sección setup no hay nada especial que no conozcamos ya. Sólo se abre una conexión serie con la consola. De este modo, cuando nuestro montaje esté operativo, podremos visualizar cada tecla que pulsemos.

En la sección loop lo primero que encontramos es que le asignamos a la variable pulsación lo que se lee, en ese momento, en el teclado. El método getKey() se ocupa de realizar esa lectura. Como ves, la notación es la típica de la programación orientada a objetos: Objeto.método().

pulsacion = Teclado1.getKey();

Si, en el momento de ejecutarse esta instrucción, no se está pulsando ninguna tecla, el método getKey() devuelve un valor false. Si se está pulsando una tecla, el método getKey() devuelve el carácter que aparece en la matriz que corresponda a la fila y columna de la tecla pulsada. Pero el método getKey() hace algo más. Si la tecla pulsada permanece pulsada, ignora este hecho, de forma que se evitan repeticiones. Así, cuando pruebes el montaje, verás que si pulsas, por ejemplo, el 5 y lo mantienes pulsado, en la consola te aparece un sólo 5. Hasta que no sueltes y pulses otra tecla (o la misma), no te aparecerá nada más en la consola.

En la segunda línea la sección loop se comprueba si hay un valor en la variable pulsacion (recuerda que, si no se ha pulsado nada, el valor es false). Si lo hay, se envía a la consola.

Como ves, el teclado es un poco engorroso de configurar pero, una vez configurado correctamente, la librería que empleamos hace que sea muy fácil la lectura y gestión de las pulsaciones.

AÑADIENDO LIBRERÍAS A ARDUINO

Como ya hemos comentado, la librería Keypad no forma parte, por defecto, del núcleo del IDE de Arduino. Si queremos poder disponer de ella, lo primero que debemos hacer (una sóla vez) es descargarla de Internet y añadirla a nuestro IDE.

La página oficial de descarga de Keypad es: http://playground.arduino.cc/uploads/Code/keypad.zip. Pulsa el enlace y se te descargará un archivo comprimido zip, que puedes guardar en cualquier parte de tu ordenador (en el escritorio, por ejemplo). Da lo mismo (mientras lo tengas localizado) porque, tras instalar la librería, podrás borrar este archivo.

El hecho de que, una vez instalada la librería, puedas borrar el archivo, no significa que debas hacerlo. Dado que Arduino es un entorno de desarrollo de código abierto, el archivo que te has descargado incluye cosas interesantes. Por ejemplo, el código fuente, en C++ de la librería. Si dominas este lenguaje, quizá sientas curiosidad por echarle un vistazo, pero eso está fuera de los objetivos de este artículo.

Ahora abrimos el IDE de Arduino. En la barra de menús, en la parte superior, pulsamos sobre la opción Programa, y se nos abrirá un menú como el de la figura 13.5.

Figura 13.5. El menú Programa del IDE de Arduino

Figura 13.5. El menú Programa del IDE de Arduino

Desplazamos el puntero del mouse a la opción Importar Librería... y se nos abrirá otro menú con todas las librerías que ya tenemos, y con una opción, al principio, que pone Añadir librería..., y que es la que nos interesa. Vemos la parte superior de este menú en la figura 13.6.

Figura 13.6. El menú Importar Librerías del IDE de Arduino

Figura 13.6. El menú Importar Librerías del IDE de Arduino

Si pulsamos sobre el nombre de cualquiera de las librerías que ya aparecen listadas, veremos que se incluye directamente en el sketch. Nosotros pulsaremos ahora sobre la opción Añadir librería... y se abrirá un cuadro de diálogo para que busquemos el archivo keypad.zip, que hemos descargado de Internet. Lo abrimos y ya queda la librería incluida en el IDE de Arduino. A partir de aquí, ya podemos cargar el sketch que hemos visto antes. Lo subimos a la placa Arduino de la forma habitual. Abrimos la consola de comunicación serie y vemos como aparecen los caracteres de las teclas que pulsemos en el teclado.

Como vemos, las librerías de Arduino proporcionan funcionalidades que el núcleo del lenguaje no incorpora. Existen librerías para manejar todo tipo de dispositivos. Las oficiales de Arduino pueden encontrarse en http://playground.arduino.cc/Code/Code, donde aparece la lista completa de librerías que puedes añadir a tu IDE Arduino. Como ves, es una gran cantidad que, seguro, satisfarán todas las necesidades que puedas llegar a tener.

Y ¿Dónde se almacena la nueva librería que hemos importado? ¿En el directorio de instalación del programa? No. Se almacena en un directorio llamado libraries que se crea en la ruta donde guardamos nuestros sketches.

LA LIBRERÍA Keypad

Ahora que ya sabemos como importar la librería, y como incluirla en nuestro sketch, que hemos probado el montaje, y vemos que va bien, vamos a conocer la librería Keypad un poco mejor, para saber lo que podemos hacer con ella.

Como vemos, la librería es muy fácil de usar. Ya conocemos el constructor, y el método getKey(). Ahora vamos a conocer las otras posibilidades que pueden interesarnos para otros montajes:

El método waitForKey(). No recibe ningún argumento. Actúa de un modo muy similar a getKey(), devolviendo el carácter de la tecla pulsada. La diferencia es que bloquea la ejecución del sketch Arduino hasta que se pulse una tecla. Esto quiere decir que no se cambiará el estado de ningún LED, ni se llevará a cabo ninguna operación aritmética, ni ocurrirá NADA hasta que se pulse una tecla. La excepción a esto son aquellas operaciones de Arduino que provocan interrupciones, tema del que hablaremos más adelante.

El método getState(). No recibe ningún argumento y devuelve una constante que nos indica el estado del teclado. Hay cuatro posibilidades:

  • IDLE. El teclado está en reposo.
  • PRESSED. Se acaba de detectar la pulsación de una tecla.
  • RELEASED. Se acaba de detectar la liberación de una tecla pulsada.
  • HOLD. Se está manteniendo pulsada una tecla.

El método keyStateChanged(). No recibe argumentos. Devuelve un valor booleano que será true si se ha producido algún cambio en el estado del teclado, o false, en caso contrario.

El método setHoldTime(int). Se emplea para establecer el número de milisegundos necesarios para que se detecte una pulsación en el teclado. Si, por ejemplo, usamos la instrucción ObjetoTeclado.setHoldTime(50); el sketch ignorará una pulsación si esta dura menos de 50 milisegundos. Resulta muy útil para ignorar esas pulsaciones “rápidas” que se producen por error cuando desplazamos el dedo sobre un teclado con teclas muy sensibles.

El método setDebounceTime(int). Establece un periodo en milisegundos durante el cual se ignoran pulsaciones consecutivas. Por ejemplo, si usamos la instrucción ObjetoTeclado.setDebounceTime(50); estaremos indicándole al sketch que, tras soltar una tecla, se debe bloquear el proceso durante 50 milisegundos, antes de poder detectar otra pulsación.

UNA VARIANTE

Vamos a escribir un sketch que le permita al usuario teclear cuatro dígitos numéricos (como un PIN de teléfono o de cajero automático). Durante el tecleo, el usuario podrá pulsar la tecla *, lo que eliminará el último dígito pulsado. También podrá pulsar la tecla D, lo que dejará el PIN en blanco, para empezar a teclear de nuevo. Una vez pulsados los cuatro dígitos del PIN, podrá pulsar la A, para comprobar si dicho PIN coincide con el que tiene el sketch almacenado en memoria. El sketch completo es el siguiente:

No vamos a entrar en detalles, porque, a estas alturas, ya conoces lo necesario para analizar el código, y comprender como funciona. Si quiero hacer una consideración final. La consola serial de Arduino ofrece bastantes limitaciones: no permite borrar el contenido, no permite letras acentuadas, etc. En un artículo posterior veremos como resolver estos problemas.

     

4 comentarios:

  1. Pingback: ARD15 – Arduino Mega » eldesvandejose.com

  2. Pingback: ARD-SYN – La sintaxis de Arduino » eldesvandejose.com

  3. Pingback: ARD17 – Pantalla táctil TFT » eldesvandejose.com

  4. Hola agradecido por su aporte, actualmente tengo un proyecto con un raspberry pi y tengo un problema con el teclado, al momento de pulsar cualquier techa de la tercera o cuarta fila se marca doble pulsación no se cual es el motivo

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *