fbpx
ArduinoNovidade

Como piscar dois LEDs 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é? 😉

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

Até a próxima!

Kleber Bastos.

Bacharel em Engenharia de Computação. Um dos criadores do Blog da Robótica. Faz parte da equipe Casa da Robótica desde 2017. Apaixonado por tecnologias e pelas “loucuras” que é possível criar usando microcontroladores e impressoras 3D. Ex-BBB, mas isso é uma longa história... que poderá ser contada posteriormente.

Kleber Bastos

Bacharel em Engenharia de Computação. Um dos criadores do Blog da Robótica. Faz parte da equipe Casa da Robótica desde 2017. Apaixonado por tecnologias e pelas “loucuras” que é possível criar usando microcontroladores e impressoras 3D. Ex-BBB, mas isso é uma longa história... que poderá ser contada posteriormente.