Formas para ligar e desligar um led (programação Arduino)

Objetivo

O objetivo deste tutorial é mostrar formas diferentes de programação para ligar e desligar um led usando um único botão (push button) e o Arduino. Os formatos apresentados no tutorial poderão ser escolhidos para serem utilizados em aplicações nos seus projetos para ligar e desligar um led ou qualquer outro componente eletrônico.

Obs.: Os botões de pressão (push button) apenas mudam seu estado enquanto o botão está sendo pressionado, voltando ao seu estado original quando o botão é liberado. Neste projeto, vamos criar várias rotinas diferentes de programação para atribuir a um só botão duas funções de ligar e desligar um led ou um componente eletrônico qualquer.

Critérios utilizados

1. Circuito eletrônico

1.1. Para a montagem do push button no circuito, utilizaremos o sistema de resistor pull-up interno do Arduino.

1.1.1. Circuito Pull-up interno do Arduíno: Nível lógico  (HIGH ou 1) no estado normal e Nível lógico (LOW ou 0) quando pressionado. Neste caso não precisaremos utilizar um resistor para garantir um nível estável, pois utilizaremos um resistor interno do Arduino. Para isto, basta habilitar o resitor pull-up interno do Arduino através da programação, utilizando pinMode(). Leia: Como usar o push button com Arduino (programação)

 1.2. A montagem do circuito deverá ser constituída de um botão (push button) conectado na entrada do Arduino, porta digital 2, e o led conectado na saída do Arduino, porta digital 8. Utilize um resistor de 150Ω ou superior para a montagem do led. Leia: Projeto 02b - Led apaga com push button pressionado (pull-up interno do Arduino)   Veja o desenho da montagem abaixo:

2. Tipo de ação do botão (push button)

2.1. Como critério adotaremos o padrão para que o a carga (led) seja acionada (liga ou desliga) ao pressionarmos o botão. Desta forma, quando pressionarmos o botão, nível lógico LOW, o led será ativado ou desativado, e ao soltarmos o botão será iniciado um novo ciclo.

2.2. Ao manter o botão pressionado a ação não será repetida, ou seja, o programa irá esperar que o botão seja liberado para iniciar um novo ciclo. Para isso podemos utilizar a linha de comando: while (!digitalRead(buttonPin)) {}

Forma nº 1 - Com state dentro do loop

3. Esta é a forma mais clássica e muito utilizada pelos programadores. Começamos com a variável "state = 0" e vamos alternando entre 0 (false) e 1 (true) a cada vez que pressionamos o botão. Teste o código abaixo:

3.1. Leia o Projeto 04a - Push Button como interruptor - liga e desliga (padrão para pull-down ou pull-up) que explica os detalhes do projeto.

/*******************************************************************************
*
*    Programação 1 – Push button com funão liga / desliga
*                   http://squids.com.br/arduino
*
*******************************************************************************/

// set pinos Arduino
const int buttonPin = 2; // entrada digital - pushbutton
const int ledPin = 8; // saída digital -  LED
 
// set variáveis
boolean state = 0; //  variável para armazenar valores do pushbutton
 
void setup() {
  // define pinos de saída e entrada
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP); // pullup interno do Arduino
}
 
void loop(){
  if (!digitalRead(buttonPin)) {   // botão pressionado - LOW (true)
    state = !state; // inverte valor da variável state
    if (state) {
      // liga o led
      digitalWrite(ledPin, HIGH); // liga se state for 1
    } else {
      // desliga o led
      digitalWrite(ledPin, LOW); // desliga se state for 0
    }
    while (!digitalRead(buttonPin)) {} // aguarda soltar o botão
    delay(150); // delay para reduzir o efeito bouncing
  }
}

3.1. Abaixo segue dados da memória utilizada pelo Arduino com este programa:

Forma nº 2 - Com state e função fora do loop

4. Esta é a mesma forma clássica do código anterior, mas com uma vantagem: o controle do botão fica fora do loop. Isto deixa o código mais organizado. Teste o código abaixo:

/*******************************************************************************
*
*    Programação 2 – Push button com funão liga / desliga
*                   http://squids.com.br/arduino
*
*******************************************************************************/

