12 de jun de 2011

Projeto básico - Utilizando um teclado com o arduino e exibindo o resultado em um display de LCD


Teclados

Teclados são dispositivos de entrada normalmente utilizados para realizar a interface do homem com a máquina. Os teclados matriciais como o usado neste projeto são os mais conhecidos devido a sua arquitetura simples e fácil integração com microcontroladores.
Figura 1 - Teclado matricial estilo membrana.

Lendo os dados enviados por um teclado

Existem vários métodos de se ler dados enviados por um teclado e estes basicamente se diferenciam pela maneira com que são conectados a um microcontrolador, mas a lógica permanece a mesma.

No micro controlador as colunas são definidas como pinos de entrada e as linhas como pinos de saída.

 Figura 2 - Detalhe das conexões de um teclado matricial.


Primeiro definimos as linhas como pinos de saída em nível alto (HIGH) e as colunas como pinos de entrada com nível baixo (LOW).
Para detectar qual tecla foi pressionada cada linha recebe individualmente nível lógico alto e todas as colunas recebem nível baixo, o micro controlador espera alguma mudança de estado nas colunas, se uma tecla foi pressionada o nível alto será enviado para a entrada do micro processador, pois as colunas foram definidas como pinos de entrada.
Para garantir níveis altos e baixos nos pinos de entrada do microcontrolador podemos utilizar resistores de pull-up ou pull-down.

 Figura 3 - Esquema de funcionamento individual.

Analisando a imagem acima, sabemos que não teremos tensão na coluna C1 pois ela está  ligada a uma resistência de 10K e ao terra, mas se pressionarmos a chave que interliga L1 com C1 teremos 5 volts em cima do resistor, estes 5 volts serão interpretados como lógica alta pelo arduino toda vez que a chave for pressionada.

Interface

Todas as linhas deverão ser conectadas diretamente ao arduino e as colunas devem ser ligadas a uma resistência aterrada como mostra a figura abaixo:


Figura 4 - Esquema de ligação simplificado

Infelizmente em um teclado comercial como o de membrana não é possível ver as conexões internas, portanto deveremos medir continuidade em todos os contatos de saída.
Fixa-se uma ponta do multímetro em um dos terminais e se pressiona uma tecla (mantenha a tecla pressionada) e coloque a outra ponta do multímetro em outro terminal. Veja se entre esses dois pinos há condutividade, se não houver coloque a segunda ponta do multímetro em outros terminais até confirmar condutividade. Fazendo isto você terá descoberto  a união entre uma linha e uma coluna, continue com este procedimento até descobrir todas as colunas e todas as linhas.

O teclado de 4 linhas por 3 colunas utilizado neste projeto terá um total  de 7 saídas, cada saída será ligada ao arduino através de um fio ou conexão, veja abaixo os resultados que encontrei depois da medição com o multímetro.
  • COLUNA 1 = Fio 4
  • COLUNA 2 = Fio 3
  • COLUNA 3 = Fio 2
  • LINHA 1 = Fio 1
  • LINHA 2 = Fio 5
  • LINHA 3 = Fio 6
  • LINHA 4 = Fio 7

Após descobrir a função de cada fio, vamos definir em quais pinos eles entraram no arduino:


#define col1 13 // Com resistor de pull down                                                                
#define col2 12 // Com resistor de pull down 
#define col3 6 // Com resistor de pull down 
#define l1 10
#define l2 9
#define l3 8
#define l4 7


Figura 5 - Esquema de ligação das colunas com os resistores. As linhas devem ser ligadas diretas no arduino.



O código


#include <LiquidCrystal.h>  // Biblioteca com funcoes para uso de um LCD baseado no Hitachi HD 44780 
LiquidCrystal lcd(1, 0, 5, 4, 3, 2);// Define os pinos de ligacao do LCD ao arduino com esta ordem LiquidCrystal(rs, enable, d4, d5, d6, d7)
#define col1 13 // Com resistor de pull down                                                                
#define col2 12 // Com resistor de pull down 
#define col3 6 // Com resistor de pull down 
#define l1 10 // Linha 1
#define l2 9
#define l3 8
#define l4 7 // Linha 4

