[Tradução/adaptação] Como fazer um teclado – A matriz

By | 08/08/2017

Artigo original: http://blog.komar.be/how-to-make-a-keyboard-the-matrix/

Este será o primeiro e, espero eu, não o último post de uma série sobre teclados. Meu desejo é fazer deles um tutorial para se projetar um teclado a partir do zero. Hoje eu irei falar de entrada/saída digital e matrizes de teclados. Relembre seus conhecimentos básicos de eletrônica do ensino médio e vamos começar.

Por que matriz?

Primeiramente, por que fazer uma matriz? Bem, a razão mais importante são as limitações físicas dos microcontroladores usados para fazer um teclado. Microcontroladores e circuitos integrados de lógica programável crescem junto com o número de pinos, e crescimento significa mais potência, capacidades e, acima de tudo, um preço maior. No fim das contas você pode ou usar um circuito integrado barato com baixa capacidade (que atenda suas necessidades) mas com poucos pinos de entrada/saída, ou um circuito integrado mais poderoso, que é muito maior do que o necessário. E apenas com um circuito integrado grande você tem pinos suficientes para fazer um teclado.

Por décadas tem sido prática comum em eletrônica aumentar o número de canais de comunicação de processadores e controladores de diversas maneiras. Uma dessas maneiras que funciona bem para contatos mecânicos (botões) é através de uma matriz. Para poder explicar como uma matriz funciona, será necessário conhecimento prévio básico. Por favor, revise a Lei de Ohm antes de continuar.

Um pouco de teoria

Para entender como eletrônica digital funciona, você precisa entender 2 princípios básicos:

O Princípio um é que não existe o conceito de enviar ou receber nada em comunicação. O que você faz para permitir que 2 dispositivos comuniquem-se entre si é meramente conectar seus pinos com um material condutor. Então você pode assumir que o estado deste material (tensão e corrente) será o mesmo em ambos os lados. Obviamente isso não é verdade na vida real, mas para comunicações lentas e condutores curtos isso funciona bem desta maneira. Então, na realidade, enviar e receber informação torna-se compartilhar informação.

No lado transmissor você muda apenas o estado elétrico do condutor (ao impôr uma corrente ou tensão constante) e conta com o fato de que o receptor será capaz de detectar esta mudança e entendê-la de maneira adequada.

Este princípio também implica que não há conexão entre a direção da comunicação e a direção do fluxo da corrente, o que é um erro que muitas pessoas fazem e que impede-as de entender como eletrônicos funcionam.

Quando você quer “enviar” um estado lógico “0”, normalmente você fará isso fazendo com que a tensão seja 0V, isto significa que a corrente tem de fluir para o seu transmissor para que o receptor seja capaz de dizer que isso é um “0” (uma vez que a direção oposta ao fluxo da corrente seria possível apenas se houvesse uma tensão negativa em algum lugar do circuito, e isso geralmente não é verdade em eletrônica digital). Por outro lado, quando você “envia” um “1” lógico, você geralmente representa isso com a mesma tensão da fonte de alimentação, como isso normalmente é a tensão mais alta do circuito, a corrente tem de fluir saindo do transmissor.

O Princípio número dois diz que não há maneira de ler o estado de um condutor sem modificar este estado. Não importa se você quer ler a tensão ou corrente, você precisa que elétrons fluam através do dispositivo com o qual você faz a medição. Fluxo de elétrons significa fluxo de corrente, e fluxo de corrente significa que a corrente e a tensão mudam no nó que você está medindo (conferir as Leis de Kirchhoff para circuitos elétricos). Isso quer dizer que se você quer “enviar” informação mudando o estado de um pino eletricamente conectado a outro pino, você tem que ser capaz de manter este estado, e isso quer dizer atender a todas as condições impostas pelo receptor.

O botão

Um botão Cherry MX. Foto cortesia da wiki da Deskthority

