Arduino – Controlando LEDs com um botão (pushbutton)

Controlando LEDs com um botão (pushbutton) no Arduino

Neste projeto vamos efetuar o controle de três LEDs por meio de um botão de pressão (pushbutton), de modo que quando o botão for pressionado, o estado dos LEDs mudará – se estiverem acendendo em sequência, irão parar, e se estiverem apagados, iniciarão a sequência acendendo um por um. Para que isso seja possível, vamos lançar mão do recurso de Interrupções presente no Arduino.

Para isto vamos precisar dos seguintes componentes:

  • 1 Chave Pushbutton
  • 3 LEDs, cores a sua escolha
  • 3 Resistores de 220 Ω
  • 1 Resistor de 10 KΩ
  • 1 Arduino Uno ou compatível

Na figura a seguir temos o diagrama esquemático para as ligações dos componentes utilizados no circuito:

Arduino - Controlando LEDs com um pushbutton

Fig. 01 – Esquema de um Arduíno controlando três LEDs por meio de um botão

Os três resistores de 220 Ω são utilizados para limitar a corrente nos LEDs, impedindo que sejam danificados durante o uso. Já o resistor de 10 KΩ é utilizado como resistor de pull-down, para manter o pino D2 do Arduino em nível baixo de tensão, evitando assim ruídos que possam causar o disparo do circuito inesperadamente.

Na figura a seguir vemos o protótipo do circuito montado em uma breadboard:

Arduino - Controlando LEDs com pushbutton

Fig. 02 – Controlando LEDs com um botão.

E, no quadro abaixo, o código do sketch que foi utilizado para realizar o projeto. Logo na sequência vamos explicar seu funcionamento, incluindo algumas noções sobre as interrupções citadas no início do artigo.

volatile int estado = LOW;
int LEDs[] = {8, 9, 10};
int contador = 0;
int timer = 100;
int pausa = 500;
 
void setup() {
for (contador=0;contador<3;contador++){
pinMode(LEDs[contador], OUTPUT);
}
attachInterrupt(0, ligaDesliga, RISING);
}
 
void loop() {
if (estado) {
for (contador=0;contador<3;contador++) {
digitalWrite(LEDs[contador], HIGH);
delay(timer);
}
delay(pausa);
for (contador=0;contador<3;contador++) {
digitalWrite(LEDs[contador], LOW);
delay(timer);
}
delay(pausa);
}
}
 
void ligaDesliga() {
static unsigned long tempoAnterior = 0;
unsigned long novoTempo = millis();
if (novoTempo – tempoAnterior < 40) {
}
else {
estado = !estado;
tempoAnterior = novoTempo;
}
}

Funcionamento do sketch

Vamos analisar a operação do código usado no nosso projeto. Primeiramente, temos a declaração de algumas variáveis, logo no início do código:

volatile int estado = LOW;
 int LEDs[] = {8, 9, 10};
 int contador = 0;
 int timer = 100;
 int pausa = 500;

Todas as varáveis são do tipo int, número inteiro. A variável estado é utilizada para armazenar o estado dos LEDs: quando em nível alto (HIGH), os LEDs estarão piscando, e quando em nível baixo (LOW), estarão apagados. Por padrão, o programa inicia com os LEDs apagados, e a variável é declarada como volatile, palavra-chave usada para definir variáveis que podem ser alteradas fora da seção do sketch onde são declaradas.

A variável LEDs é, na verdade, um array (vetor) de três posições, que conterá os números dos pinos onde os três LEDs estarão conectados no Arduíno. Já a variável count é usada dentro de laços for para, primeiramente, configurar os pinos onde os LEDs estão conectados como pinos de saída, e posteriormente, para definir a sequência na qual os LEDs serão acesos e apagados.

A variável timer permite configurar o intervalo de tempo entre o acendimento de cada LED, sendo inicializada com o valor de 100 ms (0,1 segundo). E a variável pausa define um período de pausa entre o acendimento e o apagamento dos LEDs, tendo o valor padrão de 500 ms (meio segundo). Você pode experimentar com outros valores de temporização se desejar.

Função setup()

Na função de setup do Arduíno temos um laço for que é utilizado para configurar o modo de funcionamento dos pinos do Arduíno onde os LEDs estão conectados, por meio da função pinMode(), e também a configuração do pino de interrupção (pino 2, interrupção 0), que é configurado para disparar a função ligaDesliga, no modo RISING (quando o nível passa de baixo para alto).

Função loop()

