Nesse artigo, quero compartilhar minha tradução (com algumas alterações) do código de debounce da documentação do Arduino.
Primeiro, para quem desconhece o que significa debounce em eletrônica digital, aconselho a leitura desse excelente artigo do site Embarcados, autoria do Rodrigo Almeida, que trata desde o conceito de bouncing (com excelentes ilustrações), até as formas de debouncing através de hardware esoftware (o exemplo do artigo é para o PIC). Lembrando que o ideal é utilizar uma combinação das duas formas, para que o tempo de resposta seja o maior possível, pois, como veremos adiante, o tratamento dobouncing por software implica um delay (atraso) na resposta ao comando.
Em um outro artigo, utilizei como método de debouncing por software a própria função delay() –nesse artigo não testo se o estado da chave foi modificado, de forma que se o usuário mantiver pressionado o botão por tempo superior ao delay(), o comando será executado repetidas vezes. Mas utilizar a função delay() não é a forma correta. Por quê? Simplesmente porque ela congela a execução do programa pelo microcontrolador (Arduino), atrasando todos as demais tarefas da sua rotina, por exemplo, atualizar uma amostragem de algum dado num display LCD. A forma de contornar isso é utilizando instruções condicionais if, que testam se já passou um determinado tempo (cria um delay apenas para essa tarefa para verificar a alteração de estado da chave), a partir de comparação com o tempo total e absoluto de execução do programa no Arduino, que é obtido em milissegundos através da função millis().
Obs.: Em um código que encontrei na internet, o programador usou uma instrução while para testar se o tempo havia passado, mas isso não resolve nada, simplesmente porque a execução do programa ficará nesse while [tempo_não_passa] até que o tempo realmente tenha passado, o que equivale a usar a funçãodelay()! Se for para fazer isso, melhor usar delay(), em vez de ficar declarando e configurando novas variáveis apenas para a estrutura do while [tempo_nao_passa] nao_faz_nada funcionar…
Obs. 2: A principal alteração que fiz no código da documentação está na retirada do resistor de PULL DOWN (previsto no circuito da documentação). Eu optei por utilizar o resistor de PULL UP interno do próprio Arduino, assim ele só inverteria a lógica da detecção de alteração de estado da chave ou do botão de entrada. Atenção: é importante lembrar que a maneira mais simples e enxuta de habilitar o resistor de PULL UP interno do Arduino é declarando explicitamente em “pinMode(pinodeentrada, INPUT_PULLUP)“. É possível também declarar “pinMode(pinodeeentrada, INPUT)” e na outra linha “digitalWrite(pinodeentrada, HIGH)“. Isso também irá habilitar o resistor interno de PULL UP do Arduino, mas o ideal é enxugar o código e usar apenas as instruções necessárias, ocupando menos espaço nas duas memórias e por isso mesmo otimizando a execução do programa.
Mais informações nos próprios comentários do código. Segue abaixo também o desenho da montagem do circuito, feito no Fritzing.
/*
Debounce – Estabilizacao
Cada vez que o pino de entrada vai de HIGH para LOW (e.g. devido ao pressionamento do botao), o pino de saida eh alternado de LOW para HIGH ou de HIGH para LOW. Existe um pequeno atraso entre essas alternancias para estabilizar o circuito (i.e. para ignorar o ruido).
O circuito:
- LED do pino 13 ao GND (terra ou negativo)
- Botao pulsante (pushbutton) do pino 2 ao GND (terra ou negativo)
Nota: Na maioria das placas Arduino, já existe um LED na placa conectado ao pino 13, assim vc nao precisa adicionar nenhum componente neste circuito. Ateé mesmo o botão pulsante pode ser substituído por um mero ‘jumper’ (um ‘fiozinho’) com o qual você poderá simular o pressionamento do botão fazendo contato entre o pino 2 e qualquer GND do Arduino.
- Criado em 21 de novembro de 2006, por David A. Mellis;
- Modificado em 30 de agosto de 2011, por Limor Fried;
- Modificado em 28 de dezembro de 2012, por Mike Walters;
- Modificado e traduzido em 31 de agosto de 2014, por Jeter Silveira.
Esse codigo foi copiado e alterado para disponibilização gratuita na internet em: http://www.jetersilveira.com.br
O original também é domínio público e pode ser encontrado na pagina oficial de documentação do Arduino, no endereço: http://www.arduino.cc/en/Tutorial/Debounce
*/ // as constantes nao mudam. Elas sao usadas aqui // para ‘setar’ os numeros dos pinos const int buttonPin = 2; // o numero do pino do botao pulsante (“pushbutton”) const int ledPin = 13; // o numero do pino do LED // Variaveis sofrerao mudancaso int ledState = HIGH; // o atual estado do pino de saida (LED) int buttonState; // a leitura atual do pino de entrada int lastButtonState = HIGH; // a leitura anterior do pino de entrada // as variaveis seguintes sao to tipo ‘long’ porque o tempo, medido em milissegundos // rapidamente se tornara um numero maior do que o que cabe em uma ‘int’. long lastDebounceTime = 0; // a ultima vez que o pino de saida foi modificado (toggled) long debounceDelay = 50; // o tempo de estabilizacao (debounce); // aumente se houver oscilacao na saida. void setup() { pinMode(buttonPin, INPUT_PULLUP); // habilita o resistor de PULL UP interno do Arduino pinMode(ledPin, OUTPUT); // ‘seta’ estado inicial do LED digitalWrite(ledPin, ledState); } void loop() { // le o estado do botao em uma variavel local int reading = digitalRead(buttonPin); // testa para ver se voce recem acaba de apertar o botao // (i.e. a entrada foi de LOW para HIGH, e vc esperou tempo suficiente // desde o ultimo pressionamento para ignorar qualquer ruido). // Se o estado do botao mudou, seja por pressionamento ou por ruido if (reading != lastButtonState) { // ‘reseta’ o temporizador de debounce lastDebounceTime = millis(); } if ((millis() – lastDebounceTime) > debounceDelay) { // seja qual for o valor da leitura, ele esta lah a mais tempo que // o tempo de debounce (debounceDelay), entao podemos utilizar o valor: // verifica se o botao mudou if (reading != buttonState) { buttonState = reading; // apenas muda o estado (toggle) do LED se buttonState for LOW if (buttonState == LOW) { ledState = !ledState; } } } // ‘seta’ o LED digitalWrite(ledPin, ledState); // salva a leitura. Na proxima vez que passar no loop // essa leitura sera o ultimo estado do botao (lastButtonState). lastButtonState = reading; }
Veja abaixo o diagrama de montagem do circuito. O LED que deverá ser observado é incluído na placa. Observe que é há LED SMD próximo aos LEDS indicadores de TX e RX e do pino 13, indicado pela letra L. Esse LED está em praticamente todas as placas Arduino e está ligado ao pino 13, para indicar seu status. Daí o porquê esse circuito tem apenas o botão, com o objetivo de agilizar e facilitar seu aprendizado sobre a técnica de debouncing por software. Lembre que no início do artigo falamos sobre a importância do debouncing via hardware também. No entanto, para a grande maioria das aplicações, a técnica de software que aqui demonstramos é suficiente.
Artigo enviado pelo leitor por Jeter Vaz