Um botão mecânico (a palavra mecânico tem nada a ver com teclados mecânicos neste contexto) é simplesmente um contato metálico que pode tanto conectar dois pinos eletricamente ou não. Existem outros tipos de botões que são mais complicados e têm mais pinos, mas não falaremos deles aqui, já que não são usado em teclados.

Então, como conectamos um botão à entrada de um microcontrolador? Um dispositivo de entrada básico detecta 2 estados lógicos possíveis: “0” e “1”. Uma prática comum é considerar tensões próximas de 0V como “0” e tensões próximas da fonte de alimentação (tipicamente 5V ou 3,3V) como “1”. O problema com um botão mecânico é que ele não pode controlar a tensão por si próprio. Ele pode apenas controlar a corrente de tal maneira que, se conectarmos dois nós de potenciais distintos com um botão, uma corrente fluirá se e apenas se o botão for pressionado.

Mas se usarmos um resistor, nós podemos converter corrente em tensão de uma forma bem simples.

Um botão com um resistor de pull-up

Veja o diagrama esquemático à esquerda. Quando o botão não está pressionado (não conduzindo) não há corrente fluindo através dele, então a tensão do nó A é próxima à de VCC (menos que VCC por causa da queda de tensão no resistor, que é R * I). Quando o botão é pressionado (conduzindo), a corrente flui através do resistor até o terra. Como a resistência de um botão é muito baixa (na faixa das centenas de miliohms), a tensão no nó A será próxima de 0.

Nesta configuração este resistor é chamado de resistor de pull-up, porque ele está “puxando para cima a tensão” para o nível de VCC num local onde não haveria uma tensão de outra forma (este estado seria chamado de “flutuante” ou estado de alta impedância).

Entretanto, muitos microcontroladores modernos já possuem resistores de pull-up em seu interior e na maioria dos casos você pode programar o microcontrolador para ligá-los ou desligá-los em tempo de execução. Então a regra básica ao conectar um botão a uma entrada é conectar um pino do botão ao pino do microcontrolador e o outro pino do botão ao terra. Desta maneira o microcontrolador sempre lerá “1” quando o botão não estiver pressionado, e “0” quando estiver pressionado. Isso pode parecer um pouco contra-intuitivo num primeiro momento, mas esta é a solução mais popular.

Repare que se deixarmos um dos pinos do botão desconectados, ele fará absolutamente nada, já que, pressionado ou não, ele não afetará o estado elétrico do pino do microcontrolador. Nós iremos utilizar esta propriedade quando construirmos a matriz.

O princípio da matriz

O princípio básico de uma matriz de teclado é que nós conectamos mais de um botão a uma única entrada de um microcontrolador.

Múltiplos botões, uma entrada (nó A)

Nós podemos usar transistores ou saídas propriamente configuradas do microcontrolador para conectar um único botão ao terra de cada vez, enquanto os outros estão flutuando. Os outros pinos de cada botão são conectados a uma entrada do microcontrolador. Eu omiti o resistor de pull-up deste circuito, assumindo que já exista um dentro do circuito de entrada do microcontrolador. Nós “ligamos” um botão por vez ao conectar seu pino número 1 ao terra, e podemos usar a entrada para ler seu estado a partir do pino número 2. Os outros botões conectados à esta entrada não mudam seu estado porque seus pinos número 1 não estão conectados a nada no momento. O circuito à direita ilustra esta ideia. A é a única entrada e C1Cn são saídas. Uma das saídas em “0” lógico significa que o pino está conectado de alguma forma ao terra dentro do circuito integrado, e também implica que a corrente sempre fluirá para este pino (como mostrado no princípio básico um). Agora, quando o botão conectado a esta saída é pressionado, a entrada A é puxada para o terra através do botão, e seu estado torna-se “0”. Pressionar outros botões não causa mudanças, já que seus outros pinos não estão conectados. Quando queremos ler outro botão, nós mudamos o pino de saída que é definido para “0”, de maneira que sempre apenas um deles estará definido desta forma.

