Automatizar determinadas tarefas simples do dia a dia pode ser bem vantajoso. E uma coisa que fazemos diariamente é acender e apagar a luz do quarto por exemplo. Seria muito melhor se isto fosse feito automaticamente, certo?

Tendo em vista esse pensamento, neste post, veremos como projetar um sistema para controlar a luz de um cômodo automaticamente.

A versão 2 deste projeto pode ser acessada aqui. Ela está bem mais profissional, então recomendo vê-la.


Discutindo a ideia

Obs.: Este projeto demanda tempo e não e nada simples , então leia o post com calma para entender tudo. Eu levei 3 dias para conseguir terminá-lo (gastando diversas horas em cada dia).

Objetivo e características

O objetivo do projeto é acender a luz de um cômodo automaticamente. Mas a ideia é ampla e ainda é preciso definir algumas especificações, como o que será levado em conta para acender ou apagar a luz.

Bem, a forma que pensei para fazer o sistema é considerar o número de pessoas dentro do ambiente. Se houver no mínimo uma pessoa, ele acende a luz. Senão, a luz é apagada.

Além disso, é interessante que o sistema só acenda a luz caso o cômodo esteja escuro. E, caso ele esteja bem iluminado, a luz deve permanecer apagada mesmo que haja uma pessoa dentro dele.

Essa definição de “escuro” e “bem iluminado” vai depender da sua necessidade, do quanto de luz você considera suficiente para o ambiente estar “bem iluminado”. Portanto, este será um parâmetro ajustável.

Detecção de pessoas no cômodo

Em relação à necessidade de reconhecer quantas pessoas entraram no cômodo, ela pode ser feita de algumas formas diferentes. Entretanto, a forma que escolhi é colocar dois sensores de obstáculo perto da porta. Esta é a forma que considero a mais barata, a mais fácil de implementar e que garante melhores resultados.

A ideia central é que o sensor de obstáculo seja capaz de informar se algo passou na frente dele. Como ele ficará próximo à porta, ele indicará se alguém passou pela porta (entrou ou saiu).

E, para identificar se a pessoa saiu ou entrou, basta utilizar dois sensores de obstáculos, um próximo ao outro. Quando alguém entrar no cômodo, o sensor que está mais perto da entrada vai detectar primeiro que o outro sensor. Com isto, o sistema é capaz de saber que a pessoa entrou.

E a mesma lógica se aplica ao sentido contrário. Se a pessoa está saindo, o sensor mais afastado da entrada vai detectar primeiro que o outro sensor.

Veja a imagem abaixo para entender (não se preocupe em saber o que é o sensor de obstáculo por enquanto).

Lógica do sistema de acendimento automático da luz

Detecção da iluminação

Por fim, precisamos pensar em como detectar se o ambiente está escuro ou bem iluminado. Para isto, bastará utilizar um sensor de intensidade luminosa.

E, a partir deste sensor, regularemos o nível adequado que o sistema considerará o ambiente como escuro. Mais adiante veremos como isto será feito. 


Implementação


Circuito

Sensor de obstáculo

Para fazer o sensor de obstáculo, resolvi utilizar um sensor ultrassônico. Pode parecer um pouco contra-intuitivo fazer isto, mas vamos entender os porquês:

O sensor de obstáculo comumente encontrado é o infravermelho. Mas o sensor infravermelho tem a desvantagem de sofrer interferência da radiação infravermelha do ambiente. Isso impossibilita ele de ser utilizado durante o dia, já que seria capaz de detectar obstáculos apenas em distâncias muito pequenas quando está sofrendo interferência da radiação infravermelha solar.

Portanto, outro sensor que pode substituí-lo é o ultrassônico. E basta seguir o mesmo princípio do sensor de obstáculo infravermelho: se o sensor ultrassônico detectou uma distância menor que um certo valor, ele informa que há um obstáculo em sua frente.

