Arduino – Controlando LEDs com um botão (pushbutton)
Como controlar 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:
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:
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!
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.
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;
}
}
Helcio, copie aqui todo o texto que aparece na área de informações (onde aparece o erro). Deve ter alguma pista ali do que pode estar de errado.
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!
O erro pode estar em uma linha anterior ou posterior à sinalizada… poste o código todo amigo pra eu dar uma olhada…
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)?????
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)?????
Excelente Fabil
Obrigado Leandro!
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.
Muitíssimo obrigado pelo código em c# que controla o led do/no arduino.
Pois a partir deste código poderei colocar em prática as minhas criatividades.
Código com erro. Seria bom testar o código antes de divulgar. Apesar da insistência do outro colaborador em apontar erros, os leitores foram deixados no “vácuo”. Também copiei e colei no tinkercad e não funcionou. Se o código realmente funcionasse seria ótimo para o aprendizado. Que pena!
Código funcional e sem erros. Foi amplamente testado. Se o seu não funcionou, a culpa não é minha.
Aparentemente, algumas pessoas estão com erros de conversão de caractere Unicode ou ainda tipo incorreto de aspas – o que indica que talvez não tenham sequer digitado o código no editor do Arduino. Copiar e colar é uma péssima ideia, pois está levando formatação que pode ser incompatível com o editor de textos.
Mais sobre o assunto aqui: https://askubuntu.com/questions/272741/how-to-fix-compilation-errors-that-mention-stray-342-and-stray-200
Disse Tudo !!
Copiar e colar código fonte costuma dar erro direto !!!
Código ok, ao copiar-colar na linha: if (novoTempo – tempoAnterior < 40) {
no entre aspas o caractere "-" está um traço e o correto é o sinal de menos " – ", troque o traço pelo menos que vao compilar.