Informações importantes
Interrupções
As interrupções são bem úteis para otimizar a programação e reduzir certar verificações desnecessárias do código. Na aula 11 do curso do Arduino, expliquei em detalhes sobre as interrupções e suas vantagens. Portanto, recomendo a leitura do post.
Entretanto, explicando resumidamente seu funcionamento, temos que: a interrupção é um evento que ocorre no microcontrolador quando certa condição é cumprida. Esse evento é basicamente uma interrupção, de fato, no programa principal que passa para uma função secundária, que é a função de interrupção. O motivo da interrupção pode ser mais de um, mas o mais comum é ela ocorrer por causa de uma mudança no estado de um pino digital.
Ou seja, se um pino digital passou de nível alto para baixo, por exemplo, o programa é interrompido praticamente imediatamente e a função de interrupção é executada.
Modo sleep
O modo sleep é extremamente necessário em aplicações onde o microcontrolador fica um tempo ocioso sem executar nada importante. Novamente, na aula 12 do curso do Arduino, expliquei em detalhes sobre o modo sleep e suas finalidades. Portanto, recomendo a leitura do post.
De qualquer forma, explicando resumidamente seu funcionamento: o modo sleep é um estado do microcontrolador em que ele “hiberna” e deixa de executar algumas de suas rotinas internas. Logo, o microcontrolador deixa de consumir tanta potência quanto o normal e há uma redução no gasto de energia.
Ou seja, podemos utilizar o modo sleep para economizar a energia de baterias que alimentam um sistema.
Interrupções
Comandos
1 2 3 | gpio.mode(pino, gpio.INT) -- Sem pull-up gpio.mode(pino, gpio.INT, gpio.PULLUP) -- Com pull-up interno |
1 | gpio.trig(pino, tipo, função_associada) |
Sendo os parâmetros:
- pino: pino responsável pela interrupção externa. O pino 0 não pode receber interrupções.
- tipo: tipo da interrupção. Dentre os tipos, temos:
- “up”: A interrupção ocorre em uma borda de subida.
- “down”: A interrupção ocorre em uma borda de descida.
- “both”: A interrupção ocorre em ambas as bordas de subida e descida.
- “low”: A interrupção ocorre em nível baixo.
- “high”: A interrupção ocorre em nível alto.
- função_associada: função que será executada quando a interrupção ocorrer.
Portanto, é preciso configurar o pino como interrupção, criar uma função para a interrupção e associar a interrupção à função criada com o comando acima. Agora, vamos a um exemplo de como fazer isso.
Exemplo
Circuito
Programação
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | -- Cria variáveis associadas aos pinos pino_int = 1 led1 = 2 gpio.mode(pino_int, gpio.INT, gpio.PULLUP) -- Define o pino de interrupção como uma interrupção e ativa o pull-up gpio.mode(led1, gpio.OUTPUT) -- Define o pino do led como saída -- Cria a função associada à interrupção function interrupcao() gpio.write(led1, 1-gpio.read(led1)) -- Comuta o estado do LED tmr.delay(1000 * 100) -- Delay de 100ms para gerar atraso end -- Cria a interrupção gpio.trig(pino_int, "down", interrupcao) |
Modo sleep
Comandos
Para colocar o NodeMcu em modo sleep, existem dois comandos: node.sleep(), que é para o modo “light sleep” (sono leve); e node.dsleep(), que é para o modo “deep sleep” (sono profundo). A diferença entre os dois é que, o primeiro pode ser configurado para sair do sleep a partir de uma interrupção, enquanto o segundo só sai do sleep depois de um tempo definido. Além disso, teoricamente, o segundo comando abaixa mais o consumo de corrente do que o primeiro.
Os comandos são:
1ª opção
1 | node.sleep(pino, tipo_int, funçao_wifi, preservar_modo) |
Os parâmetros deste primeiro comando são:
- pino: pino associado à interrupção.
- tipo_int: tipo de interrupção, podendo ser:
- node.INT_UP: A interrupção ocorre em uma borda de subida.
- node.INT_DOWN: A interrupção ocorre em uma borda de descida.
- node.INT_BOTH: A interrupção ocorre em ambas as bordas de subida e descida.
- node.INT_LOW: A interrupção ocorre em nível baixo.
- node.INT_HIGH: A interrupção ocorre em nível alto.
- função_wifi: função para executar quando o WiFi sai da suspensão.
- Esta função é opcional e pode ser desabilitada e ignorada com o próximo parâmetro.
- preservar_modo: preserva o modo do WiFi definido atualmente. Se for ‘false’ descarta o modo definido pelo WiFi. Se for ‘true’, apenas mantem o estado antigo.
2ª opção
1 | node.dsleep(tempo, opção, instante) |
Os parâmetros deste segundo comando são:
- tempo: tempo em microssegundos que o microcontrolador ficará em modo sleep.
- O tempo máximo pode ser obtido com o comando node.dsleepMax(). Este tempo máximo é dependente da temperatura ambiente: quanto maior a temperatura, maior é o tempo máximo.
- opção: muda a forma como ficará a corrente depois que o microcontrolador “acordar”. Os principais valores estão listados abaixo:
- Instante: define se o microcontrolador entrará imediatamente em modo sleep caso o valor seja numérico diferente de zero. Se for ‘nil’ ou zero, o sleep esperará o módulo Wi-Fi desligar.
Depois que o NodeMcu “acordar” depois do comando acima ser utilizado, ele é resetado. E, para o comando funcionar, o pino RST e o pino D0 (GPIO16) devem estar interligados. Entretanto, quando os dois estão interligados o botão de reset para de funcionar, então fique atento.
Considerações
Portanto, é preciso apenas usar um dos dois comandos acima de acordo com a forma como você deseja que o NodeMcu “acorde”.
Observação importante: não consegui fazer o primeiro comando funcionar, pois é necessário criar uma build do firmware com certos parâmetros habilitados. Esse processo é bem trabalhoso, mas, quem tiver interesse, é só usar este link para baixar os acessórios necessários para criar a build customizada. Na build customizada, você deve alterar o arquivo “app/include/user_config.h” descomentando as linhas que tiverem definindo os parâmetros: “PMSLEEP_ENABLE” e “ENABLE_TIMER_SUSPEND”.
Exemplo
Como o primeiro comando exige um processo complicado para ser habilitado, vou mostrar um exemplo com o comando dsleep. A lógica do programa será acender um LED ligado ao pino 1 por dois segundos e deixá-lo apagado por 1 segundo. Após isto, o NodeMcu entrará no modo de deep sleep.
Programação
Não pretendo explicar o código, pois os comentários do código devem ser suficientes para entender o procedimento. No caso do comando node.dsleep(), só configurei o primeiro parâmetro, pois os outros dois não são de interesse.
1 2 3 4 5 6 7 8 9 10 | -- Cria variável associada ao pino do LED led1 = 1 gpio.mode(led1, gpio.OUTPUT) -- Define o pino do led como saída gpio.write(led1, 1) -- Liga o LED tmr.delay(1000 * 2000) -- Delay de 2 s gpio.write(led1, 0) -- Desliga o LED tmr.delay(1000 * 1000) -- Delay de 1 s node.dsleep(5000000) -- Entra no modo sleep por 5 segundos |
Obs.: Não recomendo colocar o programa acima como o init.lua (código que inicia automaticamente toda vez), pois o NodeMcu pode ficar travado.
Resultados
Depois de fazer upload do código, alimentei o NodeMcu com uma fonte externa e medi a corrente que passava por ele durante a execução do código. Os resultados obtidos podem ser vistos na tabela abaixo:
Modo | Corrente |
---|---|
Normal | 84.6mA |
Sleep | 10.06mA |
As medições acima foram sem o LED (na hora que ele estava desligado). Portanto, foi percebido uma redução de cerca de 88% do valor total da corrente. Ou seja, poderia aumentar a duração de uma bateria em até 8 vezes.
Gostei da explanação de fácil entendimento e bastante útil. Parabéns.
Muito obrigado, é gratificante saber que estou no caminho certo!