
Chisme 129 del Lince: teclado matricial 4×4, el lector de códigos
Víctor Vílchez, el Lince de la Noche, apareció en la cueva con el antebrazo del traje levantado, orgulloso como quien presenta un invento.
—Mira. Un lector de números. Para el código del casco —dijo, y pulsó el 5 con mucha ceremonia.
No pasó nada. Pulsó el 7. Nada. Pulsó la D, y luego otra vez el 5, cada vez más fuerte.
La Gata Montesa lo miró con las orejas hacia atrás.
—¿Lo has programado?
—Es un teclado. Sabe lo que es.
—Es una rejilla de interruptores, Víctor. No sabe ni que existe el 5. Cuando lo pulsas, solo une dos hilos. Quien tiene que darse cuenta es la placa.
—¿Y cómo se da cuenta?
—Preguntándole, tecla a tecla, a todas horas.
El Lince bajó el brazo muy despacio.
—Entonces antes de pegar el lector en el traje…
—…hay que enseñarle a la placa a leerlo —terminó la Gata—. Y hoy lo vamos a hacer sin ninguna librería.
Introducción
En este chisme 129 vas a programar un teclado matricial de 4×4 con la ESP32 Plus de Acebott. Es el típico teclado de membrana de 16 teclas: los números del 0 al 9, las letras de la A a la D, el asterisco y la almohadilla.
Lo vamos a hacer sin librerías, para que se vea cómo funciona. En la historia, este lector será la cerradura de código del traje del Lince. Con el Chisme 141 tenemos una máscara que se mueve sola y con el Chisme 142 un reloj maestro. Falta una forma de que el Lince les diga qué hacer, y el teclado será el primer paso.
Antes de montarlo, practica en el simulador del teclado matricial, que tiene modo demostración.
Qué necesitamos
- La ESP32 Plus de Acebott, programada con el Arduino IDE (placa «ESP32 Dev Module»), sin librerías.
- Un teclado de membrana 4×4 con 8 hilos en la cinta.
- Ocho cables Dupont o un conector macho de 8 pines donde pinchar la cinta.
Cómo funciona un teclado matricial
Un teclado de 16 teclas necesitaría 16 pines si cada tecla tuviera el suyo. Es demasiado. Los fabricantes lo resuelven colocando las teclas en una matriz: 4 filas y 4 columnas. Si quieres repasar la idea de matriz, tienes la entrada de matriz en la Wikipedia.
Cada tecla es un interruptor entre una fila y una columna. Al pulsarla, esa fila y esa columna quedan unidas. Con 4 + 4 = 8 pines se leen 16 teclas.
El teclado no lleva electrónica, ni memoria, ni sabe qué número es cada tecla. Lo único que hace es unir dos hilos. La tabla que dice «la fila 2 con la columna 3 es el 6» la escribimos nosotros en el programa.
Conexión

