fbpx

Entenda o efeito Bounce e como fazer Debounce no Arduino ao apertar um Botão

Fala pessoal, tudo certo? Bom, neste post eu vou colocar a resposta do segundo desafio postado no instagram @blogdarobotica (Link: https://www.instagram.com/p/CPEaI-SHjiC ). Se você não viu, então deixo logo abaixo o vídeo do desafio:

Inicialmente para resolver esse desafio é necessário entender algumas coisas que acontecem no circuito elétrico: Ao pressionar o botão uma única vez pode haver um efeito no qual o microcontrolador, no nosso caso o Arduino, entenda como se tivéssemos pressionado o botão mais de uma vez e esse ruído é conhecido como Bounce e gera problemas, principalmente quando o objetivo do nosso código é contar quantas vezes aquele botão foi pressionado. Abaixo vemos a ilustração do efeito Bounce, tanto acontecendo ao apertar, quanto ao soltar o botão. Com isso é possível perceber que o grande problema desse segundo desafio é justamente fazer a contagem correta de quantas vezes o botão foi pressionado, pois se não resolvermos o Bounce vai acabar havendo uma contagem incorreta mesmo que apertemos uma única vez o botão.

Esses ruídos ou trepidações precisam ser resolvidos para que possamos fazer a leitura correta do sinal e contar quantas vezes o botão foi pressionado, de fato. Existe a possibilidade de sanar esse problema via Hardware, que seria acrescentando capacitores que serviriam como filtro do sinal ou então resolver via Software, que é o que iremos fazer. Para isso monte o circuito conforme mostrado abaixo:

No Botão usamos um resistor de 10K que tem a função de PULL-DOWN, ou seja, quando o botão não estiver pressionado a porta do arduino irá ler 0v (LOW) e o resistor pull-down tem a função de deixar o estado lógico muito bem definido, ao pressionar vai ser lido o sinal 5V (HIGH) e ao soltar vai ser lido 0V (LOW). Se tirarmos esse resistor de 10K não teríamos como garantir o estado lógico do circuito. Posteriormente podemos criar uma publicação com mais detalhes sobre resistores de PULL-DOWN e PULL-UP. Já para os LEDs usamos resistores de 220 ou 330 ohms que é para garantir a limitação de corrente elétrica para que eles não queimem.

Debounce via Software

O código abaixo demonstra como depurar uma entrada, o que significa verificar duas vezes em um curto período de tempo para certificar-se de que o botão está realmente sendo pressionado, ou seja, vamos criar a solução do Bounce que é o Debounce, só que através de programação. Este código utiliza a função millis() para controlar o tempo que passou desde que o botão foi pressionado pela última vez. O código abaixo está todo comentado para facilitar o seu entendimento.

/*
  ----------- Resposta do #Desafio 2 --------------
  =================================================
  ==   BLOG DA ROBOTICA - www.blogdarobotica.com ==
  =================================================
  Autor: Kleber Bastos
  E-mail: contato@blogdarobotica.com
  Fanpage: facebook.com/blogdarobotica
  YouTube: youtube.com/user/blogdarobotica
  Instagram: instagram.com/blogdarobotica
*/


#define botao 11                       //Porta em que o botão está sendo lido
#define ledVerde 10                    //Porta em que o LED verde está conectado
#define ledAmarelo 9                   //Porta em que o LED amarelo está conectado
#define ledVermelho 8                  //Porta em que o LED Vermelho está conectado

int statusBotao;                       //Variável que irá receber o status do botão: 1 = Pressionado e 0 = Desacionado
int ultimoStatusBotao = LOW;           //Variável Backup que salvará o último status do botão:  1 (HIGH) = Pressionado e 0 (LOW) = Desacionado. Inicialmente ela começa como LOW = 0 Desacionado
int contador = 0;                      //Variável que armazenará quantas vezes o botão foi pressionado

unsigned long tempoUltimoDebounce = 0; //Variável que armazenará o tempo do último Debounce
unsigned long tempoDebounce = 50;      //Tempo (em milissegundos)que é necessário manter o botão pressionado para ter a certeza de que ele foi pressionado de fato.

void setup() {
  pinMode(botao, INPUT);               //Declara o pino do botão como entrada
  pinMode(ledVerde, OUTPUT);           //Declara o pino do led verde como saída
  pinMode(ledAmarelo, OUTPUT);         //Declara o pino do led amarelo como saída
  pinMode(ledVermelho, OUTPUT);        //Declara o pino do led vermelho como saída
}

//Função principal
void loop() {

  debounceBotao();                     //Chama a função responsável pelo Debounce
  contagem();                          //Chama a função responsável por realizar as ações dependendo da quantidade de vezes que o botão foi pressionado

}

//Função responsável por fazer o Debounce
void debounceBotao() {

  int leitura = digitalRead(botao);                       //A variável leitura recebe a leitura do pino do botão: HIGH (pressionado) ou LOW (Desacionado)

  if (leitura != ultimoStatusBotao) {                     //Se a leitura atual for diferente da leitura anterior
    tempoUltimoDebounce = millis();                       //Reseta a variável tempoUltimoDebounce atribuindo o tempo atual para uma nova contagem
  }

  if ((millis() - tempoUltimoDebounce) > tempoDebounce) { //Se o resultado de (tempo atual - tempoUltimoDebounce) for maior que o tempo que determinamos (tempoDebounce), ou seja, já passou os 50 milissegundos que é o tempo que o botão precisa ficar pressionado para ter a certeza de que ele realmente foi pressionado? Se sim faça:
    if (leitura != statusBotao) {                         //Verifica se a leitura do botão mudou, ou seja, se é diferente do status que o botão tinha da última vez. Se sim, faça:
      statusBotao = leitura;                              //statusBotao recebe o que foi lido na variável leitura (pressionado = 1 e não pressionado = 0)
      if (statusBotao == HIGH) {                          //Se o statusBotao é igual a HIGH significa que o botão foi pressionado, então faça:
        contador++;                                       //Incrementa +1 na variável contador. (contador++ é o mesmo que: contador = contador +1)
      }
    }
  }
  ultimoStatusBotao = leitura;                            //Atualiza a variável ultimoStatusBotao para o que foi lido na variável leitura

}


//Função responsável por realizar as ações de acender os leds de acordo com a quantidade de vezes que o botão foi pressionado
void contagem() {

  if (contador == 1) {                 //Se o contador for 1 significa que o botão foi pressionado uma única vez
    digitalWrite(ledVerde, HIGH);      //Acender o LED verde
    digitalWrite(ledAmarelo, LOW);     //Apaga o LED amarelo
    digitalWrite(ledVermelho, LOW);    //Apaga o LED vermelho
  }
  if (contador == 2) {                 //Se o contador for 2 significa que o botão foi pressionado duas vezes
    digitalWrite(ledVerde, LOW);       //Apaga o LED verde
    digitalWrite(ledAmarelo, HIGH);    //Acende o LED amarelo
    digitalWrite(ledVermelho, LOW);    //Apaga o LED vermelho
  }
  if (contador == 3) {                 //Se o contador for 3 significa que o botão foi pressionado três vezes
    digitalWrite(ledVerde, LOW);       //Apaga o LED verde
    digitalWrite(ledAmarelo, LOW);     //Apaga o LED amarelo
    digitalWrite(ledVermelho, HIGH);   //Acende o LED vermelho
  }
  if (contador >= 4) {                 //Se o contador for maior ou igual a 4 significa que o botão foi pressionado 4 vezes ou mais
    contador = 0;                      //Zeramos a variável contador
    digitalWrite(ledVerde, LOW);       //Apaga o LED verde
    digitalWrite(ledAmarelo, LOW);     //Apaga o LED amarelo
    digitalWrite(ledVermelho, LOW);    //Apaga o LED vermelho
  }

}

Obrigado a todos que participaram do desafio e espero que tenham aprendido coisas novas com ele.

Até a próxima! Att. Kleber Bastos.

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.