Software Timer - ESP8266
Software Timer
Em várias situações, é necessário de certa forma, a manipulação do tempo em micro controladores. O jeito mais fácil é pelas funções básicas (delay e derivados), porém, normalmente, estas funções travam o micro controlador, e com isto, você é incapaz de ler botões ou algo do tipo enquanto o delay não acabar. Isto além de gerar terríveis problemas nos mais variados projetos, não é uma pratica saudável. Neste tutorial, vamos aprender sobre o OS_TIMER do ESP8266, este timer é baseado no software do ESP8266 e o limite inferior é 1mS e máximo de ~2 horas. Este software timer não é aconselhado para projetos em que o tempo é crítico. Apesar de nossos testes darem certa confiança, por ele ser baseado em software, alguns fatores podem atrasa-lo em alguns mS, tome cuidado.
Demonstrando a diferença
Neste exemplo apenas para comparação do Software Timer, usaremos um exemplo que acende 3 LEDs a cada 1 segundo e enquanto isso, ficaremos enviando dados na Serial para mostrar o funcionamento do código. Antes de ir para o software timer, testem este código abaixo no ESP8266 e veja no Serial Monitor como é o recebimento de informações.
Neste código, estamos usando Delay para fazer o acionamento simples dos LEDs. Você perceberá que só irá aparecer mensagens a cada 4 Segundos.
long x;//Variavel para mostrar o desenvolvimento do codigo no Serial Monitor. void setup() { pinMode(D1, OUTPUT);//Define D1 como Saida. pinMode(D2, OUTPUT);//Define D2 como Saida. pinMode(D3, OUTPUT);//Define D3 como Saida. Serial.begin(9600);//Inicia a comunicaçao Serial para provar que o codigo nao trava. } void loop() { led();//Sub rotina para acender os LED`s. Serial.println(x++);//Mostra no serial monitor o desenvolvimento do codigo. } void led()//Sub rotina para acender os LED`s. { digitalWrite(D1, 1);//Acende o led 1. delay(1000);//Aguarda 1 segundo. digitalWrite(D2, 1);//Acende o led 2. delay(1000);//Aguarda 1 segundo. digitalWrite(D3, 1);//Acende o led 3. delay(1000);//Aguarda 1 segundo. digitalWrite(D1, 0);//- digitalWrite(D2, 0);//- digitalWrite(D3, 0);//-Apaga os 3 leds. delay(1000);//Aguarda 1 segundo. }
Após ver que o ESP só pula para a linha debaixo da função led() a cada 4 segundos, percebe-se que o ESP fica travado durante 4 segundos apenas para acender os LEDs, inutilizando totalmente o seu uso para outras coisas.
Agora chega de papo e vamos ao Software Timer.
Normalmente, na maioria dos casos, as funções de delay travam o código até que o delay se acabe. Ao usar delay(60000), o micro controlador ficará travado por 1 Minuto nesta linha até que o tempo acabe e não fara mais nada. Se desejarmos acender um LED a cada 30 segundos, isto irá gerar muitos problemas usando delay, então, usaremos os Timer’s. O Timer gera uma interrupção no sistema a cada intervalo de tempo e voltara a fazer a sua rotina padrão após terminar suas instruções.
Lembre-se, A rotina de um timer (Interrupção) não pode conter comandos de Delay, Serial e vários outros. A rotina do ISR deve ser a mais breve possível e normalmente usamos flag’s armazenadas na RAM para agilizar o processo e evitar erros internos.
Mãos à obra
Componentes necessários
- 1 – ESP8266 (Usaremos o NodeMCU).
- 3 – LED's.
- 3 - Resistores de 220 Ω.
- Fios Jumpers.
Montando o projeto
Veja como ficou nossa montagem:
Código do projeto
#include <user_interface.h>;//Biblioteca necessaria para acessar os Timer`s. os_timer_t tmr0;//Cria o Timer. Maximo de 7 Timer's. volatile byte status;//Variavel armazenada na RAM para Status do LED. long x;//Variavel para mostrar o funcionamento do Codigo. void setup() { os_timer_setfn(&tmr0, led, NULL); //Indica ao Timer qual sera sua Sub rotina. os_timer_arm(&tmr0, 1000, true); //Inidica ao Timer seu Tempo em mS e se sera repetido ou apenas uma vez (loop = true) //Neste caso, queremos que o processo seja repetido, entao usaremos TRUE. pinMode(D1, OUTPUT);//Define D1 como Saida. pinMode(D2, OUTPUT);//Define D2 como Saida. pinMode(D3, OUTPUT);//Define D3 como Saida. Serial.begin(9600);//Inicia a comunicaçao Serial. } void loop() { leitura();//Sub rotina para processar os LED`s. //O codigo irá funcionar normalmente sem que haja delays e acendendo os LED`s no intervalo definido. //Para demonstraçao, abra o Serial monitor e voce vera que o codigo continua normalmente. Serial.println(x++);//Print para provar que o codigo nao trava. Abra o Serial monitor e veja //que o codigo continua rodando enquanto os LED`s piscam a cada 1 Segundo. } void leitura()//Sub rotina para processar os LED`s. { switch (status) { case(1)://Caso status seja 1, acenda o led 1. digitalWrite(D1, 1); break; case(2)://Caso status seja 2, acenda o led 2. digitalWrite(D2, 1); break; case(3)://Caso status seja 3, acenda o led 3. digitalWrite(D3, 1); break; case(4)://Caso status seja 4, Apague os 3 LED`s. digitalWrite(D1, 0); digitalWrite(D2, 0); digitalWrite(D3, 0); break; } } void led(void*z)//Sub rotina ISR do Timer sera acessada a cada 1 Segundo e mudara o status do LED. { if (status == 4)//Verifica se o maximo foi alcançado para resetar a contagem. { status = 0; } status++; }
Entendendo a fundo
Hardware
As ligações são simples, apenas sendo necessário ligar o pino de cada LED em sua correspondente porta, não esquecendo o uso de resistores para limitar a corrente/tensão e também não queimar o LED. O outro pino do LED no GND. Este é o básico para um LED funcionar.
Software
-Função os_timer_setfn()
os_timer_setfn(&tmr0, led, NULL);
Esta função atribui uma função sua à rotina do Timer. Neste caso, definimos a nossa função led() ao timer tmr0, que criamos anteriormente.
-Função os_timer_arm()
os_timer_arm(&tmr0, 1000, true);
Com esta outra, é definido o tempo do timer e também se irá se repetir (loop). Neste caso, definimos ao timer tmr0, que entre na função anteriormente atribuída, a cada 1000mS. Se você não precisa que isso seja repetido, troque true por false, desativando o loop.
Finalizando
Comparando os dois códigos, podemos perceber claramente a diferença entre fazer tarefas com um Timer ou Delay. Enquanto o primeiro código só mostra a mensagem a cada 4 Segundos, o segundo mostra a mensagem diversas vezes ao mesmo tempo que gerencia os LEDs. Você pode usar isso em vários projetos em que é preciso fazer tarefas em tempos definidos, sem travar o resto do sistema com Delay. Dúvidas? Sugestões? Críticas? Comente abaixo!