// set pinos Arduino
const int buttonPin = 2; // entrada digital - pushbutton
const int ledPin = 8; // saída digital -  LED
 
// set variáveis
boolean state = 0; //  variável para armazenar valores do pushbutton
 
void setup() {
  // define pinos de saída e entrada
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP); // pullup interno do Arduino
}
 
void loop(){
  readPushButton();
}

void readPushButton() {
  if (!digitalRead(buttonPin)) {   // botão pressionado - LOW (true)
    state = !state; // inverte valor da variável state
    if (state) {
      // liga o led
      digitalWrite(ledPin, HIGH); // liga se state for 1
    } else {
      // desliga o led
      digitalWrite(ledPin, LOW); // desliga se state for 0
    }
    while (!digitalRead(buttonPin)) {} // aguarda soltar o botão
    delay(150); // delay para reduzir o efeito bouncing
  }
}

4.1. Abaixo segue dados da memória utilizada pelo Arduino com este programa:

Forma nº 3 - Usando o switch para controle

5. Nesta forma usamos o switch...case para o controle do botão. O switch...case substitui o comando if e é muito utilizado para a criação de menus. Teste o código abaixo:

/*******************************************************************************
*
*    Programação 3 – Push button com funão liga / desliga
*                   http://squids.com.br/arduino
*
*******************************************************************************/

// set pinos Arduino
const int buttonPin = 2; // entrada digital - pushbutton
const int ledPin = 8; // saída digital -  LED
 
// set variáveis
boolean state = 1; //  variável para armazenar valores do pushbutton
 
void setup() {
  // define pinos de saída e entrada
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP); // pullup interno do Arduino
}
 
void loop(){
  readPushButton();
}

void readPushButton() {
  if (!digitalRead(buttonPin)) {   // botão pressionado - LOW (true)
    state = !state; // inverte valor da variável state
    switch(state) {
      case 0: // caso esteja apagado
      digitalWrite(ledPin, HIGH); // liga led
      break;
      case 1: // caso esteja aceso
      digitalWrite(ledPin, LOW); // desliga led
      break;  
    }
    while (!digitalRead(buttonPin)) {} // aguarda soltar o botão
    delay(150); // delay para reduzir o efeito bouncing
  }
}

 5.1. Abaixo segue dados da memória utilizada pelo Arduino com este programa. Observe que o valor da memória utilizada foi ligeiramente maior que nos exemplos anteriores.

Forma nº 4 - Usando o operador ternário

6. Nesta forma usamos o operador ternário, deixando o código muito mais elegante. Leia Como utilizar o operador ternário na programação com Arduino. Teste o código abaixo: 

/*******************************************************************************
*
*    Programação 4 – Push button com funão liga / desliga
*                   http://squids.com.br/arduino
*
*******************************************************************************/

// set pinos Arduino
const int buttonPin = 2; // entrada digital - pushbutton
const int ledPin = 8; // saída digital -  LED
 
// set variáveis
boolean state = 0; //  variável para armazenar valores do pushbutton
 
void setup() {
  // define pinos de saída e entrada
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP); // pullup interno do Arduino
}
 
void loop(){
  readPushButton();
}

void readPushButton() {
  if (!digitalRead(buttonPin)) { // verifica se o botão foi acionado
    state = !state; // inverte valor da variável variable_buttonEstado
    state ?  digitalWrite(ledPin, HIGH) :  digitalWrite(ledPin, LOW);
    while (!digitalRead(buttonPin)) {} // aguarda soltar o botão
    delay(150); // delay para reduzir o efeito bouncing
  }
}

 6.1. Abaixo segue dados da memória utilizada pelo Arduino com este programa:

Forma nº 5 - Sem a variável state

7. Nesta forma eliminamos a variável "state" dando lugar ao comando digitalRead(), que vai ler se o led está ligado ou desligado, alternando o seu estado. Teste o código abaixo: 

 /*******************************************************************************
*
*    Programação 5 – Push button com funão liga / desliga
*                   http://squids.com.br/arduino
*
*******************************************************************************/

// set pinos Arduino
const int buttonPin = 2; // entrada digital - pushbutton
const int ledPin = 8; // saída digital -  LED
 
