Neste sketch será feita a varredura matricial de dois grupos de 5 push-buttons utilizando novamente o circuito integrado 74HC595, um registrador de deslocamento.
Link para a simulação aqui.
Os botões foram posicionados da seguinte maneira:
Os terminais de D0 até D4 foram conectados às saídas Q1 até Q5 do mesmo registrador de deslocamento utilizado anteriormente. Assim, ao colocar nível alto no terminal D0, por exemplo, se for verificado nível alto no terminal T1, é certo que o botão SW101 foi pressionado, polarizou o transistor, fazendo-o atuar como chave fechada. O mesmo vale para o terminal T2 e o botão SW102. A mesma lógica é utilizada para o restante dos botões.
Como os botões são mecânicos, é necessário realizar o debounce via software, que tem a função de esperar o estado do botão estabilizar para assim atualizar seu valor.
Código
static int valor = 0x0000;
static unsigned char tempo;
void kpInit(){
pinMode(DIR, INPUT); // Configura as portas como entrada
pinMode(ESQ, INPUT);
}
int kpRead(){
return valor; // Retorna o valor atualizado na função kpDebounce()
}
void kpDebounce(){
static int novo = 0x0000; // As duas variáveis static não são descartadas quando o código sai da função
static int antigo = 0x0000; // As duas declarações só são executadas na primeira chamada da função
for (unsigned char i = 0; i<5; i++){
serialWrite(1<<(i+1)); // Liga as portas Q1 até Q5, uma por vez
if (digitalRead(DIR)){ // Verifica se o botão referente à porta ligada na linha anterior foi apertado
novo |= (int)1<<i; // Coloca o bit em 1 se o botão foi pressionado
}
else{
novo &= ~(1<<i); // Coloca o bit em 0 se o botão não foi pressionado
}
if (digitalRead(ESQ)){
novo |= (int)1<<(i+5);
}
else{
novo &= ~(1<<(i+5));
}
}
if (novo == antigo){ //Se os botões estabilizaram
tempo--;
}
else{ //Ruído
antigo = novo;
tempo = 12;
}
if (!tempo){ // Entrada estabilizada durante 12 chamadas da função debounce
valor = novo; // Atualiza o valor retornado por kpRead, em que cada bit representa um botao ligado ou desligado
}
}
A função kpInit() configura as entradas digitais. A função kpDebounce() verifica se o estado dos botões tornou-se estável por 12 chamadas da função e atualiza a variável que representa o estado dos botões. Por tal motivo essa função deve ser executada continuamente no loop principal do código. A função kpRead() apenas retorna o valor atualizado dos botões pela função de debounce.
A função serialWrite() utilizada na rotina de debounce é a mesma implementada no artigo anterior e tem a função de atualizar as saídas do circuito integrado registrador de deslocamento que devem estar ativas.
As funções principais, no exemplo da simulação, fazem a análise do valor do teclado, imprimindo no monitor serial quais teclas estão ativas:
#define DS 8
#define EN 10
#define CLK 11
#define DIR 12
#define ESQ 13
void setup(){
serialInit();
kpInit();
Serial.begin(9600);
}
void loop(){
kpDebounce();
static int a;
a = kpRead();
if (a){
Serial.print("Teclas pressionadas: ");
for (int i = 0; i< 10; i++){
if (a & 1<<i){ // Analiza cada bit da variável que representa o estado dos botões
Serial.print(i);
Serial.print(" ");
}
}
Serial.print("\n");
}
}
Conclusão
Neste artigo foi apresentada a leitura de um teclado matricial fazendo novamente o uso do circuito integrado registrador de deslocamento (HC74595) e uma maneira de resolver o problema de instabilidade de um botão mecânico utilizando a rotina de debounce.
O próximo artigo tratará da comunicação com o display LCD 16×2 compatível com o HD44780, como alterar seu modo de operação para 4 bits, como criar caracteres personalizados, etc.
Todos os códigos podem ser acessados em meu GitHub.
Saiba mais
Leitura de chaves mecânicas e o processo de debounce





