Arduino: relé e millis()

Usar o relógio interno do Arduino com o metodo millis() permite criar algoritmos que podem rodar simultaneamente em paralelo, o que não acontece quando usamos delay(), que “pausa” o Arduino por um tempo determinado.

Abaixo um código exemplo para o terrário do NANO, onde ligamos e desligamos uma lâmpada de 8 em 8 horas (mas que poderia ser qualquer intervalo de tempo). A partir desse modelo pode-se criar outras variáveis e ciclos para controlar outros relés (para água por exemplo), e outros dispositivos.

unsigned long tempo_luz = 0;
unsigned long tempo_luz_ciclo = 8L * 60L * 60L * 1000L; // 8 horas

boolean volt_luz = LOW;
int pino_luz = 8;

void setup(){
  Serial.begin(9600);
  Serial.print("Ciclo da luz => ");
  Serial.print(tempo_luz_ciclo);
  Serial.print("; ");
  print_clock(tempo_luz_ciclo);

  pinMode(pino_luz, OUTPUT);
}
void loop(){
  unsigned long tempo = millis();
  print_clock(tempo); 

  // se millis atual menos ultimo millis guardado for maior que o ciclo desejado
  if(tempo - tempo_luz > tempo_luz_ciclo){
    // guardar millis
    tempo_luz = tempo;
    // inverter boolean
    volt_luz = !volt_luz;
    // enviar novo valor ao pino
    digitalWrite(pino_luz, volt_luz);
    Serial.println("LUZ");
  }

  delay(1000);
}

void print_clock(unsigned long t){
  Serial.print((t/1000/60/60)); // converter millis para horas
  Serial.print(" horas, ");
  Serial.print((t/1000/60) % 60); // converter millis para minutos
  Serial.print(" minutos, ");
  Serial.print((t/1000) % 60); // converter millis para segundos
  Serial.println(" segundos");
  // o simbolo % (modulo) é o resto da divisao, serve para loopar o valor, por exemplo:
  // 2 % 10 => 2; dois dividido por dez é zero, resta 2
  // 9 % 10 => 9; nove dividido por dez é zero, resta 9
  // 10 % 10 => 0; dez dividido por dez é um, resta 0
  // 12 % 10 => 2; doze dividido por dez é um, resta 2
}

uma explicação rápida:

unsigned long tempo = millis();

usamos unsigned long para guardar valores positivos muito longos, adequado para guardar o valor de millis(), que retorna o tempo sempre em milisegundos (1000 equivale a um segundo).

unsigned long tempo_luz_ciclo = 8L * 60L * 60L * 1000L;

para ler mais facilmente os intervalos, multiplicamos valores como 10 * 1000; mas em C, para definir um número longo a partir de uma operação matemático, precisamos indicar o tipo dos valores, no caso L de long; 10L * 1000L seriam 10.000 milisegundos (= 10 segundos). 8 horas seriam como colocamos: 8L (horas) * 60L (minutos em uma hora) * 60L (segundos em um minuto) * 1000L (milisegundos em um segundo)

void print_clock(unsigned long t){...}

criamos o método print_clock, que recebe como parametro um unsigned long e envia para porta serial o cálculo do tempo em que o programa está rodando. criar os próprios métodos ajuda a manter o código modular, fácil de ser transportado para outros programas.

if(tempo - tempo_luz > tempo_luz_ciclo){...}

o ciclo só é executado quando a diferença entre o millis atual (tempo) e o millis guardado (tempo_luz) for maior que o ciclo que definimos (tempo_luz_ciclo).
quando o programa começa, tempo_luz é zero, então assim que o millis() atinge um valor maior que tempo_luz_ciclo, ele roda pela primeira vez. aí então ele guarda o valor de tempo_luz pela primeira vez:

tempo_luz = tempo;

depois disso, ele inverte o boleano volt_luz para ligar ou desligar o relé

volt_luz = !volt_luz;

7 comentários em “Arduino: relé e millis()

  • 04/06/2013 em 21:36
    Permalink

    bom, é só um exemplo, pois ficou decidido que vamos usar sensores LDR para saber quando o terrário está iluminado pelo sol ou não. Para água podemos usar esse exemplo, ou então, colocar sensores de humidade no solo.

    Resposta
    • 19/12/2016 em 12:31
      Permalink

      Olá, Elias! Para alternar o estado do LED (aceso e apagado) a cada 10 segundos, basta trocar o valor da variável ‘tempo_luz_ciclo’ na segunda linha do código para 10000.

      Usamos 10000 pois a unidade e milissegundos. 10 segundos = 10000 milissegundos.

      Abraços.

      Resposta
  • 01/09/2017 em 16:33
    Permalink

    George, seria assim, 1 minuto desligado, 10 segundos ligados. Nesse caso, acredito que tenha alguma alteração no código?

    Resposta
  • 31/10/2017 em 08:22
    Permalink

    Só que depois de 49,7 dias o Relay vai travar ! Por que ? O “unsigned long” permite até 4.294.967.295 ms ( ou pouco mais de 4 trilhões de ms ), e isto ao ser “convertido” dará 49,7 dias ( ou “49 dias 16 horas e 48 minutos” ) contínuos de funcionamento. Ao ultrapassar este valor o valor “se torna negativo”, e como “unsigned long” só pode ser positivo ( 32 bits ou 4 bytes ) o sketch causa um “deadlock” ! Então, só basta uma rotina para verificar se este máximo valor foi ultrapassado, e se foi, zerar o contador ( o “tempo” no exemplo ). E isto tem várias maneiras de se fazer, é apenas “trabalho braçal” ( pois Programadores “old school” se preocupam com “testes de mesa” e limites, e o resto – comum hoje em dia – só “aperta teclas”, ainda “não pensam” ). Boa Sorte e Abraços !

    Resposta
  • 15/11/2018 em 13:31
    Permalink

    como faço para ficar ligado 21 horas e desligado 3 horas

    Resposta

Deixe uma resposta para George Rappel Cancelar resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

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