Arduino, S2A, Tecnologia

Bounce e Debounce no Arduino e no Scratch

Escrito por: ­ 25 de nov de 2016 ­ 6.567 views

Você já reparou que muitas vezes em seu projeto eletrônico, seja com Arduino ou Scratch + Arduino, usando um botão (switch/push button) mesmo apertando uma única vez o microprocessador lê múltiplas vezes, como se você tivesse apertado mais de uma vez?
Imagine como seria se você quisesse fazer um contador, a cada aperto do botão ele poderia computar pressionadas a mais que o desejado.

Esse efeito é chamado de bounce (traduzindo para o português, seria algo como “ressalto” – mas em eletrônica é mais comum usar o termo original em inglês, portanto ficamos com o bounce [baʊns].
O efeito bounce é muito comum em chaves mecânicas, pois o contato de ferro com ferro, muitas vezes ocorre de maneira imprecisa, gerando ruídos  e uma simples “encostadinha” pode gerar um repique e desta forma o microprocessador irá ler o valor mais de uma vez.

HackEduca_Bounce_Effect

Exemplo do efeito Bounce

Um dia resolvi montar um projeto/jogo no Arduino junto com minha filha de 8 anos.
A ideia inicial era para acertar se o próximo número sequencial seria uma divisão exata por 2 ou por 3.

O LED Vermelho acenderia indicando que o número era divisível por 2, se fosse o divisível por 3, o LED Verde acenderia. Caso fosse divisível por 2 e 3 (no caso do número 6) ambos os LED acenderiam.

O primeiro protótipo (sem o visor LCD) era assim:

bounce debounce arduino projeto switch button botão scratch

O programa:

/*
  HackEduca Divisão sem resto - 2 and 3 - Bounce Detector

 This sketch was created to show a bounce effect when a button is pressed.
 Sometimes pressing the button once, the microprocessor detects more than one press.
-------------
 Este exemplo foi criado para mostrar o efeito de Bounce (Repique) quando um botão é pressionado
 Algumas vezes mesmo pressionando um botão (push button) uma única vez o Arduino interpreta mais de uma pressionada.
 
 Created  21 Nov 2016
 by Edson Sobreira

This example code is in the public domain.

It was initially inpired on StateChangeDetection from Arduino
 */

// Variables - Variáveis:
int switchPin = 2;
int counter = 0;
int CurrentState = 0;
int lastState = 0;
const int ledPin = 7;
const int ledPin1 = 8;

//---------------------------------------
void setup() {
  pinMode(switchPin, INPUT);
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
 pinMode(ledPin1, OUTPUT);
}
//--------------------------------------
void loop() {
  CurrentState = digitalRead(switchPin);
  if (CurrentState != lastState) {
    if (CurrentState == HIGH) {
      counter++;
     if (counter ==1) { 
       Serial.print("O bot");
       Serial.write(227);
       Serial.print("o");
       Serial.print(" foi pressionado ");
       Serial.print(counter);
       Serial.println(" vez");
     } 
      if (counter >>1) { 
       Serial.print("O bot");
       Serial.write(227);
       Serial.print("o");
       Serial.print(" foi pressionado ");
       Serial.print(counter);
       Serial.println(" vezes");
//       Serial.println(counter % 2 == 0); - debug
//       Serial.println(counter % 3 == 0); - debug

      } 
      else {
      }
    }

  }
  lastState = CurrentState;

  if (counter % 2 == 0) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }

    if (counter % 3 == 0) {
    digitalWrite(ledPin1, HIGH);
  } else {
    digitalWrite(ledPin1, LOW);
  }
  
}

Montando o circuito acima e carregando o programa você já poderá ver o que é o efeito Bounce na serial do seu Arduino.

No exemplo foi apertado o botão 10 vezes Hackeduca Serial Bounce, no entanto foi computado 15 vezes.

Para o propósito desejado, esse programa não pode ser utilizado, pois a função de contagem que ele possui não pode é eficiente.
Existem, no entanto, algumas soluções para o caso, desde as mais simples até as mais complexas.

As opções mais simples estão relacionadas diretamente a modificação da programação (software), que por sua vez envolve uso de memória, outras envolvem hardware, que por sua vez são mais caras, elevando, desta forma o custo  do seu projeto.

Para projetos simples, software está OK.

 

Veremos a seguir como resolver esse caso:

A solução está no Debounce

Debounce é uma solução encontrada para compensar o erro na leitura. Como já citado anteriormente o contato ferro com ferro pode causar uma leitura dupla/tripla, uma vez que de fato pode ter ocorrido realmente o contato duplo ou foi simplesmente algum ruído.

1ª solução – Capacitor

O capacitor se enche com uma carga de 5v, quando o botão é pressionado e se esvazia quando o botão é liberado.
Esse processo faz com que o sinal que sai para o microprocessador demore alguns ms e desta forma o capacitor “filtra” o sinal.

Nesta caso o polo negativo do capacitor deve estar em Gnd e o positivo, depois do resistor de 10KΩ