Um detalhe a ser adicionado é que utilizarei o sensor ultrassônico HC-SR04, que utiliza um pino para iniciar a medição e outro para leitura da distância. E, adiantando um pouco o desenvolvimento, irei utilizar o microcontrolador ATtiny85, que possui poucos pinos.

A quantidade de  pinos dele será insuficiente para ligar os dois pinos do sensor ultrassônico em dois pinos separados do microcontrolador. Portanto, terei que interligar os pinos do sensor ultrassônico e lidar com a leitura de forma diferente na programação. Desta forma, os dois sensores vão precisar de 1 pino cada, o que deixa livre 4 pinos do ATtiny85.

Adiantando: a leitura será feita da igual ocorre no sensor da Parallax, que utiliza apenas um pino para todo o processo de leitura da distância.

Detecção da iluminação

Para a parte de detectar se o ambiente está escuro ou não, basta utilizar um LDR, que é um sensor de intensidade luminosa. Para ter leituras significativas do LDR, utilizaremos ele em um divisor de tensão:

LDR com Arduino

Antes de seguir com o projeto, é importante montar o circuito acima para conseguirmos obter qual é o valor lido pelo LDR que informará se o ambiente está escuro ou bem iluminado.

Para isto, com o circuito acima, basta fazer um programa para ler a porta analógica A0 e exibir seu valor no monitor serial. Caso você tenha dificuldade nesta parte, recomendo ler o post sobre leitura analógica.

Com o circuito montado e a programação funcionando, basta colocar o LDR no local onde o sistema ficará e verificar o valor lido. No meu caso, analisei os valores com a janela fechada (quarto escuro) durante o dia e durante a noite. E, em ambos os casos, o quarto estava escuro (em minha concepção) para valores menores que 8.

Acendimento da lâmpada

Para acender a lâmpada, será necessário criar um circuito com transistor e relé. Não pretendo entrar nos detalhes deste circuito aqui, pois existe um post inteiramente dedicado à isto.

Botão de emergência

Caso ocorra algum erro com os sensores, resolvi adicionar um botão ao circuito para acender a lâmpada independente das condições do ambiente. É como se fosse um botão de emergência, que acenderá a lâmpada não importa o que aconteça.

Fonte externa

Para alimentar o circuito todo (sensores e microcontrolador) é necessário uma fonte externa de 5v. A solução que encontrei foi pegar uma fonte de 5v, parecida com as fontes de carregar celular, e desmontar a carcaça dela. Veja imagem abaixo da fonte desmontada (fiz uma pequena caixinha para ela – mais detalhes disso no fim do post).

Fonte externa do sistema da luz automática

A entrada desta fonte (fase e neutro indicado pelo número 3 da imagem) serão conectados atrás do interruptor da luz. Para isso, tive que passar uma fase e um neutro até a parte de trás do interruptor. Ambos vieram da conexão da tomada que fica “embaixo” do interruptor, como mostra a imagem abaixo.

Caminho do eletroduto

O desenho em amarelo mostra o caminho do eletroduto que sai da tomada e vai ao interruptor.

Na imagem da fonte, o número 1 era um LED que havia na placa que decidi remover, já que a fonte ficará escondida. E, onde está indicado pelo número 2, havia um conector USB, que decidi remover também, pois não será utilizado.

Dentro da indicação do número 2, há dois pontos marcados por circunferências, que são os dois pontos onde soldei fios para ligar o 5v do circuito. No seu caso, você pode ligar a fonte e medir a saída com o multímetro para saber onde soldar os fios do 5v.

Isso tudo que fiz acima pode ser evitado se você não desmontar a fonte externa e ligá-la direto na tomada. Mas lembrando de soldar dois fios na saída dela para alimentar o circuito. Decidi fazer os passos acima para tentar deixar a fonte o escondida.

Esquemático

Conforme disse, para este projeto, resolvi utilizar o microcontrolador ATtiny85. Você pode escolher qualquer outro microcontrolador, desde que a quantidade de pinos dele seja maior ou igual a do ATtiny85. Resolvi escolhe-lo, pois ele é compacto e relativamente fácil de achar para comprar.

