A função millis() retorna para o usuário o tempo, em milissegundos, de atividade do programa na placa desde a última vez em que o código foi iniciado. Essa função é capaz de gravar até 4.294.967.295 milissegundos, ou o equivalente a 49,7 dias.
A principal diferença entre essas duas funções se dá pelo fato da função delay(), quando chamada no código, pausar o programa pelo intervalo de tempo determinado pelo programador, impossibilitando o core da placa de realizar qualquer outra atividade durante esse período. Enquanto isso, a função millis( ) não é, necessariamente uma pausa no programa, mas sim, um contador de tempo de atividade do mesmo, que pode ser usado, também, como uma espécie de delay.
Imagine quando a sua placa lê a linha em que está escrito “delay (1000)”. Quando isso acontece, automaticamente ela para por 1000 milissegundos e se mantêm impossibilitada de ler qualquer outra linha durante esse intervalo de tempo.
Já quando utilizamos o millis() como um delay, isso não acontece mais. A placa não executará um trecho do programa durante o período, mas poderá ler e executar todo o resto do código, até que o intervalo de tempo que você escolheu tenha sido atingido. Isso evita que seu código fique travado e que você perca eficiência na hora de executar seu programa. Além disso, também evita que você utilize mais de uma placa microcontrolada em seu projeto.
Diagrama de funcionamento do delay() e do millis()
Antes de tudo, é importante que você saiba como funciona a lógica por trás dessa utilização.
Primeiro, precisamos de uma variável que guarde o valor de millis() para que nós possamos utiliza-lo no código. É importante escolher o tipo de variável correto. O mais indicado é o tipo unsigned long, que é capaz de armazenar de 0 a 4.294.967.295, este último, que é justamente o valor máximo que o millis() pode nos fornecer.
Além disso, precisamos declarar uma variável auxiliar de mesmo tipo, que servirá como uma espécie de “memória” do valor do millis() na última vez que a ação pretendida foi executada.
Não é recomendável utilizar variáveis do tipo int pois são capazes de armazenar entre -2.147.483.648 e 2.147.483.647. Perceba que estamos trabalhando com tempo, e a contagem de tempo tempo inicia-se em zero e é progressivo, sendo incapaz de ser negativo, por isso, perderíamos metade do valor máximo que poderíamos armazenar, caindo de 49,7 dias para 24,85 dias – por esse motivo utilizamos o modificador “unsigned”, que recebe somente valores positivos.
Para facilitar, faremos um LED piscar como exemplo:
unsigned long tempo = 0; /*Variável utilizada para salvar o valor do millis*/ unsigned long auxiliar = 0; /*Variável auxiliar*/ void setup() { pinMode(13, OUTPUT); /*Vamos usar um LED como exemplo*/ }
No void loop (), você deve iniciar igualando uma das variáveis ao millis(), assim, toda vez em que o código passar pela primeira linha, o valor do millis() será atualizado dentro da variável.
unsigned long tempo = 0; /*Variável utilizada para salvar o valor do millis*/ unsigned long auxiliar = 0; /*Variável auxiliar*/ void setup() { pinMode(13, OUTPUT); /*Vamos usar um LED como exemplo*/ } void loop() { tempo = millis (); /*Atualização do valor dentro da variável*/ }
Nesse momento, caso você execute o código dentro da placa, o valor de millis() já estará sendo atualizado dentro da variável.
Agora, vamos definir a condição para que o LED acenda: depois de 1000 milissegundos (1 segundo) após o código ser executado.
unsigned long tempo = 0; /*Variável utilizada para salvar o valor do millis*/ unsigned long auxiliar = 0; /*Variável auxiliar*/ void setup() { pinMode(13, OUTPUT); /*Vamos usar um LED como exemplo*/ } void loop() { tempo = millis (); /*Atualização do valor dentro da variável*/ if (tempo - auxiliar >= 1000){ digitalWrite (13, HIGH); } }
Perceba que a princípio a condição “tempo – auxiliar” será igual a millis(), já que tempo é igual a millis() (linha 13) e auxiliar é igual a zero quando o código inicia (linha 3).
Agora, para que o LED permaneça ligado por um segundo e apague após isso, precisamos que essa subtração seja igual a 2000 milissegundos (1000 milissegundos para ligar + 1000 milissegundos permanecido ligado).
unsigned long tempo = 0; /*Variável utilizada para salvar o valor do millis*/ unsigned long auxiliar = 0; /*Variável auxiliar*/ void setup() { pinMode(13, OUTPUT); /*Vamos usar um LED como exemplo*/ } void loop() { tempo = millis (); /*Atualização do valor dentro da variável*/ if (tempo - auxiliar >= 1000){ digitalWrite (13, HIGH); } if (tempo - auxiliar >= 2000){ digitalWrite (13, LOW); } }
Agora, após 1 ciclo de liga/desliga, o LED precisa novamente acender, e para que a primeira condição (linha 15) seja verdadeira novamente, precisamos igualar o valor da variável “auxiliar” com o valor da variável “tempo”, reduzindo novamente a diferença entre as duas variáveis para zero, de modo a reiniciar o ciclo.
unsigned long tempo = 0; /*Variável utilizada para salvar o valor do millis*/ unsigned long auxiliar = 0; /*Variável auxiliar*/ void setup() { pinMode(13, OUTPUT); /*Vamos usar um LED como exemplo*/ } void loop() { tempo = millis (); /*Atualização do valor dentro da variável*/ if (tempo - auxiliar >= 1000){ digitalWrite (13, HIGH); } if (tempo - auxiliar >= 2000){ digitalWrite (13, LOW); auxiliar = tempo; } }
Dessa forma, o código já estará funcionando, acendendo o LED da porta 13, esperando 1 segundo e apagando ele. Após isso, espera-se mais 1 segundo, o LED acende e o ciclo recomeça.
Diagrama do primeiro exemplo
Verifique abaixo o código em funcionamento:
Para que você perceba o princípio de funcionamento de forma mais clara, faremos um LED piscar em intervalos de 0,4 segundos, e o outro piscar em intervalos de 1 segundo (1000 milissegundos).
Como alterações no código do exemplo anterior, ao invés de 1000 e 2000 milissegundos nas condicionais do primeiro LED, colocaremos 400 e 800 milissegundos.
Para o segundo LED, adicionaremos uma nova variável auxiliar, responsável pela memória do millis() do segundo LED. Ainda, declararemos o pino 12 (2º LED) como OUTPUT e faremos a mesma lógica condicional do exemplo anterior (agora para o 2º LED), adicionando 1000 milissegundos para o LED acender, e em 2000 milissegundos (1000 milissegundos depois), para ele apagar, esperando mais 1000 milissegundos para acender novamente.
unsigned long tempo = 0; /*Variável utilizada para salvar o valor do millis*/ unsigned long auxiliar = 0; /*Variável auxiliar*/ unsigned long auxiliar_2 = 0; /*Variável auxiliar*/ void setup() { pinMode(13, OUTPUT); pinMode(12, OUTPUT); } void loop() { tempo = millis (); /*Atualização do valor dentro da variável*/ if (tempo - auxiliar >= 400){ digitalWrite (13, HIGH); } if (tempo - auxiliar >= 800){ digitalWrite (13, LOW); auxiliar = tempo; } if (tempo - auxiliar_2 >= 1000){ digitalWrite (12, HIGH); } if (tempo - auxiliar_2 >= 2000){ digitalWrite (12, LOW); auxiliar_2 = tempo; } }
Veja como montar o 2º exemplo:
Verifique abaixo o código em funcionamento:
Nessa situação, seria inviável o uso do delay(). Veja no diagrama abaixo a explicação:
Fluxograma de inviabilidade de utilização do delay() para ativação de dois LEDs alternadamente
Como exemplificado no fluxograma acima, é inviável a utilização do delay(). Ao manipular o acionamento dos LEDs com delay(), a máquina (seu Arduino), “travará” a leitura do código durante o período determinado por você. Assim, a utilização do millis() se torna mais vantajosa ao passo que você necessita de poucas linhas para realizar o controle e independe da necessidade de os valores dos intervalos de tempo de acionamento dos LEDs serem múltiplos. Além disso, é possível adicionar quantos LEDs você quiser no seu projeto, de forma a acioná-los simples e intuitivamente.
Vamos agora imprimir o valor de millis () no monitor serial a cada 5 segundos. Para isso, precisamos, iniciar a serial.
unsigned long tempo = 0; /*Variável utilizada para salvar o valor do millis*/ unsigned long auxiliar = 0; /*Variável auxiliar*/ void setup(){ Serial.begin (9600); /*Inicia a Serial*/ } void loop() { tempo = millis(); }
Assim como no exemplo anterior, precisamos definir a condição para que a ação seja executada. Nesse caso, se a diferença entre “tempo” e “auxiliar” for de 5000 milissegundos.
unsigned long tempo = 0; /*Variável utilizada para salvar o valor do millis*/ unsigned long auxiliar = 0; /*Variável auxiliar*/ void setup(){ Serial.begin (9600); /*Inicia a Serial*/ } void loop() { tempo = millis(); if (tempo - auxiliar >= 5000){ Serial.println (millis()); } }
Agora, para limitar que apenas a cada 5000 milissegundos o valor seja escrito no monitor serial, igualamos o valor de “auxiliar”, antes zero, ao valor de “tempo” no momento em que millis() foi escrito.
unsigned long tempo = 0; /*Variável utilizada para salvar o valor do millis*/ unsigned long auxiliar = 0; /*Variável auxiliar*/ void setup(){ Serial.begin (9600); /*Inicia a Serial*/ } void loop() { tempo = millis(); if (tempo - auxiliar >= 5000){ Serial.println (millis()); auxiliar = tempo; } }
Assim, seu código estará em pleno funcionamento, imprimindo o valor de millis() a cada 5 segundos.
Verifique abaixo o código em funcionamento:
A grande vantagem em se utilizar millis( ) se resume na possibilidade de não pausar o código por completo, e consequentemente continuar a leitura do algoritmo somente quando o tempo de espera acabasse (como ocorre com delay ( )). Isso abre um leque de possibilidades em seus projetos, e esperamos ter contribuído com isso através desse post.
|
A Eletrogate é uma loja virtual de componentes eletrônicos do Brasil e possui diversos produtos relacionados à Arduino, Automação, Robótica e Eletrônica em geral.
Conheça a Metodologia Eletrogate e Lecione um Curso de Robótica nas Escolas da sua Região!