IoT e Makers

18 set, 2014

Debouncing via software com Arduino sem usar delay – millis()

Publicidade

ArduinoCommunityLogo-610x250

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.

debounce_pullup

Artigo enviado pelo leitor por Jeter Vaz