Veja o esquemático do circuito abaixo. Gaste um tempo para analisar o circuito com calma e entender cada parte. E releia os tópicos acima para entender o que é cada elemento.

Circuito do sistema da luz automática

Os pinos do sensor ultrassônico se referem ao pino Trig e Echo que foram interligados. Veja imagem abaixo para entender.

Pinos do sensor ultrassônico interligados
Soldei os dois terminais juntos.

O  “Sensor Saindo” é o pino do sensor ultrassônico mais afastado da entrada. E o “Sensor Entrando” é o pino do sensor mais próximo à entrada do cômodo.

O esquemático pode ser seguido sem problemas, você só deve modificar o circuito do relé, pois o seu relé pode ser diferente do meu. Portanto, não deixe de ver este post para saber calcular o resistor de base do transistor.

Ligação do relé com a lâmpada

No esquemático anterior, ficou faltando falar sobre como o relé é interligado à lâmpada. Como esta é uma parte importante, resolvi colocá-la separadamente.

A ligação basicamente vai obedecer a ligação do seu interruptor. Quando você abrir a tampa do interruptor, irá se deparar com o “circuito da lâmpada”.

Se a sua lâmpada for comandada por apenas um apagador, o interruptor estará com apenas dois fios ligados. Para este caso, basta ligar um dos fios no terminal central do relé e outro na extremidade normalmente aberta do relé. Para descobrir qual é a extremidade normalmente aberta, faça um teste de continuidade.

Veja a ligação abaixo:

Ligação do relé com a lâmpada 1º caso

Agora, se sua lâmpada for comandada por mais de um apagador (three way), o interruptor estará com 3 fios ligados a ele. Neste caso, é só ligar os 3 fios, um em cada terminal do relé. Veja imagem abaixo:

Ligação do relé com a lâmpada 2º caso

Pode ser que, para o caso acima, quando o sistema for acender a luz, ela na verdade se apague e vice-versa. Se isto ocorrer, basta ir no outro interruptor (o que você não mexeu) e trocar o estado dele. Assim, a lógica do acendimento da lâmpada ficará normal.

Opcional

Uma etapa opcional do circuito que você pode fazer é:

Depois da etapa anterior, não deve ter nada mais conectado ao interruptor. Portanto, você pode utilizar o interruptor para ligar/desligar o sistema. Isto é feito passando a fase (ou o neutro) da fonte externa pelo interruptor.

Sendo assim, se o interruptor estiver desligado, a fase (ou o neutro) é interrompida e a fonte deixa de alimentar o circuito. E, caso contrário, a fase alimenta a fonte e ela alimenta o circuito.

Decidi fazer isto para adicionar uma forma de resetar o microcontrolador, embora não seja a forma mais ideal. Com isso, caso ocorra algum erro na programação, basta desligar o interruptor. E, se o cômodo não for ser utilizado por um tempo, também é bom deixar o sistema desligado.


Programação

A programação será feita com a IDE do Arduino e depois os códigos serão carregados no ATtiny.

Programando o ATtiny

Uma etapa importante da programação é saber como programar o ATtiny. Não pretendo explicar como isto é feito neste post, pois já existe um post exclusivo para esta finalidade.

Lendo os sensores ultrassônicos

Como estamos interligando os pinos do sensor ultrassônico, temos que adaptar o código para fazer a leitura corretamente. Acaba que é só fazer todas as etapas da leitura com um único pino.

Para ler sobre como fazer o procedimento de leitura do sensor ultrassônico, veja este post.

Além da leitura, temos que verificar se a distância medida é menor do que um certo valor para, então, sinalizar 1 ao programa, conforme a lógica do sensor de obstáculo.

Após alguns testes que fiz, constatei que uma distância menor que 50cm é ideal para considerar que há um objeto na frente do sensor. Isto pode variar de caso para caso, já que nem toda entrada de um cômodo é igual.