Esta configuração (na qual uma saída está ou conectada ao terra ou não-conectada) é chamada de dreno aberto (open-drain, OD) – ou, por razões históricas, coletor aberto (open-collector, OC). Usei uma simplificação aqui, na verdade o pino não pode estar não-conectado a não ser que esteja mecanicamente desconectado, mas para entrada/saída digital básica esta premissa é boa o suficiente. A maioria dos microcontroladores permite que o programador configure os pinos de saída para trabalhar em modo OD. Mas o que acontece quando não temos esta opção? A outra configuração possível é o modo push-pull e ele é mais comum atualmente. Isso quer dizer que no estado “0” o pino ainda é puxado para estado lógico baixo (ao terra), mas quando a saída é definida em “1” o pino é puxado para VCC, então ele é capaz de fornecer corrente, ao invés de ficar flutuando.

O que isto muda no projeto da matriz? Bem, se não pressionarmos múltiplos botões ao mesmo tempo, então nada. Se pressionarmos, apenas imagine a situação na figura acima. Ao pressionar quaisquer dois botões, você eletricamente conecta duas das saídas num loop simples. Se um deles for “0” e o outro for “1”, então uma corrente começará a fluir da saída definida como “1” para a saída definida como “0”. Como não há limitação desta corrente (não há resistores), não apenas o circuito pode se tornar instável, mas isso pode na prática fazer com que o circuito integrado queime. Sem contar que seria difícil fazer uma leitura confiável do estado.

Adicionando mais fileiras

Você pode considerar este exemplo como uma matriz de uma fileira. Agora o que precisamos fazer é adicionar mais fileiras. Se nós podemos compartilhar um pino de entrada com uma fileira inteira de botões, nós também podemos compartilhar cada uma das saídas com uma coluna inteira sob a condição de que cada um dos botões da coluna esteja conectado a uma entrada diferente.

Matriz básica de teclado

Se organizarmos os botões para formar uma matriz propriamente dita, esta condição é automaticamente satisfeita. E a imagem à esquerda mostra como se parece uma matriz de n colunas e m fileiras (ignore a sobreposição em verde por enquanto).

A forma como uma matriz é lida é simples. Nós lemos uma coluna por vez. A coluna a ser lida é selecionada conectando uma das colunas C1Cn ao terra (ao definirmos a saída em modo OD para “0”). Agora cada uma das fileiras R1Rm pode ser usada para ler o estado de um botão na coluna selecionada. Os botões das outras colunas não interferem, mesmo pressionados, porque seus outros pinos estão flutuando (ou em estado de alta impedância (Hi-Z), como isso é chamado em eletrônica).

Depois que uma coluna inteira é lida, nós podemos prosseguir para a próxima mudando o pino que é aterrado. Um escaneamento de matriz é completado depois que todas as colunas forem lidas. Se isso for feito rápido o suficiente, os intervalos entre a leitura de colunas torna-se imperceptível, mesmo para digitadores muito rápidos. Mesmo quando usamos um microcontrolador de apenas 16MHz, nós podemos facilmente escanear uma matriz inteira milhares de vezes por segundo, quando o digitador mais rápido no teste de digitação do site hi-games.net consegue 203 wpm, o que equivale a pouco menos de 17 toques por segundo.

Projetar um teclado usando uma matriz diminui o número de pinos necessários para ler todos os botões. Obviamente, para reduzir este número ao mínimo possível, você precisa projetar uma matriz de maneira que o número de colunas seja o mais próximo possível ao número de fileiras. Na situação ideal, na qual o número de botões é , o melhor que podemos conseguir com uma matriz são 2n pinos. Porém, na maioria das situações as matrizes não são projetadas para usar tão poucos pinos, já que normalmente microcontroladores possuem um bom número deles que podem ser utilizados. Tentar otimizar um matriz desta maneira pode ser difícil, porque isso pode levar a uma bagunça quando do roteamento da placa de circuito impresso final. Normalmente é muito mais conveniente tentar seguir o posicionamento físico dos botões, o que significa que para um teclado de computador padrão a matriz mais fácil de projetar terá apenas 6 fileiras e um número de colunas dependente do layout. Esta solução é muito sub-otimizada do ponto de vista da utilização de pinos, mas pelo menos torna o roteamento mais fácil.

