Muito provavelmente, em algum momento, você irá precisar fazer duas coisas ao mesmo tempo. Porém, surge um obstáculo que te impede de fazer isso. Talvez uma função delay atrapalhando? Nesta aula, vamos aprender por que executar duas coisas “ao mesmo” tempo e como fazer isso.
Na aula anterior, vimos sobre as bibliotecas do Arduino.
O que e por que?
A programação é algo sequencial, isto é, cada comando é executado na sequência de outro. Entretanto, há momentos em que a lógica de uma função atrapalha na lógica de outra. E isto inviabiliza que as duas funções sejam executadas “juntas”. Juntas, nesse caso, se refere a intervalos de tempo muito próximos e não exatamente no mesmo microssegundo. Veja o exemplo abaixo para entender melhor.
Você está usando um display e quer desenhar um coração pulsando no canto da tela, mas, ao mesmo tempo, você precisa que o programa verifique se algum botão foi apertado. Considere que seu coração pulsa de 1 em 1 segundo ou em um tempo maior que centenas de milissegundos. Para que o seu coração pulse, você irá utilizar a função delay, que basicamente “congela” o seu programa pelo tempo que você determinar.
Com isso, se o seu programa ficar “congelado”, não será possível conferir se algum botão foi pressionado. A não ser que você aperte o botão, coincidentemente, toda vez que o programa sair do delay. Portanto, você necessita de uma solução para fazer seu coração pulsar de 1 em 1 segundo e também precisa que o programa verifique constantemente (100% do tempo) se algum botão foi apertado.
Sendo assim, vamos ver a solução no tópico abaixo.
Como fazer
Existem diferentes formas de se chegar ao resultado, mas essencialmente todas são parecidas. Porém, vou ensinar o método genérico, que pode ser praticamente copiado e colado para quase toda situação.
Considerações
Antes de ver o método, é preciso entender alguns comandos importantes. Existe uma função chamada millis() que retorna o tempo, em milissegundos, desde que o Arduino começou a rodar o programa. Esse tempo é zerado toda vez que o Arduino é desligado ou resetado. E ele é como se fosse um relógio, que, quando chamado, nos diz as “horas”.
É importante mencionar que esse valor tem o objetivo de contar muito tempo, então ele retorna um valor do tipo unsigned long. Isto quer dizer que, é uma variável que não usa um bit para guardar valores negativos (unsigned) e que usa mais bytes para armazenar dados (long).
Portanto, ela é capaz de guardar valores na seguinte faixa [0, 4,294,967,295]. E se você fizer as contas, é possível perceber que o Arduino irá contar até cerca de 50 dias. Depois dos 50 dias, o valor volta para zero e o ciclo continua.
Agora, para ajudar na explicação do método, considere o circuito abaixo:
Com base nas aulas anteriores, você já deveria saber montar o esquema. No circuito acima, nós desejamos o seguinte funcionamento:
- O LED azul tem que comutar de estado a cada 3 segundos (se estava aceso irá apagar e vice-versa)
- O LED verde tem que comutar de estado a cada 1 segundo (se estava aceso irá apagar e vice-versa)
Os dois não podem interferir um com o outro.
Método genérico
Programa sem a solução
Primeiro, observe e tente entender o programa abaixo (leia os comentários):
1 | // Nome das saidas //Chamada das funçoes void setup(){ void loop(){ void acendeA(){ // Funçao que controla o acendimento do led Azul void acendeV(){ // Funçao que controla o acendimento do led Verde |
Se você observar, verá que o delay de uma função atrapalha o funcionamento da outra. Pois, quando o LED azul acende, ele entra no delay e congela o programa. E, assim, o LED verde não faz nada até que se passem 3 segundos.
Solução
Vou explicar a lógica da resolução do problema para apenas um dos LEDs, pois o outro será a mesma coisa. Portanto, faremos o seguinte: O LED terá uma variável tempo assimilada a ele, e ela será responsável por armazenar a hora que o LED foi comutado.
unsigned long tempoA=0; //Variavel para armazenar o tempo do LED AZUL
E para guardar o tempo nela é só fazer:
tempoA=millis();
Com isso, criaremos uma função (chamada “espera”) que verificará se o tempo gasto, desde de que o LED foi comutado, é maior do que 3 segundos. Isso traduzido, é o relógio do Arduino (função millis()) menos a hora em que o LED foi comutado (variável tempoA). Essa diferença Δt está ilustrada abaixo:
Então basta testar se millis()-tempoA>3000 (3segundos em milissegundos é 3000). Porém, ainda falta um elemento, que é uma variavel (booleana) para informar se está na hora ou não de comutar o LED.
bool comutarA = false;
Vou chama-la de comutarA e ela será acionada toda vez que millis()-tempoA for maior que 3000. E claro, nosso LED só irá comutar se ela for TRUE. Sendo assim, nossa função “acenderA” fica assim:
1 | void acendeA(){ |
Observe que comutarA foi setada para falso, para que a rotina seja executada apenas uma vez. E, quem seta ela para verdadeiro é nossa função “espera”. Agora, em nossa função espera, é só verificar se Δt é maior que 3000. Além disso, a nossa função só fará essa verificação se a variável “comutarA” for falsa. Isso porque, o programa deve esperar 3 segundos APÓS o LED comutar, que é quando “comutarA” é falsa. Portanto:
1 | void espera(){ |
Código Final
Por fim, basta colocar nossa função espera no void loop também. E está pronto nosso código. Veja o código final abaixo e leia os comentários para entender melhor.
1 | // Nome das saidas void acendeA();// Funçao que controla o acendimento do led Azul unsigned long tempoA=0; // Variavel para armazenar o tempo do LED AZUL bool comutarA = false; void
setup(){ void loop(){ void acendeA(){ void acendeV(){ void espera(){ |
Agora é só usar o exemplo dado como base para montar seu próprio projeto e conseguir resolver esse problema que dá dor de cabeça em muitos.
Arduino – Como usar o microcontrolador fora da plaquinha – Aula 10 – AI