Manual
do
Maker
.
com
Já há alguns anos que eu acho arcaico a utilização de interruptores para acender lâmpadas. Um dispositivo funcional, mas analógico, sem vida, feio. E pra achar no escuro? Se não for fluorescente ou não tiver uma luzinha, é difícil. E ainda mais difícil se for igual a do meu banheiro, que é preta e não tem janelas (porque há um exaustor de teto). Bem, consegui enfim uma razão para fazer o projeto com sensor de toque capacitivo e substituir os interruptores, mas "acho" que pode não ser viável para todas as casas.
Dá pra fazer sensor capacitivo apenas com 2 pinos do Arduino e um resistor de entrada e um de saída, mas aí o coil tem que ficar exposto. Então optei por uma solução mais "cara". Um minúsculo sensor capacitivo que tem uma boa sensibilidade sem contato.
O sensor é simples, você encontra fácil no mercado livre. Para interagir com ele, basta conectá-lo ao GND e VCC, então conectar o pino de saída a um pino analógico da sua MCU. Na leitura, basta ver qual é o valor médio retornado ao contato com o espelho (que será de acrílico e substituirá o tradicional espelho e interruptor). Tendo esse valor, é só trocar o limítrofe no define.
"Alguém vai ter que fechar o circuito para acender a lâmpada, hum? Por isso que acho que não servirá para qualquer casa, pois eu estou pegando o fio do conduite que vai para a tomada e alimentando a microcontroladora com ele. Quando acontece a "interrupção" do sensor de toque, o estado do relé será modificado para seu estado oposto, fazendo assim com que a lâmpada seja ligada ou desligada.
Só um acrílico fumê não seria nada bonito, certo? Ainda mais que só pioraria a situação de acender a lâmpada no escuro. Por isso eu fiz um conjunto de LEDs pulsantes, esmaecendo gradativamente. Desse modo, será fácil encontrar esse moderno interruptor no escuro.
Quando o interruptor é tocado e o sensor de toque enviar um sinal, uma função extra fará com que os LEDs circulem por um período, evitando assim interrupções consecutivas sem causar a impressão de que o processo está travado; é um feedback para o usuário.
Utilizei o PCF8574 para fazer as animações do LED. Infelizmente eu inverti a ordem pretendida e o PCF8574 está alimentando os LEDs invés de aterrá-los, que acredito ser o ideal, mas de qualquer modo, a prova de conceito está funcional e vou implementá-la em um projeto de home automation que estou fazendo. Quando finalizar (daqui a alguns mêses) mostro a casa toda como ficou.
Eu nem ia escrever artigo a respeito antes de toda a casa pronta, mas achei que valia a pena. Como não tinha intenção de escrever artigo, não caprichei na prova de conceito. Os LEDs foram presos a um pedaço de papelão e fixados com cola quente. Como não tenho o espelho de acrílico agora (vamos mandar cortar sob medida), utilizei um material que nem sei o nome, só pra testar o esmaecimento dos LEDs. O sensor de toque ficará no meio dos LEDs e o alinhamento correto será feito com uma placa de protótipo, então, não reparem a feiura agora e tenham em mente que é uma prova de conceito, nada mais além disso.
Ainda não defini a MCU, para o teste eu utilizei um Arduino Nano (o que aparece na imagem.
O código para esse projeto (ainda sem a implementação do relay) é esse abaixo. Utilizei a biblioteca TimerOne para gerar um timer sem interromper o fluxo principal do código. O PCF controla a animação dos LEDs através dos estados escritos em cada um dos pinos. A função chamada pela TimerOne não tem loop, só algumas condicionais para tratar o incremento e o decremento do PWM. A função de acendimento circular dos LEDs trava o fluxo, e é o pretendido para dar tempo do usuário afastar o dedo do interruptor sem gerar uma nova interrupção na leitura do sensor de toque.
#include <Wire.h>
#include <TimerOne.h>
#define PCF_ADDR 0x24
#define SMOOTH_UP true
#define SMOOTH_DOWN false
#define SMOOTH_PIN 3
#define LIMIT 500
volatile int smooth = 0;
bool goUp = SMOOTH_UP;
byte leds[8] = {1, 2, 4, 8, 16, 32, 64, 128};
void getsOn() {
}
//TODO: adicionar 1 volta incrementando os bits para ON
void smoothing() {
if (goUp) {
if (smooth < 255) {
smooth++;
}
else {
goUp = SMOOTH_DOWN;
}
}
else {
if (smooth > 0) {
smooth--;
}
else {
goUp = SMOOTH_UP;
}
}
analogWrite(SMOOTH_PIN, smooth);
}
void circle() {
Timer1.detachInterrupt();
for (byte i = 0; i < 3; i++) {
for (byte pos = 0; pos < 8; pos++) {
Wire.begin();
Wire.beginTransmission(PCF_ADDR);
Wire.write(leds[pos]);
Wire.endTransmission();
delay(50);
}
}
Wire.begin();
Wire.beginTransmission(PCF_ADDR);
Wire.write(0b11111111);
Wire.endTransmission();
Timer1.attachInterrupt(smoothing);
}
void setup() {
pinMode(SMOOTH_PIN, OUTPUT);
digitalWrite(SMOOTH_PIN, LOW);
Wire.begin();
Wire.beginTransmission(PCF_ADDR);
Wire.write(0b11111111);
Wire.endTransmission();
Timer1.initialize(5000);
Timer1.attachInterrupt(smoothing);
}
void loop() {
int val = analogRead(0);
if (val > LIMIT) {
circle();
delay(500);
}
delay(100);
}
Não tenho dúvidas que esse é o pior video do canal DobitAoByteBrasil até hoje, mas não poderia deixar de mostrar o resultado (lembre-se: prova de conceito). O video não está listado no canal, por isso coloquei o link diretamente para ele aqui.
Inscreva-se no nosso canal Manual do Maker no YouTube.
Também estamos no Instagram.
Autor do blog "Do bit Ao Byte / Manual do Maker".
Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.