No corpo principal do programa é verificado primeiramente o estado dos LEDs; se o estado for Verdadeiro (TRUE), então os LEDs serão acesos, por meio do uso da função digitalWrite, que envia o nível lógico HIGH para os pinos de saída onde os LEDs estão conectados, e se o estado for Falso (FALSE), então os LEDs serão apagados (nível lógico baixo com a função digitalWrite).

Função ligaDesliga()

Essa é uma função definida pelo programador. Ela possui grande importância no sketch, pois é invocada sempre que o botão é pressionado, permitindo alterar o estado dos LEDs (ligar / desligar a sequência de acendimento), e é declarada com tipo de retorno void, ou seja, não retorna valores ao programa, apenas realiza uma operação.

O pino digital 2 (D2) permite usar uma das duas interrupções que o Arduino Uno possui (o Arduino Mega possui quatro interrupções), a interrupção 0. A outra interrupção (1) está ligada ao pino 3. Essa interrupção foi configurada para ser acionada quando o pino alterar seu estado lógico de LOW para HIGH, ou seja, no modo RISING. O pino é mantido no estado LOW pelo uso de um resistor de pull-down, o resistor R4, de 10 KΩ. Usamos esse resistor para que não haja flutuações no nível lógico do pino, que poderiam levar ao seu disparo acidental, provocando funcionamento errático do circuito. Ao pressionarmos o botão, o pino é levado do nível baixo para o nível alto, pois o botão está ligado ao pino +5V da placa, e a interrupção é acionada, chamando a função ligaDesliga que definimos no código.

Quando a função ligaDesliga é acionada, são declaradas duas novas variáveis: tempoAnterior e novoTempo. Usamos essas variáveis para eliminar um problema bastante comum que ocorre ao usarmos chaves mecânicas para acionamento de circuitos eletrônicos: o Bounce.

Bounce

Quando uma chave interruptora é acionada e se move de uma posição aberta (desligada) para fechada (ligada), é muito comum que o contato elétrico não seja perfeito e acabe produzindo sinais espúrios, que chamamos de bounces, o que pode levar à uma variação do sinal de nível baixo para nível alto diversas vezes até que o contado do botão se estabilize. Isso pode fazer, no caso de nosso circuito, com que o nível lógico do pino conectado ao pushbutton se altere de LOW para HIGH diversas vezes, ativando a interrupção a ele conectada de forma análoga.

Geralmente, leva entre 10 e 15 ms para que uma chave se estabilize e o bounce desapareça, e por isso no código vamos usar uma rotina que espera um tempo maior que esse quando a chave é acionada, para eliminar os efeitos do bounce, antes de efetivamente realizar a função programada.

A variável tempoAnterior, do tipo long, é declarada como sendo sem sinal e estática. Uma variável estática mantém seu valor entre chamadas a uma função, e precisamos que essa variável mantenha seu valor a cada chamada para que seja possível calcular o período de pressionamento do botão e, assim, eliminar o bounce.

A variável novoTempo recebe o retorno da chamada da função interna millis(), a qual retorna o número de milissegundos decorridos desde o início do programa, sendo essa atribuição feita cada vez que a rotina de interrupção dor acionada. O programa efetua então uma comparação entre os valores das variáveis novoTempo e tempoAnterior, verificando se existe uma diferença menor do que 40 milissegundos; se a diferença for menor, nada é executado, pois assumimos que o botão não foi pressionado e sim sofreu apenas bounce; já se a diferença for maior que 40 milissegundos, assumimos que o botão foi realmente pressionado e então o estado dos LEDs é invertido (verdadeiro para falso ou falso para verdadeiro), e o valor de novoTempo é atribuído a tempoAnterior, atualizando assim a temporização.

Para testar o programa, após compilá-lo e gravá-lo no Arduíno, basta pressionar o pushbutton e verificar como os LEDs começam a piscar, e são desligados / ligados a cada vez que o botão é pressionado novamente.

É isso aí pessoal, até nosso próximo projeto!

 

Sobre Fábio dos Reis (1333 Artigos)
Fábio dos Reis trabalha com tecnologias variadas há mais de 25 anos, tendo atuado nos campos de Eletrônica, Telecomunicações, Programação de Computadores e Redes de Dados. É um entusiasta de Unix, Linux e Open Source em geral, adora Eletrônica e Música, e estuda idiomas, além de ministrar cursos e palestras sobre diversas tecnologias em São Paulo e outras cidades do Brasil.
Contato: Website