Outra distância importante é quando algo está encostando no sensor (na sua frente). Quando isto ocorre, o sensor retorna uma distância muito grande (maior que 200cm pelos meus testes). Portanto, considerei que distâncias maiores que 200cm também indicam obstáculos na frente do sensor. Isso não é um problema, porque a parede que fica na frente do sensor (quando não há nada em sua frente) está a ~130cm dele.

E adicionei um parâmetro da distância ser diferente de 0cm. Isso para o caso em que o sensor não deu resposta (possivelmente algum erro de conexão).

Por fim, englobei essa lógica toda em uma função, que pode ser vista no tópico adiante.

Código de leitura dos sensores

Leia os comentários para entender o código.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*  
 * Informa se o sensor especificado detectou algum obstáculo.
 * Parâmetros:      
 *     sensor: pino do sensor que deve ser lido
 * Retorna: 1 se detectou obstáculo e 0 se não.  
 */

bool leitura_sensor(char sensor) {
  // Inicia a leitura mandando um pulso de 10uS
  pinMode(sensor, OUTPUT);
  digitalWrite(sensor, HIGH);
  delayMicroseconds(10);
  digitalWrite(sensor, LOW);

  // Lê o sinal de resposta e converte para distância
  pinMode(sensor, INPUT);
  float dist = pulseIn(sensor, HIGH);
  dist = dist * 0.034 / 2.0;
 
  // Verifica se há um obstáculo na frente do sensor
  if (dist != 0 && (dist < 50 || dist > 200))
    return true;
  else
    return false;
}

Lógica do código

Não pretendo explicar qual foi a lógica que utilizei, pois é possível entender o código pelos comentários e, também, porque existem diferentes formas de se criar a programação do sistema.

Mas, saiba que fiz a lógica me baseando na imagem que mostrei no início do post (a imagem abaixo).

Lógica do sistema da luz automática

É basicamente uma máquina de estados. E, no código, criei variáveis para o programa saber em qual estado ele se encontra (entrando1, entrando2, saindo1, saindo2).

O que pode causar mais confusão talvez sejam as variáveis de tempo que criei (tempoE, tempoS e tempoL). As duas primeiras são uteis no seguinte:

Se alguém entrou no primeiro sensor e resolveu voltar, deve haver um tempo limite para indicar que a pessoa desistiu de entrar. A tempoE monitora o tempo limite de entrada e a tempoS monitora o tempo limite de sáida.

Já a variável tempoL serve para monitorar um tempo de 5 segundos quando LDR detectar que escureceu. Isso é feito, porque pode passar uma sombra na frente do LDR, o que não quer dizer que escureceu. Portanto, é necessário que ele detecte que o ambiente está escuro por 5 segundos até que o sistema decida ligar a lâmpada.

Código completo

O código está bem comentado, então leia ele com calma para entender cada etapa. Ele poderia ter sido melhorado significativamente se eu tivesse usado a estrutura switch case para avaliar os estados do programa.

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// Definições do programa
#define rele 0 // Pino para ligar/desligar o relé
#define entrada 1 // Sensor mais perto da porta
#define saida 2 // Sensor mais longe da porta
#define botao 3 // Botão para ligar a luz manualmente
#define ldr A2 // Pino ligado ao divisor de tensao LDR + Resistencia

// Macro para facilitar a leitura do LDR
#define leituraLDR analogRead(ldr)

// Variaveis do programa:
bool entrando1 = false; // Indica que a pessoa está entrando e passou do primeiro sensor
bool entrando2 = false; // Indica que a pessoa está entrando e passou do segundo sensor
bool saindo1 = false; // Indica que a pessoa esta saiando e passou do segundo sensor (1º da saida)
bool saindo2 = false; // Indica que a pessoa esta saiando e passou do primeiro sensor (2º da saida)
bool escureceu = false; // Indica se está escuro ou nao
bool acende = false; // Indica se a lampada deve ser acionada ou nao
int contagem = 0; // Contar quantas pessoas tem no quarto
unsigned long tempoE = 0; // Tempo de espera para aceitar se a pessoa esta entrando ou nao
unsigned long tempoS = 0; // Tempo de espera para aceitar se a pessoa esta saindo ou nao
unsigned long tempoL = 0; // Tempo de espera para aceitar se escureceu (tempoldr)

