fbpx
ArduinoNovidade

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.

Bacharel em Engenharia de Computação. Um dos criadores do Blog da Robótica. Faz parte da equipe Casa da Robótica desde 2017. Apaixonado por tecnologias e pelas “loucuras” que é possível criar usando microcontroladores e impressoras 3D. Ex-BBB, mas isso é uma longa história... que poderá ser contada posteriormente.

Kleber Bastos

Bacharel em Engenharia de Computação. Um dos criadores do Blog da Robótica. Faz parte da equipe Casa da Robótica desde 2017. Apaixonado por tecnologias e pelas “loucuras” que é possível criar usando microcontroladores e impressoras 3D. Ex-BBB, mas isso é uma longa história... que poderá ser contada posteriormente.