Tomada inteligente: Modificando um filtro de linha para controlá-lo por um Arduino ou Attiny85

Um pequeno circuito montado dentro de uma régua de tomadas nunca esquece de desligar aqueles aparelhos que ficavam em stand-by o ano inteiro sem necessidade.

Nas atuais salas de TV conectadas, frequentemente há vários aparelhos que ficam ligados o dia inteiro (o mês inteiro, o ano inteiro...), em stand-by para poderem responder a controle remoto ou porque monitoram alguma conexão: TV, DVD, decodificador, DVR, videogame, etc.

Em vários deles o consumo de energia em stand-by é eficiente o suficiente para tornar desnecessárias as medidas adicionais, mas outros (decodificador da Net que fica permanentemente quente, estou olhando para você!) são verdadeiros perdulários de energia.

Como parte do meu aprendizado, e para colocar um freio nesse consumo inútil sem reduzir muito a comodidade, adaptei um filtro de linha para dotá-lo de temporização inteligente, programada usando a IDE do Arduino, e controlada usando um botão e leds que eu adaptei em um cantinho dela.

Quando ligada, ela mantém os "quentinhos" em funcionamento normal por 4h. Quando faltam 10 minutos para esse tempo acabar, um led amarelo começa a piscar, e eu posso apertar o botão que reinicia a contagem de tempo, se quiser uma prorrogação. Senão, ao completar 4h, a tomada corta totalmente a energia do "quentinho" (e de tudo o mais que estiver ligado a ela), e só voltará a deixar passar energia quando eu pressionar o botão (ou, idealmente, quando eu voltar a ligá-la após também cortar a alimentação dela).

O mesmo circuito básico poderia ser usado com outras formas de controle além da temporização: detecção de corrente, controle remoto, controle via Internet, via voz, via palmas, por detecção de presença, por tag RFID, etc.

O mais interessante: o uso dessa tomada vem me disciplinando, e agora eu mesmo lembro de ir lá e desligar fisicamente os aparelhos, algo que está sempre ao alcance mas frequentemente é bloqueado da minha mente pela comodidade do controle remoto.

Como funciona

Do ponto de vista lógico, o projeto é bem simples: há um transistor controlando o circuito de um relé, um diodo para proteger contra o retorno de corrente do relé o restante do circuito, um botão, e 3 leds controlados por pinos específicos (2 exclusivos para isso, outro no mesmo pino que controla o transistor), mais os resistores associados ao transistor e aos leds.

Entretanto, como combina em um espaço confinado o circuito DC de controle e o circuito AC da tomada, com todos os riscos associados a trabalhar com AC (choque, incêndio, dano aos equipamentos conectados, à rede elétrica, etc.), optei por me restringir aos elementos essenciais do circuito de controle, deixando aos interessados a busca para uma solução da montagem física mais adequada ao seu caso.

Vamos, portanto, ao circuito, em um esquemático simplificado:

No lado esquerdo temos 6 pinos do ATtiny85 que eu usei (poderia ser um Arduino): VCC, o terra e 4 pinos digitais, sendo que o 1, mais ao alto controla o transistor (e um led associado), o 4 é de entrada e lê um botão, e os outros 2 (0 e 3) controlam leds indicadores de estado, sendo um para indicar que o tempo está quase acabando (para o usuário apertar o botão que reinicia a contagem, se desejar) e o outro indica que o relé já foi desligado, para lembrar o usuário de desligar fisicamente o conjunto, e assim deixar de gastar mais um pouquinho de corrente.

No lado direito, temos os 2 fios de uma tomada AC (de 220V, no meu caso).

E a parte mais complexa é a seção do circuito que une os 2 lados. Os componentes envolvidos são R1–Q1–D1–RY1; da esquerda para a direita, o pino 1 controla o transistor NPN Q1 (usei um 2N2222, com o resistor de ~1KΩ R1 no caminho), que permite ou não que o lado de controle do relé RY1 (que é o bloco roxo no centro do diagrama) tenha acesso ao terra do ATtiny85.

Quando o pino 1 está em HIGH, o transistor permite o acesso ao terra, e o relé fecha o circuito de acionamento da carga ou tomada, representada no esquema por uma lâmpada.

Como já vimos no artigo Controlando um relé no Arduino com segurança, o papel do diodo (usei um IN4007) é evitar que o retorno de corrente que o relé induz ao ser desativado cause danos ao transistor.

A montagem física

Eu fiz a montagem do circuito em uma pequena placa ilhada de 250 furos, sem trilhas, previamente medida para ter certeza de que caberia dentro da régua de tomadas escolhida.

Encaixar e conectar o meu circuito dentro de uma régua de tomadas que não foi feita para recebê-lo foi uma tarefa que exigiu muita atenção, pois se alguma parte condutora ficar exposta e mais tarde encostar no circuito da placa, os resultados serão imprevisíveis mas certamente perigosos. Da mesma forma, a estrutura da régua não pode ser danificada, nem deve haver pontas soltas de plástico que possam interferir termicamente com o resultado, entre outros riscos que busquei evitar.