void setup() {
  // define pinos de saída e entrada
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP); // pullup interno do Arduino
}
 
void loop(){
  readPushButton();
}

void readPushButton() {
  if (!digitalRead(buttonPin)) { // verifica se o botão foi acionado
    if (!digitalRead(ledPin)) { // se tiver apagado 
      digitalWrite(ledPin, HIGH);
    } else digitalWrite(ledPin, LOW);
    while (!digitalRead(buttonPin)) {} // aguarda soltar o botão
    delay(150); // delay para reduzir o efeito bouncing
  }
}

  7.1. Abaixo segue dados da memória utilizada pelo Arduino com este programa:

Forma nº 6 - Sem a variável state e o uso do operador ternário

8. Nesta forma usamos o comando digitalRead() junto com o operador ternário, deixando o código mais enxuto. Teste o código abaixo: 

/*******************************************************************************
*
*    Programação 6 – Push button com funão liga / desliga
*                   http://squids.com.br/arduino
*
*******************************************************************************/

// set pinos Arduino
const int buttonPin = 2; // entrada digital - pushbutton
const int ledPin = 8; // saída digital -  LED
 
void setup() {
  // define pinos de saída e entrada
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP); // pullup interno do Arduino
}
 
void loop(){
  readPushButton();
}

void readPushButton() {
  if (!digitalRead(buttonPin)) { // verifica se o botão foi acionado
    !digitalRead(ledPin) ? digitalWrite(ledPin, HIGH) : digitalWrite(ledPin, LOW);
    while (!digitalRead(buttonPin)) {} // aguarda soltar o botão
    delay(150); // delay para reduzir o efeito bouncing
  }
}

8.1. Abaixo segue dados da memória utilizada pelo Arduino com este programa:

Forma nº 7 - Invertendo o valor do estado do botão no próprio comando

9. Nesta forma mais concisa ainda e mais elegante, vamos inverter o valor do sinal do  usamos o comando digitalRead() junto com o operador ternário, deixando o código mais enxuto. Teste o código abaixo: 

/*******************************************************************************
*
*    Programação 7 – Push button com funão liga / desliga
*                   http://squids.com.br/arduino
*
*******************************************************************************/

// set pinos Arduino
const int buttonPin = 2; // entrada digital - pushbutton
const int ledPin = 8; // saída digital -  LED
 
void setup() {
  // define pinos de saída e entrada
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP); // pullup interno do Arduino
}
 
void loop(){
  readPushButton();
}

void readPushButton() {
  if (!digitalRead(buttonPin)) { // verifica se o botão foi acionado
    digitalWrite(ledPin,!digitalRead(ledPin)); // lê o sinal do botão e inverte
    while (!digitalRead(buttonPin)) {} // aguarda soltar o botão
    delay(150); // delay para reduzir o efeito bouncing
  }
}

 9.1. Abaixo segue dados da memória utilizada pelo Arduino com este programa:

Forma nº 8 - Substituindo o if por while e Invertendo o valor do estado do botão no próprio comando

10. Nesta forma substituímos o if por while na leitura do botão e fazemos com que o programa fique parado até que se pressione o botão, acendendo ou apagando o led em seguida. É muito útil em aplicações específicas. Teste o código abaixo:

10.1. Atenção: Esta forma interrompe o programa e aguarda o botão ser pressionado para continuar. Use somente em casos específicos.

 /*******************************************************************************
*
*    Programação 8 – Push button com funão liga / desliga
*                   http://squids.com.br/arduino
*
*******************************************************************************/

// set pinos Arduino
const int buttonPin = 2; // entrada digital - pushbutton
const int ledPin = 8; // saída digital -  LED
 
void setup() {
  Serial.begin(9600);
  // define pinos de saída e entrada
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP); // pullup interno do Arduino
}
 
void loop(){
  readPushButton();
  Serial.println(digitalRead(ledPin));
  
}

void readPushButton() {
  // Aguarda pressionar o botão
    while(digitalRead(buttonPin)) { } // espera apertar o botão para iniciar
    digitalWrite(ledPin,!digitalRead(ledPin)); // lê o sinal do botão e inverte
    while (!digitalRead(buttonPin)) { }  //esperera soltar o botão  
    delay(150); // delay para reduzir o efeito bouncing
}

