Substituir a função delay() por millis() no Arduino
Uma das funções mais conhecidas e utilizadas em programação para Arduino é a função delay(), que permite pausar o programa por um período de tempo especificado, na forma de um parâmetro com o valor em milissegundos desejados.
A função delay() aceita um número inteiro como argumento, o qual representa o tempo em milissegundos que o programa deverá esperar até poder executar a próxima linha de código – ou seja, tempo de pausa.
Por exemplo, para criar uma pausa de 5 segundos você pode simplesmente escrever:
delay(5000);
Porém, apesar de ser muito popular, nem sempre a função delay() é a mais adequada para seu sketch. Um problema sério pode surgir com o emprego dessa função: o Bloqueio de Execução.
Bloqueio de Execução: Ao ser invocada, a função delay() bloqueia a execução do programa, pelo período de tempo especificado, e nenhuma outra instrução pode ser executada durante esse período. Desta forma, enquanto o programa espera o final do delay, ele fica totalmente ocioso.
Desta forma, durante uma chaamda à função delay(), o programa não consegue detectar entrada de sinais, processar dados e nem alterar o status de saída de pinos.
O problema é que muitas vezes precisamos executar rotinas específicas durante esse tempo de pausa.
Para evitar esses problemas, muitas vezes recomendamos empregar a função millis() em lugar da função delay().
A função millis() retorna o número de milissegundos decorridos desde que o programa foi iniciado (ou seja, desde que o Arduino foi ligado).
Esta função permite verificar o relógio do sistema regularmente, de modo que sempre é possível saber o tempo decorrido – e assim calcular intervalos de tempo que podemos pausar, mas sem bloquear a execução de códigos necessários no sketch.
Exemplos
1. Suponha que você queira pausar o programa por um certo período de tempo, como por exemplo 3 segundos. Para fazer isso com delay basta executar a instrução:
delay(3000);
Para realizar a mesma tarefa com millis(), você pode escrever algo como isto:
unsigned long agora = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println("Mensagem escrita a cada 3 segundos");
// Criar a pausa de 3 segundos
agora = millis()
while(millis() < agora + 3000) {
// Pausa de 3 segundos. Nada a fazer
}
}
Como podemos ver, o código é maior e mais trabalhoso, porém realiza a pausa de 3 segundos com muita precisão.
2. Digamos agora que você deseja executar uma instrução por um período de tempo específico, mas sem bloquear a execução de outras funções no programa, como a detecção de interrupções. Por exemplo, acender um LED por 4 segundos e depois apagá-lo, mas ainda assim continuar executando outras tarefas durante esse tempo. Para tal, experimente o código a seguir:
/* Adaptado do exemplo "Blink without Delay" Código original em Domínio Público http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay */ const int LED = 9; int estadoLED = LOW; unsigned long tempoAnterior = 0; // Armazena o último momento em que o LED foi atualizado const long PERIODO = 4000; void setup() { Serial.begin(9600); pinMode(LED, OUTPUT); } void loop() { unsigned long tempoAtual = millis(); if (tempoAtual - tempoAnterior >= PERIODO) { tempoAnterior = tempoAtual; if (estadoLED == LOW) { estadoLED = HIGH; } else { estadoLED = LOW; } digitalWrite(LED, estadoLED); } Serial.println("Executado sem interferir no acendimento do LED"); }
Esse código resolve nosso problema de bloqueio do programa, pois é possível executar outras funções enquanto o LED estiver apagado ou aceso pelos 4 segundos determinados. O programa conta o tempo para alterar o estado do LED, e permite que outras rotinas sejam executadas enquanto isso.
Referências
Adafruit: Ditch the Delay
DZone – IoT Zone: Arduino: Using millis() Instead of delay()