void setup()
{
/*lcd.begin(cols, rows) */
lcd.begin(20, 4); /* Tipo de LCD usado no meu caso de 20 colunas por 4 linhas */
lcd.print("    Central AVR!");
   
// Declarando as colunas como INPUT, fios 4,3,2 do teclado
pinMode(col1,INPUT); /* Coluna 1, fio 4 */
pinMode(col2,INPUT); /* Coluna 2, fio 3 */
pinMode(col3,INPUT); /* Coluna 3, fio 2 */

// Declarando as linhas como OUTPUT fios 1,5,6,7 do teclado
pinMode(l1,OUTPUT); /* Linha 1, fio 1 */
pinMode(l2,OUTPUT);
pinMode(l3,OUTPUT); 
pinMode(l4,OUTPUT); /* Linha 4, fio 7 */  
}

void loop() 
{
int l[]={l1, l2, l3, l4}; // Array de 4 posições contendo os 4 pinos de linhas
int i=0;  
int k=0;
int tecla_apertada=0;
for (i=0; i<4; i++)
{
digitalWrite(l1,LOW); 
digitalWrite(l2,LOW);
digitalWrite(l3,LOW);
digitalWrite(l4,LOW);
digitalWrite(l[i],HIGH); // Torna uma linha alta por vez
   k=i*3; // Responsavel pela mudança de valores nas linhas após cada ciclo do for
  if(digitalRead(col1)==HIGH) // Se alguma tecla da coluna 1 for apertada executa o código abaixo
  {
    delay(10);
    tecla_apertada=k+1;
    lcd.setCursor(0, 1); /* O Cursor iniciara na coluna zero linha 3 */
    lcd.print("Coluna 1: ");
    lcd.print(tecla_apertada);
    k=0; 
  }

  if(digitalRead(col2)==HIGH)
  {
    delay(10);
    tecla_apertada=k+2;
    lcd.setCursor(0, 2); /* O Cursor iniciara na coluna zero linha 3 */
    lcd.print("Coluna 2: ");
    lcd.print(tecla_apertada); 
    k=0;
  }
 if(digitalRead(col3)==HIGH)
  {
    delay(10);
    tecla_apertada=k+3;
    lcd.setCursor(0, 3); // O Cursor iniciara na coluna zero linha 3 
    lcd.print("Coluna 3: ");
    lcd.print(tecla_apertada);
    k=0; 
  }
}

}


Algumas explicações sobre o funcionamento do programa.

A parte mais "complexa" deste código reside no laço do for onde utilizei um array para organizar a mudança para lógica HIGH das linhas, lembrando que o mesmo deve ser feito individualmente.


for (i=0; i<4; i++)
{
digitalWrite(l1,LOW); 
digitalWrite(l2,LOW);
digitalWrite(l3,LOW);
digitalWrite(l4,LOW);
digitalWrite(l[i],HIGH); // Torna uma linha alta por vez
   k=i*3; // Responsavel pela mudança de valores nas linhas após cada ciclo do for
.
.
.
.
.
}


Supondo i=0 a condição do for será verdadeira e o código dentro do laço será executado, todas as linhas são setada em nível LOW e apenas a linha 1 será setada em nível HIGH pois i=0 e no array l[] posição zero temos l1.
 digitalWrite(l[0],HIGH); // Torna uma linha alta por vez

O código executará até o final das condições(IF) e se não não for pressionada nenhuma tecla novamente todas as linhas receberão nível lógico LOW e somente a linha 2 será setada em nivel HIGH pois i=1 e no array l[] posição um temos l2.
digitalWrite(l[1],HIGH); // Torna uma linha alta por vez

k=i*3 é uma jogada para retornar um valor condizente com a linha com lógica HIGH, novamente supondo  i=0 ou seja a primeira execução do for temos k=0*3 portanto k=0 se a primeira coluna foi acionada o valor a ser impresso será 1 pois tecla_apertada=k+1;
Supondo i=1 ou seja a segunda execução do for temos k=1*3 portanto k=3 se a terceira coluna foi acionada o valor a ser impresso será 6 pois  tecla_apertada=k+3;
 

 
Resultado final