E se não tivermos saídas OD?

Você pode se perguntar o que fazer caso o microcontrolador escolhido não tiver o modo OD. Bem, nós já sabemos o que pode acontecer e que não é uma boa ideia fazer um pull-up forte a qualquer uma das saídas (isso significa “conectar” diretamente ao VCC). Existem diversas maneira de resolver este problema incluindo buffers de saída OD especiais e até mesmo circuitos shift register com saídas OD para diminuir ainda mais a contagem de pinos. Mas existe uma solução muito popular usada em teclados de computador (na verdade mais popular em épocas passadas).

Problema com saídas push-pull

O problema com saídas push-pull controlando colunas aparece quando dois botões são pressionados simultaneamente na mesma fileira e enquanto a coluna na qual um deles se encontra está sendo escaneada. A corrente flui da saída definida em “1”, ao invés de estado de alta impedância, através do outro botão, então através daquele que está na coluna escaneada até a saída definida como “0”. Isso pode resultar em qualquer coisa desde não poder ler confiavelmente o estado de um teclado até o circuito integrado ser destruído.

Mas há um macete fácil que podemos usar para converter saídas push-pull para algo parecido com OD se realmente precisarmos e eu tenho visto esta solução em muitos teclados antigos. Como os pinos de saída (coluna) precisam apenas receber corrente e nunca fornecê-la, nós podemos usar diodos para limitar a direção das correntes. Um diodo é um dispositivo simples que permite que a corrente flua em apenas uma direção. A seta no símbolo elétrico significa a direção da corrente. Ao inserir um diodo entre cada pino de coluna e o fio da coluna (que depois irá para cada botão desta coluna) nós permitimos que a corrente apenas flua para os pinos. Desta forma o pino definido em “1” nunca irá fornecer corrente e isso quase o torna em um pino OD. É claro que isso não é um OD real, mas resolve o problema do loop de corrente numa matriz de teclado. Volte ao primeiro circuito de matriz, mas desta vez considere a sobreposição em verde para ver como esta solução se parece.

É claro que para limitar o número de diodos usados você pode tentar reduzir o número de colunas à custa do número de fileiras, e se isso não se encaixar com o layout físico do teclado, então “rotacione” a matriz em 90 graus (troque fileiras com colunas). As possibilidades são ilimitadas. Mas por causa da grande variedade e facilidade de uso de microcontroladores amigáveis para hobbistas, este método praticamente nunca será usado em teclados feitos por hobby. Ainda bem.

Ghosting

Se você gosta de teclados, você certamente já ouviu esta palavra antes, e parece que é um termo frequentemente não-compreendido no mundo dos teclados.

Exemplo de ghosting

Nós já vimos como pressionar múltiplas teclas de uma mesma fileira pode atrapalhar as leituras, mas este problema já pode ser considerado resolvido. Agora veremos o que acontece se múltiplas teclas são pressionadas tanto na mesma fileira quanto na mesma coluna.

Na ilustração à direita três botões são pressionados simultaneamente. Dois deles compartilham a coluna 2 e dois a fileira m. Isso significa que um desses três botões pressionados compartilha sua fileira e sua coluna com algum outro botão pressionado. Esta situação é normalmente chamada de *ghosting*. Suponha que nós estejamos lendo a coluna 1 (então seu pino de saída está sendo aterrado – estado “0”). Por causa desta configuração específica de botões pressionados, mesmo que o botão restante (no canto superior esquerdo da ilustração) não esteja pressionado, o estado da linha R2 é “0” porque ele está sendo aterrado por C1 (no momento em “0”) através de todos os 3 botões pressionados. Isto faz com que o controlador leia o estado desta tecla como “pressionado” independente dele estar realmente pressionado ou não. A palavra ghosting vem do fato de que algumas combinações de teclas pressionados em conjunto causam estes pressionamentos “fantasmas” (“ghost” em inglês), mesmo que as teclas não estejam fisicamente sendo pressionadas.

