Questions about keyboard programming.

User avatar

27 Feb 2019, 04:16

Hello again. I have to obligatory make a project for my last year of school and I want to make an Arduino enigma machine featuring this symbols:

a b c d e f g h i j k l m n ñ o p q r s t u v w x y z A B C D E F G H I J K L M N Ñ O P Q R S T U V W X Y Z 1 2 3 4 5 6 7 8 9 0 á é í ó ú ü Á É Í Ó Ú Ü , . ; : ( )

I want to know a little bit more of keyboards before start this project.
So, when a keyboard scans a key, what comes to my mind is the idea of a loop with all the rows and columns waiting until a value between a row and a column changes to "true", is that right?
If it is like that, is the only way to make it work or there is more alternatives?
In a row to column keyboard, how do you know when X column is connected to what row if the row is giving current and not receiving it?


27 Feb 2019, 07:07

You "strobe" one column at a time by outputting a logical 0 to that column, and only that column. The other columns get logical ones.
Each time, you first wait a couple microseconds (why, I'm not sure, but it is recommended for the matrix to "settle").
After the wait, you read the rows. Each row has a pull-up resistor. A logical 0 on one row's input means that the key is pressed on the current column and that row. Then you strobe the next column, and so on.

A switch connects one column to a row at a junction. Diodes are put in series with the switch at each junction to prevent current from flowing the wrong way through multiple pressed keys when you strobe another column. This is explained better on the wiki in Rollover, blocking and ghosting.

However, key switches have contact bounce for about 5 ms, so you need also to debounce the scanned input by waiting for the signal to be stable for some time. You need to do that either on the both press and release, or on only press or only on release.

Some firmwares scan the matrix continuously, over and over again, and when they see a leading edge (or falling edge) on one key, another loop is entered waiting for only that key to stabilise using a timer. When the timer has run 5 ms with the key in the same state, the key's state is considered changed. If the input is not stable, it goes back to the main loop. This is done by TMK's firmware, I believe.

Another method for debouncing is to scan the matrix only regularly, with a delay between scans, and store the history of the last n scans in a buffer.
One variation of this (used by Soarer, I believe) is to store one byte per key and each time shift one position and enter a bit from the last scan. Then the debounced state of a key can be found by checking the byte's value against a constant. (For example if you scan the matrix once every ms and your debouncing delay is 5 ms testing for (0b00011111 & key_bits[row][column) == 0) would mean the key is pressed.)
What I do in my own firmware is instead to read each row as a bitfield and store the result from each scan into a two-dimensional circular buffer. After each scan, the debouncing routine loops through that buffer and'ing (or or'ing) bits together on each row to find the debounced matrix state.

An article that talks about debouncing (for any type of input switch) is:A Guide to Debouncing, or, How to Debounce a Contact in Two Easy Pages, by Jack Ganssle. Just skip over the sections about debouncing in hardware, as they don't apply to matrices.

User avatar

27 Feb 2019, 08:51

I already made something in Arduino, but thanks! I didn't mind about the debouncing part. I'm not making a PC keyboard so is fairly easier, but I will need some more information in the future with my personal projects.

User avatar

27 Feb 2019, 10:38

