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