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
É 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.
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