Na foto acima é possível ver que o circuito original da régua tem longos trechos expostos sem isolamento. Procurei fixá-los o melhor possível, ao mesmo tempo em que reduzi ao mínimo os trechos expostos do meu circuito, e testei sua flexibilidade para garantir que nenhum deles poderia se mover até alcançar o circuito original, para não dar chance para o azar.

Com uma furadeira comum, broca para metal/plástico e bastante cuidado, eu furei o corpo da régua de tomadas para instalar suporte para led e um pequeno botão. O local dos furos precisa ser muito bem escolhido, para que os contatos dos botões e dos leds fiquem perto o suficiente do circuito de controle sem prejudicar o posicionamento deste, mas longe de qualquer contato original da tomada.

Quanto aos fios AC da régua, 2 deles (o neutro e o terra, no meu caso) permaneceram inalterados, e o terceiro foi cortado, sendo um dos lados conectado (em uma versão anterior eu conectei por um borne KRE, na versão atual eu soldei) ao pino entrada de AC (“IN”) do relé, e o outro conectado ao pino (designado como “NO”, de normally open, na datasheet - veja diagrama abaixo, referente ao modelo que eu usei) de saída AC do relé, também por meio de um borne KRE.

Você deve escolher um relé que seja acionável pela tensão do circuito do seu Arduino (5V, normalmente), ou de um circuito intermediário que você projete, e que esteja apto a acionar uma tensão compatível e uma carga superior à do equipamento que deseja alimentar. Sem exceções. Nem por 1 minutinho. Nem só pra testar.

Para completar, fiz sair pela mesma passagem do cabo elétrico da régua os 2 fios de alimentação DC do ATtiny85, sendo um conectado ao pino VCC e o outro ao GND. No meu caso, há uma porta USB (permanentemente disponível) com tensão apropriada (o ATtiny85 funciona entre 1,8V e 5,5V), próximo ao local de instalação, portanto liguei esses 2 fios a um conector que permite plugá-los nessa porta USB.

O programa

A lógica do programa é simples, mas tem alguns detalhes de implementação que merecem atenção. Como de hábito, segue o código completo, em cores para facilitar a explicação que vem logo depois:

#include <Narcoleptic.h>

const int pinoRele=1;
const int pinoLedFinal=0;
const int pinoLedDesligue=3;
const int pinoBotaoReset=4;

unsigned long tInicio=millis();
boolean alertaAtivo=false;
boolean avisoDesligue=false;
byte contaLoop=0;
unsigned long segundosDuracao=4*60*60;      // desliga em 4h
unsigned long segundosAlerta=4*60*60-10*60; // comeca a piscar o 
                                            // alerta em 4h-10min


void setup() {
  pinMode(pinoRele, OUTPUT);
  digitalWrite(pinoRele,HIGH);
  pinMode(pinoLedFinal, OUTPUT);
  pinMode(pinoLedDesligue, OUTPUT);
  pinMode(pinoBotaoReset, INPUT_PULLUP);
  digitalWrite(pinoLedFinal,LOW);
  digitalWrite(pinoLedDesligue,LOW);
}

unsigned long releUptime() {
  // retorna o tempo desde a ativacao, em segundos
  return (millis()-tInicio)/1000;
}  

void desligaRele() {
  digitalWrite(pinoRele,LOW);
}

void myDelay100() {
  // se o rele ja estiver desativado, pausa por 
  // mais tempo e em modo de baixa energia 
  if (digitalRead(pinoRele)!=HIGH) {
    Narcoleptic.delay(250);
  } else {  
    // quando o rele ainda esta ativo, usa o delay nativo, 
    // para nao prejudicar a contagem de tempo pelo millis()
    delay(100);
  }
}


void loop() {
  myDelay100();
  contaLoop++;
  if ((releUptime() > segundosAlerta) & (digitalRead(pinoRele)==HIGH) & (!alertaAtivo)) {
    alertaAtivo=true;    
  }  
  if ((releUptime() > segundosDuracao) & (digitalRead(pinoRele)==HIGH)) {
    desligaRele();
    alertaAtivo=false; 
    avisoDesligue=true;   
  }  
  if (alertaAtivo) {
    digitalWrite(pinoLedFinal,(contaLoop % 4 == 0));
  }  else digitalWrite(pinoLedFinal,LOW);
  if (avisoDesligue) {
    digitalWrite(pinoLedDesligue,(contaLoop % 10 == 0));
  }  else {
    digitalWrite(pinoLedDesligue,LOW);
  }  
  if (digitalRead(pinoBotaoReset)==LOW) {
    tInicio=millis();
    alertaAtivo=false;
    avisoDesligue=false;
    digitalWrite(pinoRele,HIGH);
  }  
}

