Tutoriais

Arduino: Como ligar botões de uma forma “profissional

39 Comentários

Por Samuel Carreira  para o Pplware

Uma das formas mais comuns de controlar o Arduino é utilizar interruptores ou botões de pressão. Neste pequeno tutorial, vou explicar como utilizar botões de uma forma fácil, “profissional” e recorrendo a poucas linhas de código.

arduino_04


No âmbito deste tutorial, vão ainda introduzidos os seguintes conceitos básicos:

  • PWM
  • Constante INPUT_PULLUP
  • “Bounce” de um botão
  • Instalação automática de uma biblioteca externa no Arduino
  • Utilização da biblioteca Bounce

Para introduzir este tutorial, imaginemos uma situação prática em que pretendemos controlar o brilho de um LED através de dois botões (um botão para aumentar o brilho e outro para o diminuir). Os botões devem controlar o aumento de uma forma precisa (aumentar o valor do brilho em incrementos de uma unidade) e possibilitar um aumento mais rápido do valor caso se mantenha o botão premido.

Parte I – Hardware

Para se variar o brilho do LED é necessário utilizar uma porta com saída PWM. O que acontece de uma forma simples numa saída PWM é que o LED é ligado e desligado muito rapidamente (até aproximadamente 490 vezes por segundo). Variando o os valores deste pulso é possível “obter a sensação” que o LED não está com o brilho máximo (mais informações sobre PWM aqui).

O pino escolhido para ligar o LED poderá ser qualquer um dos pinos do Arduino que suportem PWM, como por exemplo, o número 11. Visto que na saída dos pinos do Arduino a corrente máxima é de 40 mA a 5 V, deverá utilizar-se uma resistência ligada em série com o LED para o proteger (tipicamente utiliza-se uma resistência de 220 Ohms).

A ligação dos dois botões poderá ser realizada em qualquer uma das portas digitais do Arduino (neste caso vamos escolher os pinos 7 e 8). Na maioria dos tutoriais são utilizadas resistências de proteção em conjunto com os botões (chamadas de resistências pull-down), no entanto, para simplificar as ligações e o número de componentes usados, vamos utilizar as resistências internas do Arduino (chamadas de resistências de pull-up), e por isso a ligação será realizada diretamente entre a massa (ground ou GND) e o botão.

As nossas ligações ficariam assim:

arduino_00

Ou o esquema eléctrico:

arduino_01

NOTA: no esquema é utiliza um botão de pressão simples de dois terminais, os botões de 4 terminais que devem ser ligados da seguinte forma

arduino_00

Parte II – Software

Algo que pode passar despercebido ao principiante na eletrónica é que os interruptores mecânicos não funcionam de uma forma totalmente “limpa”. De uma forma simples, quando se pressiona um botão, os contactos metálicos não fecham o circuito imediatamente devido às condições microscópicas das superfícies de contacto e ocorre um ligeiro oscilar (Bounce) entre estados durante breves microssegundos entre. A figura abaixo esquematiza este pormenor ao representar a variação de estado de um botão ao longo do tempo:

arduino_02