10.2. Abra o Monitor Serial e observe que o valor lido pelo comando digitalRead() só será exibido ao pressionar o botão. Caso contrário, o programa ficará parado aguardando o botão ser pressionado novamente.

10.3. Nesta forma obtemos uma redução no número de linhas e na memória utilizada. Abaixo segue dados da memória utilizada pelo Arduino com este programa:

Forma nº 9 - Utilizando registradores (manipulação direta de portas do Arduino)

11. Esta é a forma mais profissional, onde acessamos diretamente às portas do Arduino sem a necessidade de compilação. Isto torna tudo mais rápido com uso bem menor de memória utilizada.

11. Atenção: O código abaixo foi desenvolvido para Arduino com microcontrolador ATmega328. Outros microcontroladores podem ter configurações diferentes. Leia Projeto 81 - Ligar e desligar um led por manipulação direta de portas do Arduino 

 /*******************************************************************************
*
*    Programação 9 – Push button com funão liga / desliga
*                   http://squids.com.br/arduino
*
*******************************************************************************/

const byte BOT = (1<<2); //  pino digital 2 (bit 2 da Porta D)
const byte LED = (1<<0); //  pino digital 8 (bit 0 da Porta B)

void setup() {
  DDRB |= LED; // Configura o pino 3 como OUTPUT (1) na porta B
  DDRD &= ~BOT; // Configura o pino 2 como INPUT (0) na porta D
  PORTD |= BOT; // Habilita o pullup interno (1) (INPUT_PULLUP)
  
  readPushButton(); // lê o botão e realiza a ação
}

void readPushButton() {
    while (1) {
    if (!(PIND &BOT)) {
      PORTB ^= LED;
      while (!(PIND &BOT))  { }
      delay(150); // debouncing
    }
  }
}

 11.1. Nesta forma obtemos uma redução considerável da memória utilizada. Abaixo segue dados da memória utilizada pelo Arduino com este programa:

Forma nº 10 - Utilizando interrupção externa

12. Esta é a forma deve ser utilizada apenas nos casos em que há a necessidade de manter 2 ou mais atividades simultâneas. Assim, quando você aciona o botão, é executada a ação sem interromper as demais atividades do circuito. Leia: Projeto 78 - Como realizar interrupção externa no Arduino usando sensor de toque.

12.1. Como a interrupção externa gera uma ação muito rápida, somente o delay utilizado no software não será suficiente para evitar as oscilações geradas pelo efeito "bouncing". É recomendável utilizar um capacitor cerâmico de 2,0nF a 10nF na montagem do botão. Veja abaixo como conectar o capacitor cerâmico. Leia: Projeto 82 - Como realizar interrupção externa utilizando registradores do Arduino

12.2. Teste o código abaixo:

 /*******************************************************************************
*
*    Programação 10 – Push button com funão liga / desliga
*                   http://squids.com.br/arduino
*
*******************************************************************************/

// set pinos Arduino
const int buttonPin = 2; // entrada digital - pushbutton
const int ledPin = 8; // saída digital -  LED

// set variables
boolean state = 0;
 
void setup() {
  // define pinos de saída e entrada
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP); // pullup interno do Arduino

  // -- Configura Interrupção Externa int 0 -- pino 2 Arduino
  // Chama função "extInt", quando houver o toque no botão
  attachInterrupt(0, extInt, FALLING);  
}
 
void loop(){
  readPushButton();  
}

void readPushButton() {
  // liga ou desliga o led
   if(state){
       digitalWrite(ledPin,HIGH); //inverte o estado do Led
   } else digitalWrite(ledPin, LOW);

   delayMicroseconds(50000); // debouncing
}

// --- função a ser executada quando houver interrupção ---
void extInt() {
  state = !state;
}

 12.3. Nesta forma obtemos uma pequena redução da memória utilizada no Arduino em relação ao primeiro skecthc. Abaixo segue dados da memória utilizada pelo Arduino com este programa:

 

Forma nº 11 - Utilizando interrupção externa com manipulação direta