Findecanor wrote:
27 Feb 2019, 07:07
Each time, you first wait a couple microseconds (why, I'm not sure, but it is recommended for the matrix to "settle").
It's because a microcontroller is scanning a voltage on an LRC circuit. Typical values are about:
R = 33 kΩ, C = 5e-12 F, L = 0.5e-3 H
You are interested mostly in the times t1=(-1/s1) and t2=(-1/s2) in the equation for I(t) in the LRC circuit wiki page. The times define how quickly the circuit setles down. For our typical values the times are 0.15 µs and 0.018 µs. The circuit is over-damped (capacitance prevails over inductance) and you can just simplify your situation by considering only RC circuit and computing a simple RC time constant t=R*C. It is 0.16 µs in our case. You can consider the circuit settled in about double the time constant, i.e. about 0.32 µs and that is the minimum time delay you should have between selecting a column/row and strobing a row/column. It is only about 10 instructions on a 32 MHz MCU. It is likely the instructions are already there and an explicit wait is not needed. Depends on the MCU and R,L,C values.


27 Feb 2019, 13:29

PlacaFromHell wrote:
27 Feb 2019, 08:51
(...)I'm not making a PC keyboard so is fairly easier, but I will need some more information in the future with my personal projects.
Spanish at the end.

That's a mixed blessing.

On one hand, if you are making an enigma machine for a school project, you can very well get off with a ridiculous dead-time between keypresses, since you'll be only demo-ing the contraption and not using it a lot. So the debouncing can be quite crude and overzealous.

On the other hand, if you manage it to be an actual PC keyboard connected to an Arduino (is that even possible?), maybe you can borrow firmware that's already perfected to a great extent and focus on the actual logic of the enigma machine, maybe a lot more interesting to an evaluator.


Por un lado: Si es para un proyecto escolar, seguro a nadie le va a importar un carajo si escribo cualquier cosa, porque pocos hablan español jaja pero te decía que seguro no te van a poner un 6 por hacer una matriz que se escanee cada medio segundo o algo ridículo e inútil como eso; lo podés sacar mas o menos andando y sigue siendo un proyectazo.

Por otro lado: si conseguis conectar un teclado USB corriendo un firmware de los que ya están probados y andando (y super bien, QMK es una joya, por ejemplo), lo sacás andando super rápido y te podés enfocar en la parte de la enigma propiamente dicha, que va a ser mucho mas copado para un profesor que lo evalúa.

Te felicito por el proyecto! Un abrazo

User avatar

27 Feb 2019, 23:06

A single bouncing can ruin an entire page of text (if I don't add a backspace). Use an USB keyboard sounds great but is quite a mess of code. I would need something that read bit per bid and discard things until it finds an entire reading. Anyway everything sounds easier than what I expect.

Un sólo bouncing me puede arruinar un texto entero si no tengo un backspace. Usar un teclado USB suena de diez pero es un quilombo de código. Tendría que leer bit por bit e ir descartando caracteres hasta llegar a una lectura completa. Al final todo suena más fácil de lo que parece. La idea es complicarlo más con más símbolos y que el espacio como tal también sea parte del encriptado.
Te devuelvo el abrazo. ¡Saludos!


28 Feb 2019, 13:34

Of course a single bouncing will mess everything up. But it is unlikely you'll need to demo the unit working with a full page of text. You can type a short 20 characters message in that many seconds with a crude but functional debouncing. For instance, once you read a character, shut down detection for 300ms for the entire grid. It actually adds up to the mojo of the gizmo XD
(And it is a good idea to add a backspace key!)

I was under the impression that having a usb-interfaced keyboard work against an arduino would not be that cumbersome, maybe I was entirely misled. But if it is indeed possible, I bet there's a tutorial around somewhere.

And if it is that the case, you can contain the keyboard logic inside the keyboard firmware and the enigma logic inside the arduino. Heck, you can put both inside the keyboard firmware and make it display things with the arduino alone.

Claro que un rebote te va a joder todo. Pero no es esperable que necesites teclear una página entera de texto para mostrar que la unidad funciona. Podés teclear 20 caracteres en otros tantos segundos con un debouncer sencillo pero funcional. Por ejemplo, cada vez que detectas un caracter, apagar la detección de nuevos caracteres por 300ms. (Y una tecla de backspace es muy buena idea.)

Tenía la impresión de que usar un teclado USB contra un arduino no era tan complicado, capaz le pifié. Si es posible, seguro hay un tutorial por ahí.

Y, si es el caso y se puede, podés contener la lógica del teclado en el controlador del mismo (cof cof QMK) y la de la enigma en el arduino. Carajo, seguro hasta podrías contener ambas en el firmware del teclado y usar el arduino solo para visualizar. Y para bonus cool points y conseguir chicas.

User avatar

28 Feb 2019, 23:44

I could try to put the entire logic in a single Arduino, even using QMK, but in any case I have to build the rocket before fly to the moon. About the display, it will be the same as the original Enigma machine (letters with some kind of backlight). I would like conect it to my Sharp ZX-410 and just see how spits the text in a piece of paper.
The only thing that fails is the part of the girls, because a technical school is like a fishing boat that passes a 7 year season sea inside. although not corresponded, I'm stilll a man in love :lol:

Podría tratar de meter todo en un sólo Arduino e incluso usando QMK, pero bueno, en cualquier caso primero armo el cohete y después voy a la luna. La parte de la visualización va a ser igual que la de una enigma normal, o sea las letras con bulbos (en este caso LED's, obviamente). No estaría mal conectarla a mi Sharp ZX-410 y que directamente te escupa una hoja con el texto.
Lo único que estaría fallando es la parte de las chicas, ya que un colegio técnico es como un barco pesquero que pasa 7 años mar adentro. Aunque no correspondido, igual soy un hombre enamorado :lol:


06 Mar 2019, 13:55

Then, divide and conquer.

The best way to solve a complex problem is splitting it down into simpler problems and solve them one at a time.

I'd say: get to the hardest part first. You need to veto or dismiss the whole project as impossible to solve as soon as possible. Succeding in that, you know you can't spend any more time on this project and go find another. Failing that, you know you will succeed and proceed with the rest. I call it the "DIYer's paranoia".

Connecting the gizmo to an electric typewriter is ballsy as heck, I hope you can pull it off, I know I could not =)

Divide y conquistaras.

La mejor manera de resolver un problema complejo es dividirlo en problemas mas simples y resolver esas partes de a una.

Yo diría: apuntale a resolver la parte mas compleja primero. Tenés que asegurarte que lo vas a poder resolver cuanto antes. (no realmente resolverlo cuanto antes, sino asegurarte de que vas a poder.) De esa manera, si ves que no vas a poder (porque a veces sencillamente no se puede, otras veces porque ya vas viendo que implica estudiar un bodoque muy grande de cosas nuevas y no vale la pena tanto esfuerzo por el resultado...) ya podés buscarte otro proyecto ANTES de invertir mas tiempo en el asunto.
Si ves que si vas a poder con esa parte mas compleja, le das para adelante. Suena contradictorio, intentar sabotear el proyecto antes de avanzar mucho: La llamo "la paranoia de DIYer".

Conectar el cuchuflo a una máquina de escribir eléctrica es muy zarpado, ojalá lo puedas lograr. Yo se que no podría =)

Post Reply

Return to “Keyboards”