| Hilo de la cinta (de izquierda a derecha) | Pin de la ESP32 Plus |
|---|---|
| 1 | 13 |
| 2 | 14 |
| 3 | 27 |
| 4 | 16 |
| 5 | 17 |
| 6 | 25 |
| 7 | 19 |
| 8 | 18 |
Con el USB desenchufado. El teclado no necesita 3V3 ni GND, porque solo son interruptores.
Elegimos estos pines porque son de los que tienen conector macho en la shield. Evitamos el 12, que condiciona el arranque de la ESP32, y los pines 34 a 39, que solo sirven de entrada y no tienen resistencia pull-up. El 26 está en una hilera de conectores hembra.
Primero: descubrir filas y columnas
Cada teclado se monta a su manera y la cinta no trae etiquetas. Antes de escribir el programa final, necesitamos saber qué hilos son filas y cuáles columnas.
Este programa pone cada hilo en bajo y mira qué otro hilo cae con él. Si dos hilos se unen, nos lo dice.
// Chisme 129 - Descubrir filas y columnas del teclado de membrana 4x4
// Placa en Arduino IDE: ESP32 Dev Module. Monitor serie a 115200.
// Hilo 1 = pin 13, 2 = 14, 3 = 27, 4 = 16, 5 = 17, 6 = 25, 7 = 19, 8 = 18.
const int P[8] = {13, 14, 27, 16, 17, 25, 19, 18};
void setup() {
Serial.begin(115200);
for (int i = 0; i < 8; i++) pinMode(P[i], INPUT_PULLUP); // todos como entrada con pull-up
Serial.println("Pulsa teclas...");
}
void loop() {
for (int i = 0; i < 8; i++) {
pinMode(P[i], OUTPUT);
digitalWrite(P[i], LOW); // ponemos este hilo a 0
delayMicroseconds(50);
for (int j = 0; j < 8; j++) {
if (j != i && digitalRead(P[j]) == LOW) { // otro hilo ha caido a 0: estan unidos
Serial.print("Unidos hilo "); Serial.print(i + 1);
Serial.print(" y hilo "); Serial.println(j + 1);
}
}
pinMode(P[i], INPUT_PULLUP); // lo devolvemos a entrada
}
delay(150);
}
Sube el programa, abre el monitor serie a 115200 y pulsa teclas de una en una. Cada pulsación sale dos veces, por ejemplo «hilo 1 y hilo 7» y «hilo 7 y hilo 1». Es normal: se detecta desde cada lado.
En el teclado de este chisme salió esto:
| Tecla | Hilos que se unen |
|---|---|
| 3 | 1 y 7 |
| A | 1 y 8 |
| 4 | 2 y 5 |
| 7 | 3 y 5 |
* | 4 y 5 |
Todas las parejas tienen un hilo del 1 al 4 y otro del 5 al 8. Los hilos 1 a 4 son las filas de arriba abajo y los 5 a 8 las columnas de izquierda a derecha. Por ejemplo, la tecla 7 está en la fila 3 y la columna 1, y por eso une los hilos 3 y 5.
Tu teclado puede venir con otro orden. Si es así, las parejas te lo dirán y solo tendrás que cambiar los pines del programa final.
El programa final
Ahora que sabemos cómo está hecho, escribimos la tabla de teclas y la función que las lee.
// Chisme 129 - Teclado de membrana 4x4 con la ESP32 Plus de Acebott
// Placa en Arduino IDE: ESP32 Dev Module. Monitor serie a 115200.
// Sin librerias: leemos la matriz "a mano".
// Filas (hilos 1 a 4): 13, 14, 27, 16
// Columnas (hilos 5 a 8): 17, 25, 19, 18
const int FILAS[4] = {13, 14, 27, 16};
const int COLUMNAS[4] = {17, 25, 19, 18};
const char TECLAS[4][4] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
char ultima = 0; // ultima tecla detectada (para no repetirla mientras sigue pulsada)
// Devuelve la tecla pulsada, o 0 si no hay ninguna
char leerTecla() {
for (int f = 0; f < 4; f++) {
pinMode(FILAS[f], OUTPUT);
digitalWrite(FILAS[f], LOW); // activamos esta fila (la ponemos a 0)
delayMicroseconds(50);
for (int c = 0; c < 4; c++) {
if (digitalRead(COLUMNAS[c]) == LOW) { // la columna cae a 0: tecla pulsada
pinMode(FILAS[f], INPUT);
return TECLAS[f][c];
}
}
pinMode(FILAS[f], INPUT); // desactivamos la fila (alta impedancia)
}
return 0;
}
void setup() {
Serial.begin(115200);
for (int f = 0; f < 4; f++) pinMode(FILAS[f], INPUT);
for (int c = 0; c < 4; c++) pinMode(COLUMNAS[c], INPUT_PULLUP); // columnas con pull-up
Serial.println("Teclado listo. Pulsa teclas...");
}
void loop() {
char t = leerTecla();
if (t != 0 && t != ultima) { // tecla nueva
Serial.print("Tecla: ");
Serial.println(t);
}
ultima = t; // si soltamos, ultima = 0 y se puede repetir
delay(20); // pequeno antirrebote
}
Fíjate en tres cosas:
- Pull-up en las columnas. Con
INPUT_PULLUP, cada columna lee 1 mientras nada la toque. Así sabemos que un 0 significa «una tecla me ha unido con una fila activa». - Una fila cada vez. Ponemos una fila en bajo y miramos las cuatro columnas. Después la soltamos con
INPUTy pasamos a la siguiente, para que dos filas no se peleen. - La variable
ultima. Sin ella, mientras mantienes pulsada una tecla el programa la imprimiría cientos de veces por segundo.
Cómo probarlo
- Sube el programa y abre el monitor serie a 115200.
- Pulsa las 16 teclas, una a una. Cada pulsación debe salir una sola vez, con su número o letra.
- Mantén una tecla pulsada un segundo. Debe seguir saliendo una sola vez.
- Si una tecla falla, comprueba que su fila y su columna llegan a los pines correctos.
Si alguna tecla no responde, puede ser que el contacto de la cinta no apriete bien en el cable. Es lo más habitual con estos teclados.
Qué estamos midiendo realmente
El teclado no mide nada: cada tecla es un sensor digital de todo o nada. Lo que sí hay es una trampa importante, el rebote. Al pulsar una tecla, el contacto vibra durante unos milisegundos y puede contar como varias pulsaciones. Por eso añadimos delay(20) al final del programa.
Otra limitación es la de las «teclas fantasma». Si pulsas tres teclas a la vez en una matriz sin diodos, puede detectarse una cuarta que no has tocado. En un teclado de 16 teclas lo normal es pulsar de una en una, y no nos afecta.
Para el aula
- Predice: ¿qué hilos se unirán al pulsar la D? ¿Y la tecla 0? Escríbelo y comprueba con el programa de descubrimiento.
- Dibuja la matriz: pinta una tabla de 4×4 con las filas y columnas y escribe en cada celda qué hilos se unen.
- Cuenta pines: una matriz de 5×5 tiene 25 teclas y necesita 10 pines. ¿Cuántas teclas se leerían con 12 pines si repartes 6 y 6?
- Combinaciones: un código de 4 dígitos con teclas del 0 al 9 tiene 10 000 combinaciones. ¿Cuántas con 6 dígitos?
- Mide el rebote: quita el
delay(20)y quita también la variableultima. Pulsa una tecla rápido y cuenta cuántas veces sale. - Cambia una variable: cambia
LOWporHIGHen la lectura y observa qué ocurre. ¿Por qué falla? - Debate: ¿es seguro un código de 4 dígitos para proteger algo importante? ¿Qué le falta?
Retos
- Reto 1: haz que funcione y comprueba las 16 teclas.
- Reto 2: cambia los pines por otros libres y adapta el programa.
- Reto 3: enciende un LED cada vez que pulses una tecla.
- Reto 4: guarda las cuatro últimas teclas y compáralas con un código secreto, por ejemplo 1234.
- Reto 5: si el código es correcto, mueve el servo del Chisme 141 para abrir la máscara.
- Reto 6: muestra los asteriscos del código en la pantalla OLED del Chisme 128.
- Reto 7: apunta la hora de cada pulsación con el reloj del Chisme 142.
- Reto 8: convierte el proyecto en una pequeña investigación: ¿cuántos milisegundos dura el rebote de tu teclado?
Qué hemos aprendido
Has leído 16 teclas con solo 8 pines, has descubierto con un programa qué hilos son filas y columnas y has comprobado que un teclado no sabe qué tecla es cada una: lo sabe el programa. Has visto qué hace una resistencia pull-up y por qué hay que controlar el rebote y las repeticiones.
La Gata Montesa miró el antebrazo del traje.
—Ahora sí. Pulsa el 5.
El Lince pulsó el 5 y el monitor serie dijo, muy serio: «Tecla: 5».
—¡Funciona! —gritó.
—Claro. Ya sabe que existe —dijo la Gata—. Mañana le ponemos un código.
