delay() Função Arduino: Tight Loops e Código de Bloqueio
Deixou alguma vez ter feito um projecto Arudino e quer que algo ocorra num intervalo de tempo? Talvez a cada 3 segundos você queira que um servo se mova, ou talvez a cada 1 minuto você queira enviar uma atualização de status para um servidor web.
Como você faz isso? Existe alguma função que seja simples e direta que nos ajude nisso? Sim, existe! Vamos discutir a função de atraso, assim como a função millis(), no vídeo abaixo:
Esta é a parte 2 da nossa mini-série de funções millis(). A parte 1 nos ajuda a entender o que a função millis() faz, a parte 2 discute loops apertados e código de bloqueio, e a parte 3 discute quando a função millis() supera a função delay().
Tópicos nesta lição
- Laços apertados
- Código de bloqueio
- Uma receita antiga para música inspiradora
Millis() versus Delay()
Então você quer que algo ocorra em um intervalo definido e você está procurando por uma solução. Se a sua resposta é usar a função de atraso, bem, você está meio certo. Mas há outra maneira.
A opção cooler, snazzier é a função Arduino millis(). E quanto mais familiarizado você estiver em usar a função millis, para ajudá-lo a cronometrar eventos no seu código Arduino, mais fácil será incorporar outras partes no seu programa mais tarde.
Após você começar a usar a função millis(), você será mais feliz, mais alegre, e, caramba, as pessoas vão gostar de você.
![Arduino Millis() Função](https://i0.wp.com/www.programmingelectronics.com/wp-content/uploads/2019/03/people_like_you.png)
Laços apertados
Primeiro vamos discutir o conceito de um laço apertado. E quando dizemos um loop apertado, o que significa isso?
Vejamos um esboço do Arduino para uma demonstração de um loop apertado. Começando com o sketch mais básico, temos apenas duas funções: configuração void, e loop void. E como você deve saber, o void setup só funciona uma vez, e então ele passa o show para void loop.
![Arduino void setup loop](https://i0.wp.com/www.programmingelectronics.com/wp-content/uploads/2019/03/void_setup_loop_2.png)
Void loop então passa por todas as linhas de código que possam estar dentro do loop (dentro destes parênteses encaracolados).
Executa a primeira linha, depois executa a segunda, e depois a terceira, e assim sucessivamente, até chegar ao fundo. E depois volta para o topo.
Quão rápido executa o laço? Depende de qual placa Arduino você está usando, mas um Arduino Uno tem uma velocidade de relógio de 16 megahertz. Então isso significa que 16 milhões de instruções estão acontecendo a cada segundo no Arduino!
![Velocidade do relógio do Arduino](https://i0.wp.com/www.programmingelectronics.com/wp-content/uploads/2019/03/16-Mhz.png)
Cada linha de código não é necessariamente uma instrução. Na verdade, é mais provável que sejam múltiplas instruções. Mas mesmo assim, isso é relativamente rápido (seu processador de computador provavelmente está rodando na velocidade de Gigahertz… isso é bilhões).
Então você consideraria esse esboço vazio um loop apertado? Definitivamente, isso é tão rápido e apertado quanto você pode fazer um laço. Como não há nada dentro do laço para executar, o tempo que leva para passar pelo sketch é praticamente zero. Dito de outra forma, o intervalo desde o início do laço até ao fim é curto (portanto é rápido, ou “apertado”).
Vamos adicionar algumas linhas de código. Vamos iniciar a comunicação serial, e então imprimir algo na janela do monitor serial.
![Arduino tight loop serial communication](https://i0.wp.com/www.programmingelectronics.com/wp-content/uploads/2019/03/tight_loop.png)
Isto é um tight loop? Ou seja, do início ao fim do loop, isso leva muito tempo? Demora muito pouco tempo, então é um loop rápido e apertado.
No entanto, vale a pena notar que este loop não é tão apertado como o exemplo anterior. No exemplo anterior, nós não tínhamos código. Então estava apenas correndo através do loop. Agora que temos uma função aqui, impressão serial, vai levar (um pouco) de tempo para imprimir “Ice Ice Baby” para o monitor serial.
Mas este ainda é um loop bastante rápido. Então vamos adicionar um pouco mais de código. Vamos ter o programa para verificar se um botão está pressionado, e se estiver, teremos algo novo enviado para o monitor serial
![Arduino tight loop serial monitor com botão push](https://i0.wp.com/www.programmingelectronics.com/wp-content/uploads/2019/04/tight_loop_2.png)
Então declaramos um botão e usamos uma declaração if para verificar e ver se o botão foi pressionado. A voltagem no pino cinco é alta? Se sim, então imprimimos outra coisa na janela do monitor serial.
Isto é um loop apertado? Então, desde o início do loop, até ao fim do loop, é bastante rápido?
Sim, ainda é bastante rápido. Este é um laço bastante apertado. Nós temos quatro linhas de código. Estamos imprimindo para o monitor serial, e depois estamos fazendo uma verificação rápida para ver se um botão está sendo pressionado. E se estiver, nós imprimimos algo. Ainda apertado, ainda rápido.
Nextos vamos adicionar um atraso a este programa usando a função Arduino delay(). Você pode ver abaixo que adicionamos um atraso de mil milissegundos (1 segundo) ao loop.
![Arduino tight loop with delay](https://i0.wp.com/www.programmingelectronics.com/wp-content/uploads/2019/04/tight_loop_3.png)
Isto ainda é um loop apertado? O tempo, desde o início do laço até ao fim do laço, é muito tempo? Não, este não é definitivamente um laço apertado. O código começa rápido, nós fazemos a impressão em série, mas depois paramos ali mesmo na função de atraso.
O programa inteiro pára enquanto esperamos que este código de atraso termine.
Quando o Arduino chega a esta linha de código, é como ir à mercearia. Você entra na linha de 12 itens ou menos, mas depois o cara na sua frente puxa o seu livro de cheques e começa a passar um cheque. Sabes que vais estar lá por um minuto. É o mesmo negócio aqui.
>
![Quando alguém tira um cheque na linha expresso](https://i0.wp.com/www.programmingelectronics.com/wp-content/uploads/2019/04/checkout.png)
>
Então isto não é um loop apertado. O tempo desde o início do laço até o fim do laço é bastante significativo. Especialmente em comparação com os últimos programas de casal. A ordem de magnitude do tempo é enorme.
Agora o que tentamos demonstrar aqui é que toda essa idéia sobre loops apertados é relativa. Tudo depende da sua aplicação. Se você precisa verificar o status de um sensor a cada 10 milhões de segundos, então um programa que tem três linhas de código pode não ser apertado o suficiente, só depende.
Outro ponto a fazer é que nem todas as linhas de código levam a mesma quantidade de tempo para executar. Se você está chamando uma função que faz um monte de coisas, como impressão em série, por exemplo, então uma linha de código pode levar muito mais tempo que outras 10 linhas de código.
Então o aperto de um laço é uma idéia relativa.
![O aperto de um loop Arduino é relativo - Einstein](https://i0.wp.com/www.programmingelectronics.com/wp-content/uploads/2019/04/The-tightness-of-a-loop-is-relative.png)
Código de bloqueio
Quando um programa pára em algum ponto, e leva algum tempo para executar algum código, esse código pode ser chamado código de bloqueio. Este é um termo geral.
No nosso programa temos a função de atraso actuando como código de bloqueio. Nenhum do código após o atraso pode ser executado até que o atraso acabe, então ele está sendo bloqueado.
Código de bloqueio não é, no entanto, apenas quando usamos a função delay().
Deixamos pegar nosso programa e nos livrarmos do atraso, mas vamos adicionar um para loop. Nosso para loop irá imprimir números e texto para a porta serial.
![Arduino tight for loop](https://i0.wp.com/www.programmingelectronics.com/wp-content/uploads/2019/04/tight_loop_4.png)
Então por quanto tempo este loop funciona? Vai correr durante algum tempo porque tem de passar por 100 iterações antes de parar.
E o código depois disto para loop? Ele é capaz de rodar? Não, ele tem que esperar porque está sendo bloqueado pelo for loop.
Este for loop está aninhado dentro do loop principal. O for loop é um loop “apertado”? Antes de responder, vamos voltar a sublinhar como deve pensar: demora muito tempo a passar por isto para o loop, de cima para baixo?
Bem, não é bem assim. Só tem duas linhas de código. Então este é um loop bastante apertado.
Mas é um loop apertado que tem de passar por muitas iterações antes do programa conseguir chegar ao código abaixo dele. Então, mesmo um loop apertado, se for forçado a passar por várias iterações, pode bloquear nosso código.
Mais sobre a função delay()
Vamos falar um pouco mais sobre essa função delay. O que estabelecemos até agora?
Primeiro dizemos que a função delay diminui o aperto de um loop. Se você tiver um laço apertado e adicionar a função de atraso, vai levar mais tempo e torná-lo menos apertado. Ou seja, a quantidade de tempo que leva para chegar do início do laço até o fundo, vai aumentar com a função de atraso.
Sabemos também que a função de atraso bloqueia o código. Isto vai de mãos dadas com o que acabamos de dizer. Quando a função de atraso está a correr, está a bloquear outro código de correr enquanto está a atrasar.
Podemos pensar que esta função de atraso é uma total frouxidão! Nunca vai chegar a nada nos nossos projectos. Mas para muitos programas simples que nós escrevemos, a função de atraso funciona fantásticamente. É simples de usar, é muito fácil de soletrar e faz exatamente o que diz.
![A função de atraso do Arduino sendo um sofá batata](https://i0.wp.com/www.programmingelectronics.com/wp-content/uploads/2019/04/Is-the-delay-function-a-total-slacker__.png)
Por isso não devemos necessariamente ostracizar a função delay() da nossa caixa de ferramentas de programação. Devemos apenas reconhecer que é uma função de programação simples que pode funcionar em muitas instâncias.
Mas há um momento em que você começa a se deparar com problemas. Isso tem a ver com o efeito de bloqueio que a função delay tem em nosso programa.
Na próxima lição da série, parte 3, vamos identificar onde isso realmente se torna um problema. Você vai aprender quando faz sentido usar a função delay() em um programa, e quando for hora de mudar para usar a função millis().
Review
First, nós falamos sobre o aperto de um loop. Dissemos que o aperto de um laço é relativo. Depende do que sua aplicação é.
Segundo, falamos sobre o código de bloqueio, ou código que bloqueia. Essencialmente, é um termo genérico que podemos dar ao código que vai levar algum tempo para ser executado, e vai impedir outras partes do nosso programa de executar enquanto ele executa.
Esperamos ter gostado desta lição! Na próxima parte desta série, vamos continuar nossa jornada aprendendo como usar a função millis para criar eventos cronometrados e repetitivos em nosso código Arduino. Até a próxima!
![Arduino receita antiga para música inspiradora](https://programmingelectronics.com/wp-content/uploads/2019/04/ancient-recipe-gif.gif)
>