Começando com o trecho em cor de rosa, que traz definições básicas, tais como a inclusão da biblioteca Narcoleptic, os números dos pinos dos leds, do controle do relé e do botão, o tempo até que o relé seja desligado, e o momento a partir do qual o led de alerta de desligamento deve começar a piscar.

Já falamos sobre a biblioteca Narcoleptic no artigo “Arduino e bateria: providências simples para reduzir o consumo”. Ela oferece uma versão alternativa da função delay(), que coloca o microcontrolador em um modo de baixo consumo de energia enquanto dura a sua pausa.

Não há problema em inicializar variáveis a partir de operações matemáticas e resultados de funções.

O trecho em cor de rosa faz uso de 2 formas de inicialização de variáveis que eu creio não ter comentado em exemplos anteriores. A primeira delas é a da variável tInicio, que é inicializada com o valor de uma função (no caso, a millis(), que conta o tempo desde o último reset). A outra é a das variáveis segundosDuracao e segundosAlerta, inicializadas a partir de operações aritméticas com constantes numéricas. No primeiro caso, a variável será inicializada com o valor da função a cada vez que o programa iniciar; no segundo caso, como a operação matemática tem valor constante, o compilador é inteligente o suficiente para realizar a operação apenas uma vez, e já registrar seu resultado no programa executável gerado.

O trecho verde é a função setup(), que roda uma vez após o boot, e faz o de sempre: define modos para os pinos, e seus estados iniciais. Note que o pino de controle do relé é inicializado como HIGH (ou seja, com o relé permitindo a passagem de corrente).

As duas funções em cinza não têm complexidade nenhuma, mas a função myDelay100(), em vermelho, merece uma olhada: note que ela verifica se o relé já foi desativado e, se for este o caso, chama a versão do delay() da biblioteca Narcoleptic por 250ms. Caso contrário, ou seja, se o relé ainda estiver HIGH, ela chama o delay tradicional, por 100ms.

Usamos uma versão da função delay quando é relevante preservar a contagem de tempo interna do Arduino, e outra versão, mais econômica, quando a contagem do tempo é irrelevante.

A função delay() econômica que vem na biblioteca Narcoleptic coloca o Arduino (ou ATtiny) em um modo de economia de energia, mas interfere na contagem de tempo interna. Assim, usá-la enquanto ainda estivermos contabilizando o prazo no qual o relé pode ficar ligado exigiria cuidados especiais, desnecessários quando usamos o delay() tradicional – e isso explica a escolha acima.

Vamos agora ao loop(), que é o trecho que o Arduino executa repetidamente a partir do fim da função setup().

Note que toda rodada do loop() começa com uma chamada à função myDelay100(), que já vimos acima, e um incremento na variável contaLoop. A partir daí, basicamente verificamos 5 condições diferentes:

  1. em rosa-choque: se já tiver sido atingido o momento em que o led de alerta de final do tempo deve começar a piscar, torna verdadeira a variável alertaAtivo. No início do programa, esse momento foi definido para 3h50min após o boot.
  2. em verde-oliva: se já tiver sido atingido o momento em que o led deve ser desligado, e ele ainda estiver ligado, desliga-o, e aproveita para desligar o alerta de final do tempo, e ativar o led de lembrete de que o sistema já pode ser desligado, para poupar ainda mais energia.
  3. em cáqui: controla as piscadas do led de alerta de final de tempo. Note que o estado que é escrito no pinoLedFinal será verdadeiro (que equivale a HIGH) quando o resto da divisão do contaLoop por 4 for zero, e será falso nos demais casos. Isso equivale a dizer que o led ficará aceso em 1/4 das rodadas do loop.
  4. em vermelho: controla as piscadas do led de lembrete de que o sistema já pode ser desligado, para poupar ainda mais energia. Se eu incluísse um circuito que permite ao Arduino cortar a alimentação de si mesmo, ficaria ainda mais sustentável ;-)
  5. em azul celeste: identifica se o botão está pressionado. Se estiver, zera a contagem e reinicializa todas as variáveis de estado.

É só isso. Simples, não? O melhor é que funcionou, e o mesmo código acima pode ser usado em um ATtiny85 (como o meu) ou em um Arduino.

Comentar

Dos leds ao Arduino, ESP8266 e mais

Aprenda eletrônica com as experiências de um geek veterano dos bits e bytes que nunca tinha soldado um led na vida, e resolveu narrar para você o que descobre enquanto explora esse universo – a partir da eletrônica básica, até chegar aos circuitos modernos.

Por Augusto Campos, autor do BR-Linux e Efetividade.net.

Recomendados

Livro recomendado


Artigos já disponíveis

Comunidade Arduino

O BR-Arduino é integrante da comunidade internacional de entusiastas do Arduino, mas não tem relação com os criadores e distribuidores do produto, nem com os detentores das marcas registradas.

Livros recomendados