Executar uma função sem atrapalhar o funcionamento de outra é algo extremamente necessário em sistemas que começam a ter uma leve complexidade. Ainda mais no caso do ESP8266 que é um microcontrolador poderoso que pode fazer muitas coisas. Portanto, vamos aprender a executar duas funções “ao mesmo tempo” (sem uma interferir na outra).

Na aula anterior, aprendemos a ler os pinos digitais e o analógico do ESP8266.

Informações básicas

No post que expliquei sobre como executar duas coisas ao mesmo tempo no Arduino, comentei sobre a importância desse assunto. Para não ser repetitivo, vou apenas falar a importância aplicado ao caso do esp8266.

Como o esp se conecta à internet, podem existir inúmeros sistemas que vão precisar dessa técnica. Por exemplo: imagine que o esp está controlando um display que atualiza o horário a cada minuto e também verifica constantemente a temperatura pela internet e mostra no display. Essas duas funções, de atualizar a hora e a temperatura, podem conflitar uma com a outra, já que criar um delay de 1 minuto para atualizar o horário iria congelar o programa, impossibilitando o código de verificar a temperatura na internet.

Sendo assim, nós precisamos de uma forma de executar rotinas a cada intervalo de tempo definido sem depender de delays. O termo “executar ao mesmo tempo” pode não representar exatamente isso, mas ele facilita o entendimento da ideia.

Usando a linguagem Lua igual fiz no curso antigo, tinha um módulo que criava funções pra facilitar essa implementação. Mas, no caso de usar a IDE do Arduino tem um jeito fácil também que é igual ao que ensinei no post mencionado no início deste tópico. Isto é, usar a temporização do microcontrolador pela função millis()

ESP8266 executando duas coisas ao mesmo tempo

Vou mostrar como implementar a temporização utilizando o mesmo exemplo do post do Arduino. Que no caso é ficar comutando dois LEDs , cada um com um tempo de comutação diferente.

Circuito

esp8266 comutando LEDs

É só ligar o negativo dos LEDs em um resistor, e a outra ponta do resistor no GND do NodeMcu. O pino positivo de cada LED deve ser ligado em uma porta digital. No meu caso, liguei o verde no pino D0 e o azul no pino D1.

Assim como antes:

  • O LED verde tem que comutar de estado a cada 1 segundo (se estava aceso irá apagar e vice-versa);
  • O LED azul tem que comutar de estado a cada 3 segundos (se estava aceso irá apagar e vice-versa).

Lógica a ser usada

Conforme mencionei no início do post, a execução de duas rotinas que funcionam em tempos diferentes sem o uso de delays será feita pelo comando millis(). Este comando retorna o tempo, em milissegundos, desde que o esp8266 foi energizado. Isto é, exatamente 5 segundos após ser energizado, essa função retornará o valor 5000. Se tiver passado um pouco mais de tempo, mas não a ponto de chegar em 6 segundos, ela vai retornar um valor entre 5000 e 6000.

Podemos usar isso para marcar o tempo do código da seguinte forma: quando executo uma função, eu armazeno o valor do millis() em uma variável chamada tempoA. Após isso, se eu subtrair o valor de millis() pelo valor de tempoA, terei a informação de quanto tempo se passou desde a última execução da função. Portanto, posso usar essa informação para decidir se a função deve ser executada ou não.

diferença entre os tempos

Usando a imagem acima como referência, a verificação do tempo entre execuções seria:

\Delta t = millis() – tempo_A

E, se Δt for maior que 3 segundos (exemplo), a função será executada.

Código completo

O código abaixo segue a lógica citada acima. Leia os comentários para entender.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// Pinos dos LEDs
#define LED_1  D0
#define LED_2  D1

// Intervalos das rotinas (em milissegundos)
#define INTERVALO_TEMPO_1   1000
#define INTERVALO_TEMPO_2   3000

unsigned long tim_1 = 0;
unsigned long tim_2 = 0;

void setup()
{
  // Configura pinos como saída
  pinMode(LED_1, OUTPUT);
  pinMode(LED_2, OUTPUT);
}

void loop()
{
  // Rotina 1 (executa a cada 1 segundos)
  if((millis() - tim_1) > INTERVALO_TEMPO_1)
  {
    // Registra o tempo para a próxima comparação
    tim_1 = millis();

    // Executa a rotina 1
    digitalWrite(LED_1, !digitalRead(LED_1));
  }

  // Rotina 2 (executa a cada 3 segundos)
  if((millis() - tim_2) > INTERVALO_TEMPO_2)
  {
    // Registra o tempo para a próxima comparação
    tim_2 = millis();

    // Executa a rotina 2
    digitalWrite(LED_2, !digitalRead(LED_2));
  }
}

Criando mais rotinas

Para permitir ao código executar mais de 2 rotinas “ao mesmo tempo”, basta criar uma variável de temporização e um if igual ao do código acima para cada caso.

Como criar um Web Server com ESP8266 – Aula 6 – EA