Existem diversas maneiras para impedir que o ghosting atrapalhe o trabalho de um digitador ou a jogatina de um gamer e elas são amplamente utilizadas em todos os teclados para PC. Na verdade é possível detectar uma situação onde um fantasma pode aparecer e impedir que isso aconteça. Uma vez que uma pessoa comum não é capaz de pressionar ou soltar 2 teclas exatamente no mesmo instante, com um escaneamento rápido o bastante podemos assumir que entre 2 escaneamentos apenas uma única tecla irá mudar seu estado. Desta maneira o controlador do teclado pode processar um toque por vez e procurar situações onde 2 ou mais teclas ficaram pressionadas ao mesmo tempo entre dois escaneamentos. Assumindo que o teclado está escaneando rápido o bastante de modo a não permitir que tais situações aconteçam voluntariamente, sua ocorrência significa que uma das teclas recentemente pressionada é um fantasma. Neste caso o teclado deverá ignorar ambos os pressionamentos e é mais seguro esperar até que ambos sejam liberados antes de enviar qualquer mudança de estado para o PC.

Uma abordagem alternativa é detectar situações em que a “terceira” tecla é pressionada e suprimí-la e quaisquer teclas posteriores até que seja liberada e a situação volte ao normal. Para usar esta abordagem o firmware deve se lembrar quais teclas foram pressionadas (o que ele já faz normalmente de qualquer maneira) e impedir teclas em que ambas a coluna e a fileira já tenham uma tecla pressionada nelas. Com um pouco de programação inteligente não seria necessário bloquear todos os toques subsequentes exceto aqueles que causam o problema, a não ser que eles quebrem esta regra de novo. Se o controlador do teclado bloquear cada tecla em que ambas a coluna e a fileira já tenham uma tecla pressionada, algumas teclas não serão registradas dependendo do estado das outras teclas. Esta situação é normalmente chamada de jamming (“emperramento”). O termo faz sentido se você imaginar que são outras teclas pressionadas que fazem com que algumas outras parem de funcionar, como se estivessem “emperrando” parte do teclado.

Do ponto de vista do usuário, ele sempre pode pressionar todas as teclas de uma coluna ao mesmo tempo (se não estiver pressionando teclas de outras colunas), mas ele pode pressionar ao mesmo tempo teclas da mesma fileira apenas se houver no máximo uma tecla pressionada em cada coluna. O mesmo vale para pressionar teclas de uma mesma coluna. Outras teclas pressionadas só são permitidas se estiverem em fileiras diferentes daquelas já “ocupadas”.

Os termos ghosting e jamming são confundidos com frequência maior do que eu imaginava, já que ambos são bem intuitivos para mim.

Não é possível não ter nem ghosting nem jamming num teclado que use uma matriz como as que mostrei acima. Uma vez que o ghosting é inaceitável para um usuário comum, praticamente todos os fabricantes de teclados de domo de borracha usam alguma abordagem anti-ghosting, o que introduz o jamming. Como projetar uma matriz de tal maneira que o jamming atrapalhe o mínimo possível, e que combinações típicas de teclas não causem jamming é um bom assunto para um livro inteiro e é a razão pela qual as matrizes de teclados produzidos em massa são tão bagunçadas.

Diodos em todos os botões — a solução definitiva

Se você olhar de novo o circuito de exemplo de ghosting, verá que o culpado é o botão inferior direito.

Versão final da matriz