13. Esta é a forma mais econômica possível, pois executamos todos os comandos com acesso direto às portas do Arduino sem a necessidade de compilação. Isto torna tudo muito mais rápido com uso bem menor da memória utilizada. Este formato também pode ser utilizado quando há a necessidade de manter 2 ou mais atividades simultâneas, ou seja, a interrupção do botão não afeta as demais atividades do circuito. Leia: Projeto 78 - Como realizar interrupção externa no Arduino usando sensor de toque.

13.1. Atenção: O código a seguir foi desenvolvido para Arduino com microcontrolador ATmega328. Outros microcontroladores podem ter configurações diferentes. Leia Projeto 81 - Ligar e desligar um led por manipulação direta de portas do Arduino 

13.2. Como a interrupção externa gera uma ação muito rápida e não foi utilizado nenhum delay no software para evitar as oscilações geradas pelo efeito "bouncing", é necessário utilizar um capacitor cerâmico de no mínimo 10nF na montagem do botão. Veja abaixo como conectar o capacitor cerâmico. Leia: Projeto 82 - Como realizar interrupção externa utilizando registradores do Arduino

13.2.1. Caso precise melhorar ainda mais o efeito "bouncing" do botão, considere aumentar o capacitor cerâmico utilizado.

13.3. Teste o código abaixo:

 /*******************************************************************************
*
*    Programação 11 – Push button com funão liga / desliga
*                   http://squids.com.br/arduino
*
*******************************************************************************/

const byte BOT = (1<<2); //  pino digital 2 (bit 2 da Porta D)
const byte LED = (1<<0); //  pino digital 8 (bit 0 da Porta B)

void setup() {
  DDRB |= LED; // Configura o pino 8 como OUTPUT (1) na porta B
  DDRD &= ~BOT; // Configura o pino 2 como INPUT (0) na porta D
  PORTD |= BOT; // Habilita o pullup interno (1) (INPUT_PULLUP)

  EIMSK |= (1<<INT0) | (1<<INT1); // habilita a interrupção externa int 0 e int 1

  EICRA |= (1<<ISC01) | (0<<ISC00);  // configura interrupção externa int 0 - FALLING (pino 2)

  sei(); // flag que habilita as interrupções globalmente

  PORTB &= ~LED; // inicia com led desligado (LOW)
}  

void loop() {  
}

// interrupções ISR's
ISR(INT0_vect) {
  PORTB ^= LED;
}

  13.4. Nesta forma obtemos a melhor condição de uso de memória, pois quase tudo é processado diretamente nas portas do Arduino, sem a necessidade de compilação.  Abaixo segue dados da memória utilizada pelo Arduino com este programa:

 

O anúncio abaixo ajuda a manter o Squids Arduino funcionando.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Compartilhe:

Publicidade

Doações

Contribua pra manter o site online :)

Inscreva-se no canal Squids

Advertisement

Squids Arduino News

Básico - Hub 014 Controlando led RGB com potenciômetros (RGB Color Mixer)   Sugerido por: Ronaldo A Junior Objetivo do misturador de cores Controlar as cores de um led RGB mediante 3 poten...

Desafio 94 - Projeto 103 Medir iluminância em 3 modos de precisão - BH1750 e Arduino Com base no Projeto103 - Como usar o sensor BH1750 com Arduino sem auxílio de biblioteca específica, resolva...

Básico - Projeto 103 Usando o sensor BH1750FVI sem biblioteca - luminosidade Objetivo O objetivo deste projeto é mostrar como utilizar o sensor de luz BH1750FVI junto com o Arduino para determi...

Intermediário - Projeto 17 Medir distâncias com sensor HC-SR04, RGB, display OLED e Arduino Objetivo Utilizar o sensor ultrassônico HC-SR04 junto com o Arduino para medir distâncias entre o sen...

Desafio 93 - Projeto I16 Medir distâncias com sensor ultrassônico / indicador luminoso Com base no projeto I16 - Como medir distâncias por meio de um sensor ultrassônico HC-SR04 com Arduino e d...

Outros artigos

Mais: Básico Desafios Projetos Básicos Projetos Intermediários

Você está preparado?

Topo