Como os microcontroladores são muito rápidos a processar os sinais, conseguem detetar esta oscilação no estado do botão e em determinadas aplicações tal facto pode ser problemático. Existem diversas formas de contornar este problema. A mais comum é utilizar algumas linhas de código que recorrem à função millis() do Arduino ( http://arduino.cc/en/Tutorial/Debounce ). No entanto, vamos aprender a utilizar a biblioteca Bounce que foi escrita para este efeito e que adiciona algumas funcionalidades interessantes de uma forma muito simples e sem ser necessário escrever muitas linhas de código.

Instalar a biblioteca automaticamente

1- Fazer download da biblioteca (comprimida em zip) aqui

2- Na IDE do Arduino, navegar até ao menu Sketch -> Importar Biblioteca… -> Adicionar Bibliotecae escolher o ficheiro descarregado anteriormente

NOTA: caso deseje instalar a biblioteca manualmente poderá utilizar as instruções disponíveis aqui

Análise do código

O código inicia com a chamada da biblioteca e a definição dos pinos de ligação. Definir os pinos utilizados é uma boa prática que simplifica a alteração das ligações eléctricas sem ser necessário rever todo o código escrito.

#include  // biblioteca utilizada
// definição dos pinos de ligação
#define LED_PIN 11
#define AUMENTAR_PIN 8
#define DIMINUIR_PIN 7

É criada uma variável do tipo byte (valores entre 0 e 255) que irá armazenar o valor do brilho do LED.

byte brilho = 0; // valor do brilho do LED entre 0 e 255

Os dois botões utilizados são declarados como objetos da seguinte forma Bounce(byte pin, unsigned long debounce_interval) sendo que o intervalo de debouce é definido em milissegundos (5 milissegundos é um valor tipicamente utilizado).

#define DEBOUNCE_TIME 5 // tempo em ms
Bounce aumentar = Bounce(AUMENTAR_PIN, DEBOUNCE_TIME); 
Bounce diminuir = Bounce(DIMINUIR_PIN, DEBOUNCE_TIME);

O pino do LED é definido como pino de saída e os pinos dos botões são definidos como entrada com o argumento INPUT_PULLUP que possibilita o uso das resistências internas de pull-up. Esta definição inverte o comportamento do pino no sentido que um valor HIGH ou ligado significa que o sensor está desligado e vice-versa.

De forma a monitorizar o valor da variável que define o brilho do LED é iniciada uma comunicação série que pode ser controlada através do Monitor Série integrado na IDE Arduino (Menu Ferramentas -> Monitor Série).

void setup()  { 
  pinMode(LED_PIN, OUTPUT)
  pinMode(AUMENTAR_PIN, INPUT_PULLUP);
  pinMode(DIMINUIR_PIN, INPUT_PULLUP);

  Serial.begin(9600);
  Serial.println("Tutorial Botao");
}

O código da função principal do programa começa com a escrita do valor da variável brilho (um valor de 0 corresponde a sempre desligado e um valor de 255 corresponde a sempre ligado). O estado dos botões é detetado através da função update, caso este valor seja verdadeiro (o que corresponde a uma mudança de estado do botão), é verificado se o botão encontra-se premido (devido à utilização da resistência interna de pull-up corresponde a um estado inverso, ou seja, 0 ou LOW).

A função rebounce força o sinal do estado do botão a alterar mesmo que o estado físico não altere. Neste caso é utilizado para repetir o estado do botão a cada 250 milissegundos enquanto o botão estiver a ser premido (útil para alterar rapidamente o valor). O valor da variável brilho pode ser lido no monitor série de forma a se comprovar o correto funcionamento do programa (a função Serial.println(valor) escreve o valor da variável seguido de uma quebra de linha ou “parágrafo”).

void loop()  { 
  analogWrite(LED_PIN, brilho);

  if (aumentar.update() ) {
    if (aumentar.read() == LOW ) {
      aumentar.rebounce(250);

      if (brilho < 255)         
             brilho ++;                

      Serial.print("Aumentar o brilho do LED: ");       
      Serial.println(brilho);     
          }   
     }      
if (diminuir.update() ) { 
    if (diminuir.read()== LOW ) 
            {       
             diminuir.rebounce(250);              

          if (brilho > 0)
          brilho --;     
      Serial.print("Diminuir o brilho do LED: ");
      Serial.println(brilho);
    }
  }
}

Aconselhamos a uma revisão cuidada do código e das ligações elétricas antes de fazer o upload do código. Uma configuração errada dos pinos de entrada pode danificar permanente o Arduino.
Caso o upload seja realizado com sucesso poderão utilizar o Monitor Série (atalho: CTRL+SHIFT+M) para observar a alteração do valor da variável que controla o brilho e comprovar o correto funcionamento do programa.

arduino_05

Video de Demonstração

Com este pequeno tutorial foi possível aprender alguns conceitos básicos mas bastante úteis para todos aqueles que se desejam iniciar no fantástico mundo do Arduino.
Download Código fonte: aqui

Referências

Esquemas desenhados no Fritzing: ver aqui

Autor: Pedro Pinto
Partilhar:
Também pode gostar

Comentários

39

Responder a Michel Cancelar resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *

  1. Avatar de Mota
    Mota

    Parabéns gostei!

  2. Avatar de Rui Peixeiro

    Muito bem!!!

    Com estes kist do Arduino tão baratos no ebay e com um leque de possibilidade infinitas, estes tutoriais são muito bem vindos!

    Eu estou a fazer com base no Arduino, uma estação meteorológica online, sem necessidade um ter um PC ligado a enviar para a net, e com recolha dos dados do tempo por “wireless”, com uns sensores económicos a funcionar a 433MHz.
    Por pouco mais de 60€, fico com uma estação meteorológica, a enviar os dados (temp, chuva, vento, direcção, humidade, …) em tempo real, para site próprio e Wheatherunderground!!!

    Continuem a ensinar e dar ideias ao pessoal!

    1. Avatar de John
      John

      Rui Peixoto, podes partilhar que componentes usas? Por acaso também estava a analisar a possibilidade de fazer algo semelhante. O que tinha em mente, para a temperatura e humidade seria um dht11 e para luminosidade um ldr. Para chuva sei que há módulos dedicados. Mas para o vento, que utilizas?

      1. Avatar de Rui Peixeiro

        Eu usei um Arduino UNO rev3 (http://www.dx.com/p/120464), um BMP085 que me dá a pressão atmosférica e a temperatura interior (http://www.dx.com/p/147261) e um receptor wireless 433MHZ (http://www.dx.com/p/149252). Comprei tudo no dx.com se procurares pelo ebay, ainda se encontra tudo mais barato.

        Em adição e para envio directo para a net, tenho uma Ethernet Shield W5100.

        Depois, andei a ver o que sairia mais barato para os receptores externos (pluviómetro, termómetro, higrómetro e anemómetro e cata vento) e acabei por comprar uma estação meteorológica completa do Lidl (Auriol h13726) igual a isto: http://www.celestron.com/astronomy/celestron-deluxe-weather-station.html

        Sensores de UV e Radiação solar ainda não tenho, só depois de ter isto tudo a 100%.

        O que me está a dar mais trabalho, é que não quero ter um PC ligado todo o dia. Há em vários sites o código pronto e liga o arduino por USB a um PC com o software Cumulos que trata os dados dos sensores e envia para a net. Eu estou a evitar este passo e enviar os dados directamente para a net e fazer aí o tratamento dos dados…

        1. Avatar de João Tavares
          João Tavares

          Bom dia.
          Acho muito interessante a sua ideia. Estava a pensar se estiver interessado poderíamos criar uma rede a nível nacional de estações metereológicas caseiras com arduino.

        2. Avatar de jose carlos
          jose carlos

          Ola poderia me ajudar tenho um Arduino idêntico ao seu
          posso usar uma bateria de lipo de 7.5V de 500miliamper para alimentalo
          ou corro risco de queimalo
          poderia me ajudar por favor

          1. Avatar de SamC
            SamC

            O arduino tem um regulador de tensão integrado por isso não há problema em o alimentar com 7.5 V. A desvantagem é apenas uma eficiencia energetica reduzida

  3. Avatar de Rui Santos
    Rui Santos

    O bounce podia muito bem ter sido eliminado na fonte, com um circuito RC em cada interruptor, era escusado induzir iowaits via software.

    1. Avatar de lmx
      lmx

      é bem verdade, mas isso faz com que tenhamos que gastar mais dois componentes por botão, e se tivermos muitos, ou se o custo final do equipamento for baixo, a melhor solução é usar o micro…apesar de isso poder criar problemas de performance, dependendo da aplicação/micro.

      cmps

      1. Avatar de SamC
        SamC

        Exato, felizmente na eletrónica há muitas formas de fazer a mesma coisa. Podia-se utilizar uma resistência de pull down no interruptor (como é tradicionalmente realizado nos tutoriais http://arduino.cc/en/tutorial/button ) no entanto, no esquema apresentado acima evitou-se o uso de componentes extra, só o botão e o microcontrolador.

        Na minha experiência até ao momento, o uso do software para eliminar o bounce, não tem tido influências perceptíveis na performance.

        1. Avatar de lmx
          lmx

          boas…a questão da performance, vai depender muito do hardware e da especificidade do projecto.

          Se tiveres a correr uma aplicação em tempo real que precise de ter sempre cpu para realizar tarefas, ai pode acontecer, porque enquanto corres código de debounce não podes correr código da aplicação.

          Mesmo que os inputs usem irq’s existe sempre o problema de correres código de debounce.

          Embora que usando DMA possas minorar ou resolver por completo o problema, pois aceleras um pouco todas as tarefas que programas-te para usufruirem do DMA, e por sua vez libertas espaço para outras coisas…

          cmps

  4. Avatar de Ikari-Pt
    Ikari-Pt

    Bom tutorial, so uma coisa,
    “variando o os valores deste pulso é possível “obter a sensação” que o LED não está com o brilho máximo”

    O led não esta mesmo com o brilho ao máximo, pois o pwm esta a limitar a corrente que o led recebe, logo se não tem corrente “máxima” então o led não brilha ao máximo.
    Não é uma questão de percepção, é mesmo assim.

    Por outro lado se o PWM for muito lendo, então sim, o led chega a receber a corrente máxima, mas a velocidade tipica do pwm não costuma ser tão baixa.

    1. Avatar de Pedro Pinto

      Ai que este “know how” anda perdido. Quando fazer uns posts Ikari-Pt?

    2. Avatar de SamC
      SamC

      No PWM limita-se a potência média do circuito (na fórmula do cálculo da potência é necessário multiplicar por o DutyCycle T=1/F). Numa onda quadrada monofásica a corrente e a tensão são MÁXIMAS no seu pico.
      Repara que estamos a falar do comportamento de um díodo (LED) e não de uma carga indutiva ou resistiva não linear (como uma lâmpada incandescente).
      Mais info sobre o efeito visual aqui: http://en.wikipedia.org/wiki/Flicker_fusion_threshold

    3. Avatar de pixar
      pixar

      Desculpa mas não concordo. O tutorial está mesmo correto.
      O PWM, como a sigla pretende indicar, é a modulação por largura de pulso. Isso significa que o LED apenas tem dois estados: 0 e 1, ou se preferires, corrente máxima e zero.
      Com 0 a corrente é zero. Com 1 a corrente é máxima.
      O que vai dar mais ou menos brilho é o tempo que o LED permanece ligado durante a pulsação.
      O teu raciocínio estaria completamente correto se tivesses dito que em termos de média de corrente nunca seria máxima. Isso estaria certo porque com o PWM o valor médio é sempre mais baixo que se estivesse sempre ligado. O valor médio pode ser calculado com recurso às áreas dos retangulos. Para dificultar a coisa até podiamos usar um integral…

      1. Avatar de lmx
        lmx

        pixar…o que o colega disse , ou deixou subentendido não está errado por aquilo que percebi…

        A corrente demora tempo a circular, de tal forma que quando dizes que o led quando está on a currente é maxima…isso também não é uma verdade absoluta…pois a currente demora tempo a subir…

        por esses motivos, e por outros podemos ficar com a sensação que o led não esta no seu valor maximo de corrente…porque este efeito visual depende de muitos aspectos…

        Para termos uma noção de brilho maximo, teremos que atingir determinados valores de corrente por intervalo de tempo…

        Claro que o pwm resolve esta situação, e o duty cycle é porporcional á quantidade de corrente, mas esta não está disponivel no imediato…e o led também tem o seu tempo de resposta como tudo na vida…

        Por outras palavras…teremos que ter um duty cylce maior para surtir os efeitos teoricos(esquecendo a velocidade de propagação da corrente/defeitos do conductor/calor-resistência/lentidão do led em responder).

        cmps

        1. Avatar de pixar
          pixar

          Boas. A questão do tempo de resposta do LED não é significativa neste projecto. Neste caso a frequência é de 490Hz, muito abaixo do que um LED consegue fazer tendo em conta os seus tempos de subida e descida.
          Dependendo da qualidade do LED, facilmente funcionam na casa dos 30kHz (os mais rascas).
          O projecto em cima põe em prática o que está aqui explicado.
          http://www.newtoncbraga.com.br/index.php/eletronica/57-artigos-e-projetos/6006-art1318

  5. Avatar de thylux

    Uma pequena informação extra:

    As resistências pull-up ou pull-down não servem como protecção, mas sim para evitar falsos positivos ou negativos.
    Se não estiverem ligadas por defeito a um dos extremos (HIGH ou LOW) alguns dispositivos mais sensíveis podem apanhar electricidade estática do ar o que pode alterar os valores lidos pelo Arduino.

    Se esperam receber um sinal HIGH quando carregam no botão, assumem que quando não se carrega vão receber um sinal LOW. Para o garantir ligam uma resistência ao GND para que essa faça o serviço de pull-down.

    Escrevi este artigo quando aprendi sobre isso:
    http://thylux.blogspot.pt/2011/03/curious-case-of-pull-up-push-down.html

    1. Avatar de lmx
      lmx

      a principal aplicação é mesmo como protecção dos integrados…cada vez mais on integrados usam-nas internamente, ou então disponiblizam saidas em open colector, precisamente para a malta distraida,ou atarefada, não se “divertir” a queimar as saidas…

      Mas também são muito utilizadas para esse fim…

      cmps

  6. Avatar de onike
    onike

    O youtube foi a baixo.
    Print tirado por mim:
    http://oi41.tinypic.com/v6olro.jpg

  7. Avatar de samuel sa
    samuel sa

    Posso só dizer que esta demonstração do hardware está errada
    Deveria levar uma resistência entre o pino do botão que liga ao Arduino e os 0V

    1. Avatar de SamC
      SamC

      Podes confiar na montagem que está tudo correto. Se leres o artigo bem encontras as explicações.

  8. Avatar de Carlos Ferreira
    Carlos Ferreira

    Alguém sabe de um tutorial onde possa controlar à volta de 50 leds com um arduino?

    1. Avatar de SamC
      SamC

      Como já foi mencionado, há muita forma de fazer a mesma coisa.
      A maneira mais amadora é utilizares a enorme quantidade de portas de um Arduino Mega (há alguns modelos baratos no OLX).
      A forma mais “profissional” é utilizares shift registers (exemplo http://arduino.cc/en/Tutorial/ShiftOut )

    2. Avatar de thylux

      Para além disso podes ainda achar interessante o uso de matrizes de leds. Para 49 leds só precisas de usar 14 pinos do arduino. Tens é de trabalhar mais para conseguir acender 1 de cada vez.

      Exemplo:
      http://thylux.blogspot.pt/2010/10/poor-mans-led-matrix.html
      http://www.instructables.com/id/LED-Dot-Matrix-Display/

  9. Avatar de Christian
    Christian

    Prezado, boa noite.

    Quanto tento usar a biblioteca em questão, recebo erro na compilação: “expected unqualified-id before ‘<' token" referente a linha
    Saberia me ajudar? Baixei a biblioteca e instalei como instruído.

    Grato

    1. Avatar de jose carlos
      jose carlos

      ola
      se vc estiver tentando ativar alguma shild
      ante3s de compilar desencaixe ela pois quando a uma shild conectada no Arduino não aceita compilação

  10. Avatar de JOAO SERGIO VIEIRA DA COSTA
    JOAO SERGIO VIEIRA DA COSTA

    Bom dia , sera que alguem poderia me ajudar a introduzir um codigo no steeperdo motor de passo do arduino para que quando eu apertar um botao o motor gira 360 graus e pare.Nao sei criar o codigo e se alguem puder me enviar o mesmo eu agradeco,

    PS o acionamento do motor deve ser ao toque do botao,sem mante-lo pressionado.

    Grato sergio costa

  11. Avatar de Fabio
    Fabio

    Boa tarde gostaria de saber se existe uma forma de ligar o arduino automatico tipo eu programo ele pra livar tal dia e tal hora e ele liga sozinho tem como fazer isso ….eu pensei em uzar o agendador de tarefas do Windows mas ai nao deu certo…

  12. Avatar de Ijanai
    Ijanai

    Boa tarde, gostei muito do post. Estou querendo adicionar botão profissional para controlar o tempo de funcionamento de um relê, tem com vocês me ajudarem?

  13. Avatar de André
    André

    boas
    sou novo neste mundo do arduino, ainda ando a recolher informação para perceber como funciona a programação e precisava de uma ajuda.
    montei este esquema e funciona cinco estrelas mas tentei add mais um led e um botao para acender e apagar esse novo led mas sem sucesso o programa só me faz a função aqui mostrada.
    alguém me podia dar uma ajuda

    1. Avatar de SamC
      SamC

      Viva, sem o código será dificil perceber o problema…

      1. Avatar de André
        André

        o código ficou assim :$

        #include // biblioteca utilizada

        // definição dos pinos de ligação
        #define LED_PIN 11
        #define AUMENTAR_PIN 8
        #define DIMINUIR_PIN 7

        #define led 12
        #define botao 6

        byte brilho = 0; // valor do brilho do LED entre 0 e 255

        #define DEBOUNCE_TIME 5 // tempo em ms
        Bounce aumentar = Bounce(AUMENTAR_PIN, DEBOUNCE_TIME);
        Bounce diminuir = Bounce(DIMINUIR_PIN, DEBOUNCE_TIME);

        void setup() {
        pinMode(LED_PIN, OUTPUT);
        pinMode(AUMENTAR_PIN, INPUT_PULLUP);
        pinMode(DIMINUIR_PIN, INPUT_PULLUP);
        pinMode(led,OUTPUT);
        pinMode(botao,INPUT);
        digitalWrite(botao,HIGH);
        // digitalWrite(led, HIGH);

        Serial.begin(9600);
        Serial.println(“Tutorial Botao v.1.0.0”);
        }

        void loop() {
        analogWrite(LED_PIN, brilho);

        if (aumentar.update() ) {
        if (aumentar.read() == LOW ) {
        aumentar.rebounce(20);

        if (brilho 0)
        brilho –;

        Serial.print(“Diminuir o brilho do LED: “);
        Serial.println(brilho);
        }
        }
        }
        void ledd() {
        int valor = digitalRead(botao);
        if (valor == HIGH) {
        while (digitalRead(botao) == HIGH){
        delay(100);
        }
        brilho = !brilho;
        digitalWrite(led, brilho);

        }
        }

        1. Avatar de SamC
          SamC

          vi o código por alto e estão aqui vários erros de iniciante

          pinMode(botao,INPUT); // o botão assim estará ligado da forma “tradicional” com uma resistência, se o ligaste da forma que está aqui no esquema e com esse código arriscas-te a queimar esse I/O pin do arduino. o artigo explica isso

          parei a análise do código aqui:
          if (brilho 0)
          brilho –;

          !!! estão aí erros “básicos” de programação. O meu conselho é começares a “brincar” com código ainda mais simples para treinares a programação porque uma letra a mais faz diferença (tens uma função chamada ledd (que está “perdida” no meio do código)

          Daqui a um tempo quando estiveres mais à vontade já vais conseguir mexer neste código (que é de nível básico, mas ainda exige os mínimos de conhecimentos)

  14. Avatar de Giovanni
    Giovanni

    Boa tarde. Gostei da ideia, mas a página pra download do sketch não está mais disponível?

      1. Avatar de Joao Pedro
        Joao Pedro

        boa noite amigo como faço para baixar a biblioteca não está indo o link.Poderia me ajudar?

        1. Avatar de Michel
          Michel

          Realmente. A biblioteca .zip não está funcionando

  15. Avatar de Curso de Arduíno Online
    Curso de Arduíno Online

    To procurando informações e gostei do conteúdo, passando pelo seu blog para conhecer mais seu trabalho, muito obrigado por compartilhar.