fbpx

Como piscar dois Led’s simultaneamente com tempos diferentes sem usar delay no Arduino

Fala pessoal, tudo certo? Bom, neste post eu vou colocar a resposta do desafio postado no instagram @blogdarobotica (Link: https://www.instagram.com/p/CNdW3hyjQ-f/). Se você não viu, então deixo logo abaixo o vídeo do desafio:

Existem diversas formas de conseguir o resultado mostrado acima e o mais interessante desse desafio foi olhar as respostas em que foram sugeridas formas diferentes de como programar. E sim, cada pessoa pensa e programa de uma forma diferente e o bacana da programação é justamente isso: Diferentes formas de se chegar a um objetivo, no entanto, vale ressaltar que algumas formas vão ser mais eficientes que outras.

Abaixo vou mostrar a forma que eu programei, não significa que seja a melhor, porém deixo aí para vocês estudarem e compararem com o código de vocês e a partir daí novas soluções (melhores) podem sair.

Código Fonte:

/*
----------- Resposta do #Desafio 1 --------------
=================================================
==   BLOG DA ROBOTICA - www.blogdarobotica.com ==
=================================================
Autor: Kleber Bastos
E-mail: contato@blogdarobotica.com
Fanpage: facebook.com/blogdarobotica
YouTube: youtube.com/user/blogdarobotica
Instagram: instagram.com/blogdarobotica
*/

//Definições de variáveis
#define led_1 5                                       //pino em que o led 1 ficará
#define led_2 6                                       //pino em que o led 2 ficará

//Declaração de variáveis
unsigned long tempoAtual;                             //variável que irá receber o tempo em que o arduino está ligado em milissegundos. Long armazenam valores maiores que o tipo int e o unsgined significa que estamos desconsiderando valores negativos, fato que aumenta a capacidade de armazenamento do tipo long

long tempoDecorrido = 0;                              //variável que contará o tempo decorrido para o led 1
long tempoDecorrido2 = 0;                             //variável que contará o tempo decorrido para o led 2

long tempoLed_1 = 1000;                               //tempo em milissegundos que quero que o led 1 pisque. Pode ser alterado para o tempo que desejar
long tempoLed_2 = 100;                                //tempo em milissegundos que quero que o led 2 pisque. Pode ser alterado para o tempo que desejar

//Condições iniciais do programa
void setup() {
  pinMode(led_1, OUTPUT);                             //seto a porta do led 1 como saída
  pinMode(led_2, OUTPUT);                             //seto a porta do led 2 como saída
}

//Loop 
void loop() {
  tempoAtual = millis();                              //atribuo o tempo (em milissegundos) que o arduino está ligado na variável tempoAtual
  efeito1();                                          //chamo a função efeito1() que é responsável pelo piscar do led 1
  efeito2();                                          //chamo a função efeito2() que é responsável pelo piscar do led 2
}


//Construção da função 1 - Função que faz o led piscar 1000 milissegundos
void efeito1() {

  if (tempoAtual - tempoDecorrido > tempoLed_1) {     //verifica se passou 1000 milissegundos e se sim
    tempoDecorrido = tempoAtual;                      //subsitui o valor que já passou pelo tempo atual
    digitalWrite(led_1, !digitalRead(led_1));         //escreve em led_1 o estado inverso em que ele se encontra, ou seja, se está ligado ele desliga e se estiver desligado o led ligará
  }
}


//Construção da função 2 - Função que faz o led piscar 100 milissegundos
void efeito2() { 

  if (tempoAtual - tempoDecorrido2 > tempoLed_2) {    //verifica se passou 100 milissegundos e se sim
    tempoDecorrido2 = tempoAtual;                     //subsitui o valor que já passou pelo tempo atual
    digitalWrite(led_2, !digitalRead(led_2));         //escreve em led_2 o estado inverso em que ele se encontra, ou seja, se está ligado ele desliga e se estiver desligado o led ligará
  }
}

Algumas observações:

A função millis() é responsável por contar quanto tempo a placa está ligada (em milissegundos) executando aquele sketch (programa) e ela tem um limite, ou seja, depois de 50 dias de programa executando sem que a placa desligue haverá um overflow da variável (vai exceder o limite que ela suporta) e quando isso acontecer o tempo voltará a ser contado do zero. Por esse motivo não usamos millis() como um relógio para contar tempos longos que ultrapasse o limite dos 50 dias. Para fazer isso a solução ideal para tempo é a utilização do módulo RTC.

No nosso caso precisamos apenas contar o tempo decorrido de 1000 milissegundos e 100 milissegundos, logo podemos utilizar a função millis() tranquilamente que mesmo que o arduino fique ligado mais de 50 dias não afetará a execução porque a variável tempoAtual vai zerar e consequentemente as outras variáveis tempoDecorrido e tempoDecorrido2 serão atualizadas.

Por que não usar delay?

Pelo que vi tiveram pessoas que resolveram o desafio usando delay, mas quando nós utilizamos o delay significa que o programa fica parado naquela linha esperando até que o tempo definido dentro do delay passe, ou seja, se você tiver outras coisas para serem executadas posteriormente não vai acontecer porque o programa fica parado. Já com millis não, o programa executa de maneira sequencial e fica verificando se já passou o tempo que eu defini e se não passou ele segue fazendo as coisas que estão nas linhas abaixo. Só depois de já ter decorrido o tempo especificado é que vai entrar no condicional e fazer o que tá lá dentro. Então sempre que possível use millis() no lugar de delay. =)

Ah, outra coisa bem legal nesse código é essa parte:

digitalWrite(led_2, !digitalRead(led_2)); //escreve em led_2 o estado contrário em que ele se encontra

E essa linha acima substitui isso:

if ( digitalRead(led_2) == HIGH){ //se o led estiver ligado
   digitalWrite(led_2, LOW); //desligue
}
else { //se não
   digitalWrite(led_2, HIGH); //ligue
}

Tá vendo como existem formas diferentes de fazer a mesma coisa? Legal né =P

Obrigado a todos que participaram do desafio e espero que tenham aprendido coisas novas.

Até a próxima! Att. Kleber Bastos.

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.