// Funções
void verifica_tempoS(void); // Manipula as variaveis de tempo
bool leitura_sensor(char sensor); // Indica se alguém passou na frente do sensor ultrassônico

void setup() {
  // Configura os pinos
  pinMode(rele, OUTPUT);
  pinMode(botao, INPUT_PULLUP);
  pinMode(ldr, INPUT);
  digitalWrite(rele, LOW);
}

void loop() {  
  // Verifica se os sensores detectaram algo
  bool leituraE = leitura_sensor(entrada);
  bool leituraS = leitura_sensor(saida);
 
  // Logica da pessoa entrando
  if (leituraE && !leituraS && !saindo1) { // Condiçao da pessoa estar entrando (nao esta saindo e leituraE é true)
    entrando1 = true;
    tempoE = millis();
  }
  if (!leituraE && leituraS && entrando1 ) { // Condiçao para a pessoa estar entrando no meio do caminho
    entrando2 = true;
    tempoE = millis();
  }
  if (leituraE && !leituraS && entrando2){ // Condição para a pessoa desistir de entrar e voltar
    entrando2 = false;
    tempoE = millis();
  }  
  if (!leituraE && !leituraS && entrando2) { //Condiçao para a pessoa ter entrado (nenhum sensor le nada)
    contagem++;
    entrando1 = false;
    entrando2 = false;
    delay(500); // Delay para nao duplicar a leitura)
  }


  // Logica da pessoa saindo
  if (leituraS && !leituraE && !entrando1) { //Condiçao da pessoa estar saindo (nao esta entrando e leituraS é true)
    saindo1 = true;
    tempoS = millis();
  }
  if (!leituraS && leituraE && saindo1) { //Condiçao para a pessoa estar entrando no meio do caminho
    saindo2 = true;
    tempoS = millis();
  }
  if (!leituraE && leituraS && saindo2){ // Condição para a pessoa desistir de sair e voltar
    saindo2 = false;
    tempoS = millis();
  }  
  if (!leituraS && !leituraE && saindo2) { //Condiçao para a pessoa ter saido (nenhum sensor le nada)
    if (contagem > 0) { //So diminui se tiver alguem dentro do quarto
      contagem--;
    }
    saindo1 = false;
    saindo2 = false;
    delay(500); //delay para nao duplicar a leitura
  }
 

  // Logica da pessoa parada no meio do caminho
  if (leituraE && leituraS) { //Condiçao para a pessoa estar parada no meio do caminho
    if (entrando1 || entrando2) {
      tempoE = millis();
    }

    if (saindo1 || saindo2) {
      tempoS = millis();
    }
  }


  // Manipula os tempos
  verifica_tempos();


  // Logica do acendimento da lampada
  if (leituraLDR < 8) { //se o ldr indicou que escureceu
    if (!escureceu){
      escureceu = true;
      tempoL = millis(); // tempo para saber se nao foi apenas uma sombra
    }
  } else { //se o ldr indicou que esta claro
    escureceu = false;
  }
 
  if(digitalRead(botao)){ // Se o botão está desligado, funciona normalmente
    if (contagem >= 1 && acende) {
      digitalWrite(rele, HIGH);
    } else {
      digitalWrite(rele, LOW);
      acende = false;
    }
  }else{ // Senão, apenas acende o relé
    digitalWrite(rele, HIGH);
  }
}

/*
 * Verifica se os intervalos limites de tempo de entrada e saída foram ultrapassados para reiniciar as variáveis
 * Verifica se o LDR ficou  escuro por no mínimo 5 segundos
 */