Mas este botão é o único onde a corrente flui “para cima” neste caso, e já que não precisamos de corrente alguma subindo para ter uma leitura apropriada da matriz, podemos usar diodos para permitir que a corrente flua apenas para as saídas das colunas ativas na parte inferior do circuito. Infelizmente isso requer um diodo para cada botão. Em relação à direção, você já deve ser capaz de perceber que neste exemplo em específico eles têm de conduzir a corrente “para baixo”, então seus catodos (o lado pontudo) deve estar virado para as saídas (colunas), estando os anodos apontados para as entradas (fileiras). Qual lado do botão está não importa, desde que ele corretamente polarizado. Apenas lembre que nesta abordagem a corrente sempre flui da entrada para a saída. Por sinal isto é o que sempre acontece com entradas pull-up e saídas OD.

Esta abordagem limita a corrente de maneira que ela flua apenas “para direita” e “para baixo”, então ela impede que o loop apareça quando múltiplas teclas são pressionadas. Este também é o único circuito que permite teclados totalmente NKRO. Apesar de parece óbvio, também é bom reparar que usar um diodo em cada botão elimina a necessidade de usar saídas OD, já que os diodos em série com os botões lidam com o problema do curto-circuito da mesma maneira que a solução de um único diodo por coluna.

Rollover

Eu sei que este artigo já está bem comprido, mas acho que preciso adicionar este último capítulo para deixá-lo completo. Rollover é a habilidade de um teclado suportar múltiplos toques ao mesmo tempo.

xKRO

KRO significa key roll over e normalmente vem depois de um número. Então, por exemplo, ele pode ser 2KRO, o que significa rollover de 2 teclas. Um teclado tem x key rollover se e apenas se suportar x teclas pressionadas ao mesmo tempo independente de quando isso aconteça e quais teclas sejam. A maioria dos teclados de domo de borracha vendidos atualmente são 2KRO. Isso não quer dizer, entretanto, que este seja o limite de teclas pressionadas ao mesmo tempo em todos os casos. Ele apenas diz que o teclado tem a garantia de sempre suportar x teclas ao mesmo tempo.

Dependendo do layout da matriz e do controlador usado, 2 teclados com 2KRO podem se comportar de maneiras bem distintas. Alguns podem sempre registrar no máximo apenas 2 toques simultâneos, e outros podem registrar com facilidade mais do que isso. Neste caso 2KRO pode ser anunciado apenas porque há algumas combinações de teclas (de preferência incomuns) que impedem que outras teclas sejam pressionadas ao mesmo tempo. Uma vez que isso significa que existem combinações de 3 ou mais teclas que não podem ser pressionadas juntas, a companhia declara apenas 2KRO.

NKRO

O termo NKRO significa n key rollover e é utilizado para descrever um teclado que suporta qualquer combinação de teclas pressionadas ao mesmo tempo independente da situação. Lembre-se, entretanto, que há uma diferença entre o NKRO da matriz do teclado e o NKRO do próprio teclado. Mesmo que a implementação da matriz que mostrei neste artigo sempre suporte NKRO com um firmware adequado, isso não necessariamente é verdade para um teclado que use esta matriz. Isto acontece por causa de várias limitações das portas de comunicação usadas por teclados e por causa de cortes de gastos dos fabricantes. Tentarei descrever o problema do NKRO em portas PS/2 e USB nos próximos artigos.

Resumo

Esta pode ter sido uma longa leitura, mas o conceito não é tão fácil de compreender, especialmente para alguém que não seja um engenheiro elétrico/eletrônico. Espero ter explicado de forma clara, já que tentei ser o mais didático possível. Talvez o artigo seja entendiante para alguns de vocês, mas se você gosta de eletrônica então provavelmente não precisava ler isso no fim das contas. 😉

De qualquer forma, por favor diga-me se este texto teve algum valor para você e se faz sentido escrever partes futuras e começarei a trabalhar no próximo “episódio”.

† Aqui o autor faz um trocadilho intencional e intraduzível: “and it’s the reason the matrices in mass-produced keyboard are so messy and jammed (pun intended).”