11 Comentários em Arduino – Controlando LEDs com um botão (pushbutton)

  1. Olá. Eu vi seu código e achei interessante mas na hora de compilar, apresentou o seguinte erro.
    sketch_jul06a:29: error: stray ‘\’ in program
    sketch_jul06a.ino: In function ‘void ligaDesliga()’:
    sketch_jul06a:29: error: expected `)’ before ‘u2013’

    • Helcio, as mensagens de erro aparentemente indicam algum erro de digitação do código. Dê uma revisada e tente compilar de novo. Se não funcionar, poste aqui o código todo que você digitou.

  2. Fábio dos Reis, eu olhei, olhei mas é o mesmo o qual você postou no artigo, não notei nada de estranho, só não funcionou aqui. Vou continuar analisando. Abrç.

    volatile int estado = LOW;
    int LEDs[] = {8, 9, 10};
    int contador = 0;
    int timer = 100;
    int pausa = 500;
    void setup() {
    for (contador=0;contador<3;contador++){
    pinMode(LEDs[contador], OUTPUT);
    }
    attachInterrupt(0, ligaDesliga, RISING);
    }
    void loop() {
    if (estado) {
    for (contador=0;contador<3;contador++) {
    digitalWrite(LEDs[contador], HIGH);
    delay(timer);
    }
    delay(pausa);
    for (contador=0;contador<3;contador++) {
    digitalWrite(LEDs[contador], LOW);
    delay(timer);
    }
    delay(pausa);
    }
    }
    void ligaDesliga() {
    static unsigned long tempoAnterior = 0;
    unsigned long novoTempo = millis();
    if (novoTempo – tempoAnterior < 40) {
    }
    else {
    estado = !estado;
    tempoAnterior = novoTempo;
    }
    }

  3. Helcio Alves // 11/07/2016 em 9:41 // Responder

    Bom dia! sinaliza essa linha.
    if (novoTempo – tempoAnterior < 40) {

    E o código de erro é esse em baixo.

    sketch_jul11a:29: error: stray '\' in program
    sketch_jul11a.ino: In function 'void ligaDesliga()':
    sketch_jul11a:29: error: expected `)' before 'u2013'

    Obrigado!

  4. Sócrates Usignolo // 24/01/2017 em 15:33 // Responder

    Boa tarde Fabio tudo bem??
    Adorei seu blog, porém no exemplo acima estou com muito dificuldade, pode me ajudar???No exemplo se a variavel novoTempo recebe os millis(milisegundos que o programa iniciou), Um exemplo adotando 1000 no millis – tempoAnterior que era 0 nunca vai ser menor que 40, então porque usar este if nesta programação.Outra dúvida na programação Else tempoAnterior = novoTempo , porque isso se toda vez que entrar no void ligaDesliga() {
    static unsigned long tempoAnterior = 0;(acontece isso)?????

  5. Sócrates Usignolo // 24/01/2017 em 15:34 // Responder

    Boa tarde Fabio tudo bem??
    Adorei seu blog, porém no exemplo acima estou com muito dificuldade, pode me ajudar???No exemplo se a variavel novoTempo recebe os millis(milisegundos que o programa iniciou), Um exemplo adotando 1000 no millis – tempoAnterior que era 0 nunca vai ser menor que 40, então porque usar este if nesta programação.Outra dúvida na programação Else tempoAnterior = novoTempo , porque isso se toda vez que entrar no void ligaDesliga() {
    static unsigned long tempoAnterior = 0;(acontece isso)?????

  6. Excelente Fabil

  7. Celso Luiz // 11/07/2017 em 12:11 // Responder

    Bom dia, estou interessado em montar um sistema automatizado com as seguintes condições:
    – Ao acionar o botão (push button??), é acionado o relé que terá ligado um exaustor;
    – Durante o funcionamento do mesmo, um LED verde fica aceso;
    – Ao acionar o botão novamente, o relé deverá desligar somente após 5 minutos e, durante esse tempo, um LED amarelo deverá ficar piscando, indicando que está “entrando em hibernação”;
    – Quando concluir o tempo, um LED vermelho acende e fica assim até o próximo acionamento;
    – O mesmo pode acontecer se for o caso de incluir + 3 relés (totalizando 4), sendo que não é necessário que os demais tenham um tempo para desligar;
    – Uma opção interessante seria inserir um display LCD 16×2 para indicar o status (relé 1 ligado e o “nome do equipamento”; relé 2, relé 3… etc) e além disso, poderia indicar o status de preparando para desligar e pronto.

    A dúvida final seria: dá para montar isso no Arduino ou usando um microcontrolador??
    Como poderia ser o esquema de ligação desse sistema?
    Quais componentes eu iria precisar (resistores, etc)?
    Se puder me ajudar, agradeço imensamente!
    Abraço e desde já, muito obrigado.

Escreva um comentário

Seu e-mail não será divulgado


*