void verifica_tempos(void) {
  // Entrada
  if (millis() - tempoE >= 500) {
    entrando1 = false;
    entrando2 = false;
  }

  // Saida
  if (millis() - tempoS >= 500) {
    saindo1 = false;
    saindo2 = false;
  }

  // Espera 5 segundos para saber se está de fato escuro ou se foi uma sombra que passou no sensor
  if (escureceu && millis() - tempoL >= 5000) {
    acende = true;
  }
}

/* Informa se o sensor especificado detectou algum obstáculo.
 * Parâmetros:      
 *     sensor: pino do sensor que deve ser lido
 * Retorna: 1 se detectou obstáculo e 0 se não.  
 */

bool leitura_sensor(char sensor) {
  // Inicia a leitura mandando um pulso de 10uS
  pinMode(sensor, OUTPUT);
  digitalWrite(sensor, HIGH);
  delayMicroseconds(10);
  digitalWrite(sensor, LOW);

  // Lê o sinal de resposta e converte para distância
  pinMode(sensor, INPUT);
  float dist = pulseIn(sensor, HIGH);
  dist = dist * 0.034 / 2.0;

  // Verifica se há um objeto na frente do sensor
  if (dist != 0 && (dist < 50 || dist > 200))
    return true;
  else
    return false;
}

Montagem estrutural

Depois de programar o ATtiny e criar uma plaquinha, seja ela uma PCI ou uma placa ilhada (meu caso), é necessário fazer uma estrutura para que os sensores fiquem parados direcionados para a porta.

A solução que optei foi desenhar uma caixa com as corretas dimensões dos sensores e imprimi-la com uma impressora 3D. Como não tenho muita experiência com esta parte estrutural, acabou que a caixa que fiz não ficou muito adequada.

Aqui está o link para download dos arquivos de impressão. Comecei desenhando a caixa principal na escala errada (cm), por isso o desenho possui uma mudança de escala, para converter para mm.

Acabei não imprimindo a caixa depois de ter feitos alguns ajustes no desenho. Então, tive que fazer algumas adaptações na caixa impressa.

Circuito principal e sensores

Essa caixa serve para colocar os sensores (ultrassônico, LDR) e o circuito principal, incluindo o botão. Veja a imagem do desenho abaixo.

Caixa dos sensores e circuito principal

A imagem acima mostra a parte da frente da caixa, onde os sensores ultrassônicos devem ser posicionados. O ponto 1 é o furo onde deve ser encaixado o LDR. E o furo 2 é onde deve ser passado o botão.

É necessário alterar as dimensões do desenho para as dimensões do seu botão e do seu circuito principal.

Por fim, a imagem a seguir mostra o espaço onde o circuito deve ser colocado, que é a parte de trás da caixa.

Caixa dos sensores e circuito principal

E não há nenhum elemento na caixa que permita que ela seja parafusada. Isto porque, projetei ela considerando que ia fixar utilizando fita dupla face (daquelas que aguentam vários quilos). Portanto, utilize o arquivo para adicionar algum elemento para atender sua necessidade.

Fonte externa

Como disse anteriormente, para fazer a fonte externa, desmontei uma fonte de 5v e removi alguns componentes. E, para não deixar ela sem proteção, fiz uma caixa para ela.

As imagens da caixa e da tampa estão mostradas abaixo. Pode ser que a tampa não fique fixada na caixa, então use uma fita para prender os dois.

Caixa da fonte externa
Tampa da caixa da fonte externa

Resultados

Cheguei a gastar 3 dias para fazer o sistema. Apesar de todo o trabalho, digo que valeu muito a pena, pois o sistema funciona muito bem e é prazeroso ver a luz acendendo e apagando sozinha.

As fotos da minha montagem podem ser vistas na sequência. Repare que o botão e o LDR estão na parte de cima da caixa principal. Isto porque, foi a primeira versão da caixa.

O bom de ter essa abertura na parte de trás da caixa principal é que fica fácil acessar o circuito do sistema e retirar o ATtiny para fazer alguma modificação na programação.