Debouncing via software com Arduino sem usar delay – millis()
Nesse artigo, quero compartilhar minha tradução (com algumas alterações) do código de debounce da documentação do Arduino.
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