Foi pressionado 10 vezes e o programa leu exatamente as 10 vezes
bounce debounce arduino projeto switch button botão scratch  bounce debounce arduino projeto switch button botão scratch

2ª solução – delay(50)

Essa solução é a mais simples de todas, porém deve ser evitada, pois ela causa uma parada no programa toda vez que precisa ser executada.
Nesse caso, 50ms não vai fazer diferença em termos de performance, porém em programas mais elaborados a somatória dessa função ao longo do projeto atrapalhará o resultado final.
A função delay (50); deverá ser colocada na linha 61 do programa acima

delay(50); // debounce - 2nd option

Teste e veja o resultado: 10 pressionadas = 10 registros.
(50milisegundos de atraso no programa é imperceptível.)
Hackeduca Serial Bounce II

3ª solução – millis()

Essa função é mais elaborada e um pouco mais trabalhosa para usar, porém a contagem ocorre com o programa ainda em operação, ou seja , ela não paralisa a execução, causando atrasos, como na função delay ().
Há um exemplo no sketch do seu Arduino chamada BlinkWithoutDelay que faz um bom uso dessa função.
A função millis() utiliza o contador interno do Arduino, cujo contagem, inicia-se junto com a execução do programa ou um através de um Reset.

Neste caso vamos perguntar ao nosso programa quando ocorreu a última pressionada no botão. Caso tenho ocorrido em menos tempo que o estipulado ele não autorizará a execução. É como se descartássemos os toques duplos e triplos (quando ocorrido em tempo inferior a 50ms) que é o tempo suficientemente superior ao típico do bounce.

Veja como o projeto fica:

/*
  HackEduca Divisão sem resto - 2 and 3 - DeBounced sketch

 This sketch was created to show a debounce sketch when a button is pressed.
 Sometimes pressing the button once, the microprocessor detects more than one press - so this program solve the issue
-------------
 Este exemplo foi criado para mostrar o efeito de Debounce, que é uma correção do Bounce(Repique) quando um botão é pressionado
 Algumas vezes mesmo pressionando um botão (push button) uma única vez o Arduino interpreta mais de uma pressionada.
 
 Created  21 Nov 2016
 by Edson Sobreira

This example code is in the public domain.

It was initially inpired on Debounce program from Arduino IDE
 */

// Variables - Variáveis
int ledPin = 7;       // the number of the LED Red pin  --  Pino onde o LED Vermelho está conectado
int ledPin1 = 8;      // the pin that the LED Gren is attached to -- Pino onde o LED Verde está conectado
int switchPin = 2;    // the number of the pushbutton pin - Pino onde o botão está conectado (Ligado com PullDown Resistor)

int counter = 0;
int currentState; 
int lastState;
int buttonState;     // the currentState from the input pin

unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers
//---------------------------------------------
void setup() {
  pinMode(switchPin, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(ledPin1, OUTPUT);
  Serial.begin(9600);
}
//---------------------------------------------
void loop() {
  // read the state of the switch into a local variable:
  // ler o valor atual do botão e coloca na variável currentState
  int currentState = digitalRead(switchPin);

//---
// If the switch changed, due to noise or pressing:
// Se o botão mudar de status por qualquer motivo é iniciado uma nova contagem
  if (currentState != lastState) {
      lastDebounceTime = millis();
  }
//--------
//Verifica se o último toque no botão é superior ao valor do delay (50ms), definido na variável debounceDelay
  if ((millis() - lastDebounceTime) > debounceDelay) {
        
    if (currentState != buttonState) {
      buttonState = currentState;

//------------------------      
      if (currentState == HIGH) {
      counter++;
     if (counter ==1) { 
       Serial.print("O bot");
       Serial.write(227);
       Serial.print("o");
       Serial.print(" foi pressionado ");
       Serial.print(counter);
       Serial.println(" vez");
     } 
      if (counter >>1) { 
       Serial.print("O bot");
       Serial.write(227);
       Serial.print("o");
       Serial.print(" foi pressionado ");
       Serial.print(counter);
       Serial.println(" vezes");
     } 
    }
//--------------    
   }
  }

//Atualiza o lastState para o a informação atual
  lastState = currentState;

// --- Execute the logic for gaming ---
  if (counter % 2 == 0) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }

    if (counter % 3 == 0) {
    digitalWrite(ledPin1, HIGH);
  } else {
    digitalWrite(ledPin1, LOW);
  }
// --- End og logic ---  
}

Scratch

O Scratch, não sofre tanto desse problema quando está integrado ao Arduino, mas é necessário colocar um comando para que a programação aguarde até que ocorra uma mudança da variável, caso contrário ela ficará efetuando a leitura eternamente.

hackeduca_scratchdebounce

 

Exemplo do mesmo jogo feito no Arduino:

hackeduca_scratchdebounce_ii

print
Previous Post Next Post

Você também pode gostar / You Might Also Like

No Comments

Leave a Reply

Show Buttons
Siga-nos no Facebook
Siga-nos no Twitter
Siga-nos no Google Plus
Siga-nos no Pintrest
Siga-nos no Youtube
Siga-nos no Scratch
Hide Buttons
Top
HackEduca