sábado, 17 de março de 2012

Botões e Resistores Pull-down e Pull-up

Como um bom programador, e não profundo conhecedor de eletrônica, tive um pouco de dificuldade até entender como o Arduino verifica se um botão foi ou não pressionado, para isso tive que entender um pouco sobre a montagem dos circuitos e seus respectivos resistores pull-down e pull-up.

Como cheguei nessa dúvida?

Bom, vi que algumas aplicações que utilizavam um botão, faziam as verificações se os botões estavam pressionados de formas diferentes, as vezes verificavam se estavam em HIGH e as vezes em LOW quando pressionados. Mas por que?

O Arduino na verdade não vê se o botão está pressionado ou não, ele verifica se a porta onde está o botão está energizada (HIGH) ou não (LOW), e dependendo de como o circuito está montado, é possível que sejam feitas as seguintes leituras na porta:

Exemplo 1:
- HIGH - com o botão não pressionado
- LOW - com o botão pressionado

Exemplo 2:
- HIGH - com o botão pressionado
- LOW - com o botão não pressionado

No exemplo 1, significa que a porta está energizada (HIGH) com o botão não pressionado, isso quer dizer que estamos utilizando resistores pull-up para manter a porta em HIGH. A porta terá leitura LOW quando o botão for pressionado.

E no exemplo 2 é o contrário, significa que a porta está em LOW quando o botão não está pressionado e será HIGH quando o botão for pressionado, levando-nos a entender que estamos utilizando resistores pull-down para manter a porta em LOW enquando o botão não estiver pressionado.

Ou seja, HIGH e LOW não tem nada a ver com a situação do botão (pressionado ou não), e sim com a montagem do circuito.

Mas por que utilizar os resistores de pull-up e pull-down?

Pode haver variação na leitura da tensão das portas do Arduino (ou de qualquer circuito eletrônico), logo, utilizando essa técnica, sempre forçamos a leitura em 5V ou 0V, isolando essas variações que podem fazer com que ocorra erros na leiruta de pressionamento de um botão.
E como deixo a porta em HIGH (pull-up) ou LOW(pull-down)?

Para isso utilizamos os resistores, fazendo que com o circuito aberto (botão não pressionado) a porta esteja energizada com os 5V no Arduino, como no exemplo abaixo:

PULL-UP
Repare que com o botão não pressionado
a porta está ligada aos 5V (HIGH), e com o botão
pressionado, o caminho com menor resistência será
o GND (LOW).

Ou, forçamos que com o circuito aberto (botão não pressionado) a porta esteja com leitura LOW, como no exemplo abaixo:

PULL-DOWN
Repare que com o botão não pressionado
a porta está ligada ao GND (LOW), e com o botão
pressionado, o caminho com menor resistência será
os 5V (HIGH).

No código, as verificações ficam da seguinte forma:

  // Verifica se o botão foi pressionado - PULL-UP.
  if (digitalRead(buttonPin) == LOW) {
    // rotina...
  }

  // Verifica se o botão foi pressionado - PULL-DOWN
  if (digitalRead(buttonPin) == HIGH) {
    // rotina...
  }

Agora a boa notícia, o Arduino possui internamente os resistores de PULL-UP, basta ativar esse recurso através do código:

    pinMode (buttonPin,INPUT);
    digitalWrite (buttonPin,HIGH); // ativa os resistores pull-up


O digitalWrite de HIGH na porta onde está o botão faz com que o resistor PULL-UP interno do Arduino seja ativado. Bem mais simples hein?

Agora basta fazer a verificação de pressionamento do botão utilizando o código do PULL-UP que já havia mostrado acima:

  // Verifica se o botão foi pressionado - PULL-UP.
  if (digitalRead(buttonPin) == LOW) {
    // rotina...
  }

Esse esquema dispensa o resistor externo para fazer o Pull-Up e utiliza o resistor interno do Arduino (na verdade do ATMega), facilitando em muito a montagem do circuito.
PULL-UP interno do Arduino


Espero ter ajudado no entendimento e montagem de botões no ATMega, e como utilizar os resistores Pull-Up e Pull-Down para manter um circuito energizado ou não, evitando a leitura de variações de tensão na porta do Arduino e gerando possíveis erros para saber se um simples botão está ou não pressionado.

Abraços!
Diego Feliciano

9 comentários:

  1. Mas posso utilizar a chave numa entrada digital sem resistor nenhum, apenas ligando a entrada ao pino 5v?

    ResponderExcluir
  2. Fala Rafael!

    Pode sim, é o exemplo da última imagem. Liga um lado da chave em uma porta digital e o outro lado no GND, sem resistores.

    Só não esquece de ligar os resistores interno do arduino com o código:
    pinMode (buttonPin,INPUT);
    digitalWrite (buttonPin,HIGH); // ativa os resistores pull-up

    E pra verificar o botão:
    // Verifica se o botão foi pressionado - PULL-UP.
    if (digitalRead(buttonPin) == LOW) {
    // rotina...
    }

    Mas se esquecer de algum código não precisa esquentar a cabeça que não vai queimar nada, só a verificação de pressionamento do botão que pode ser informada errada.

    Qualquer coisa fala ai!

    Abraço!

    ResponderExcluir
  3. Ok amigo, muito obrigado pela informação! Abraço!!

    ResponderExcluir
  4. Muito boa a explicação, essa questão do pull-up nativo do arduino facilita muito. Seu blog vai pro meu Delicious! parabéns

    ResponderExcluir
  5. Existe uma forma mais fácil ainda pessoal!
    Dentro do setup, configuramos o pino do botão com INPUT_PULLUP.
    Ficando assim:

    void setup()
    {
    pinMode(pinobotao, INPUT_PULLUP);
    }

    Pronto, quando o botão for pressionado, o Arduino irá ler "zero" na entrada do pino do botão. Simples assim!

    ResponderExcluir
  6. Parabéns pela explicação! Realmente foi muito exclarecedora. Foi a explicação mais clara e objetiva que consegui encontrar.

    ResponderExcluir
  7. Olá amigo. Em ambos os exemplos (pull up ou down) estão sendo usados botão NA (normalmente aberto)?

    Quando na programação é LOW para Pull-up e HIGH para Pull-down, ambos estão para chave normalmente aberta?

    Ou no caso do Pull-down é necessário usar NF?

    Atenciosamente.

    ResponderExcluir
  8. Muito esclarecedor. Obrigado pelas dicas. Liguei o Arduino controlando uma Realidade Virtual junto a um motor, e a energia eletromagnética estava interferindo no sistema. Vou implantar isso é ver funcionando 100%. Obrigado.

    ResponderExcluir