Conhecimento

Evitando repiques em entradas digitais do Arduino

Entradas digitais de microcontroladores são muito utilizadas para ler botões/botoeiras/chaves de fim de curso e sensores instalados em campo. Normalmente existem apenas dois estados possíveis: nível baixo ou zero volts ou “false”, e nível alto ou 3,3V/5V ou “true”. 

O ideal é que o elemento de acionamento da entrada digital faça uma transição rápida e limpa entre os estados zero e um, alto e baixo. Que o sinal saia de nível baixo e vá para nível alto o mais rápido possível e sem repiques ou oscilações. Porém algumas vezes não é isso que acontece, o sinal oscila brevemente várias vezes entre alto e baixo.

Isto tudo devido à não-linearidades ou até mesmo circuitos capacitivos ou indutivos, como por exemplo uma fiação muito longa ou passando próximo a um circuito de potência. Estes elementos podem fazer com que a transição entre níveis lógicos nas entradas digitais não seja tão “limpa” e rápida como desejado.

 

O problema

 

Uma transição entre níveis lógicos menos “ideal”, mais lenta e com alternância entre estados pode por exemplo confundir o nosso código rodando no Arduino, fazendo-o acreditar que vários acionamentos foram realizados. Tudo isto quando apenas um acionamento foi realmente efetuado.

 

Este problema é especialmente preocupante em circuitos contadores de peças em uma linha de produção, por exemplo. Neste caso uma falsa contagem pode fazer com que uma caixa não seja preenchida com a quantidade correta de produtos, ou receba mais produtos do que o esperado. 

 

Isto pode levar à perda de produtividade e itens de produção, causando prejuízos aos acionistas e envolvidos. Por isso da importância de analisar e mitigar os ruídos em entradas digitais do Arduino. 

 

A solução

 

Existe uma técnica de limpeza e organização de sinais elétricos chamada “debounce” (do Inglês “deixar de oscilar”), que torna as transições entre sinais mais limpas e rápidas. Uma das formas de fazer debounce é instalando um filtro passa-baixas entre o botão/sensor e a entrada digital, conforme imagem abaixo.

 

Fonte: https://www.electronics-tutorials.ws/filter/filter_2.html

 

Neste circuito o capacitor C é calculado para ter uma tal reatância que as altas frequências passem todas por ele, indo para a terra e não chegando ao microcontrolador. Em sistemas embarcados sempre é uma boa prática utilizar este tipo de circuito RC em suas entradas digitais.

 

Outra forma de fazer debounce é através de software, dentro do microcontrolador em questão. A ideia principal é detectar a primeira transição entre zero e um e então ignorar as demais transições por alguns poucos milissegundos. É como se após a primeira detecção nós olhássemos para o lado e ignorássemos as demais transições (que são na verdade o ruído).

 

Esta técnica é bem tranquila de se implementar via software, veremos em seguida. Mas para isso precisamos de um hardware, que pode ser visto abaixo. É composto por um botão no pino D11 e LEDs no pino D1. Veja que não há nenhum capacitor no circuito, então não vamos implementar o debounce por hardware. Vai ser puramente código.

Fonte: o autor

O microcontrolador utilizado é o Wemos D1, um ESP8266 com WiFi; mas poderia ser literalmente qualquer Arduino, visto que não usaremos nenhuma biblioteca mais específica. Veja abaixo como ficou a montagem do protótipo para testes.

Fonte: o autor

 

Fonte: o autor

O código

 

Nossa placa Wemos D1 é um Arduino, então escreveremos código assim como se estivéssemos tratando de um Arduino UNO. O que queremos é detectar uma borda de subida e então aguardar 200 milissegundos para fazer nova verificação. Nesta condição alternaremos o estado da saída para o LED entre ligado e desligado.

 

#define LED D1
#define TOUCH D11


long oldtime;
bool oldstate= false;


void setup() {
  // put your setup code here, to run once:
  pinMode(LED, OUTPUT);
  pinMode(TOUCH, INPUT);
 
}


void loop() {
  // put your main code here, to run repeatedly:
  if(millis() - oldtime > 200){
    oldtime= millis();


    if(digitalRead(TOUCH) && oldstate== false){
      digitalWrite(LED, !digitalRead(LED));
      oldstate= true;
    }else if(digitalRead(TOUCH) && oldstate== true){
      oldstate= true;
    }else if(!digitalRead(TOUCH) && oldstate== true){
      oldstate= false;
    }
  }
 
}

Note que precisamos de uma variável booleana (“true” ou “false”) para termos controle do estado anterior da entrada digital “oldstate”. A variável “oldstate” recebe “true” (nível lógico 1) quando detectar uma borda de subida ou se mantiver em nível alto. Recebe “false” (nível lógico 0) quando o estado anterior for sinal alto e o atual baixo. Tudo isso ocorre em intervalos de 200 milissegundos.


Conclusão


Este tipo de implementação de software é muito útil tanto para sensores digitais como botões, push-buttons e relês/contatores acionando portas de um microcontrolador. Evita contagens/acionamentos excessivos e falsos, basicamente ignorando tudo que ocorre por 200 milissegundos após a primeira detecção.


No vídeo abaixo eu falo sobre o código de exemplo que estudamos acima, aproveite. 


https://youtube.com/shorts/PTA932T9kUc?feature=share

Autor


Avatar

Clovis Fritzen

Engenheiro eletricista e técnico em eletrônica, tem um interesse por sistemas embarcados (aos quais chama de "plaquinhas") e eletrônica desde muito cedo. Tem um blog em Inglês (FritzenLab.net) e outro em Português (FritzenLab.com.br), onde posta tutoriais e reviews das "plaquinhas".