Lámpara de amanecer DIY
Esta es la construcción de mi lámpara de amanecer. Quería saber si una lámpara que simula el amanecer podía facilitar de verdad el despertarse en las oscuras mañanas de invierno. Como no quería gastar más de 60 euros en una lámpara ya hecha, y además me gusta fabricar cosas, se me ocurrió este diseño.
La idea es que la luz te ayude a despertarte poco a poco, igual que en una mañana de verano, de forma relajada y sin necesidad de una alarma brusca.
Está construida a partir de una lámpara de mesa Ikea Fado y una bombilla LED regulable, utilizando una base impresa en 3D para alojar la electrónica. La unidad final se controla desde mi panel de Node-RED en la Raspberry Pi.
Piezas necesarias para la lámpara de amanecer
- Lámpara Fado - Ikea
- Bombilla LED regulable - Ikea
- WeMos D1 mini
- Hi-Link 220V AC - 5V DC
- Regulador PWM RobotDyn
- Conectores Dupont
- Base impresa en 3D
Sin contar la impresión 3D, el coste total fue inferior a 25 euros.
Base impresa en 3D para la lámpara de amanecer
Empecé utilizando SketchUp para diseñar una base que sujetara la electrónica encargada de controlar la lámpara.
El diseño puede descargarse en Thingiverse.
Imprimí con un 20 % de relleno y 3 perímetros para la base y las paredes. Así se consigue una pieza bastante sólida. Con los ajustes que utilicé, el tiempo de impresión supera las 12 horas.
La lámpara no se asienta completamente en la base impresa debido al estrechamiento de su parte inferior. No era mi intención, pero apenas se nota y, además, los cuatro pequeños huecos que quedan ayudan a disipar el calor.
Añadiendo la electrónica a la base
Recortar el disipador térmico
Es necesario reducir la altura del disipador del regulador PWM RobotDyn para que quepa bajo la base de la lámpara.
Con una sierra para metal recorté 10 mm de la parte superior del disipador.
No suelo recomendar reducir el tamaño de un disipador, pero como la lámpara solo funcionará unos 45 minutos al día, la acumulación de calor debería ser mínima.
Soldar los pines del WeMos D1 mini
Utilicé dos grupos de pines, uno de 2 y otro de 4, tal y como se ve en la imagen.
- Pines: 5V y G
- Pines: D6, D7, D8 y 3.3V
Insertar y conectar los componentes
La electrónica queda sujeta con un poco de cola caliente.
He acortado cables Dupont estándar. La verdad es que debería invertir en una crimpadora, porque me ahorraría tiempo y el acabado sería mucho mejor.
Conexiones de cableado
- Alimentación AC del Hi-Link.
- Alimentación AC del Hi-Link.
- Conexión negativa DC empalmada al pin GND del WeMos.
- Conexión positiva DC al pin 5V del WeMos.
- Pin GND del regulador empalmado al pin G del WeMos.
- Pin VCC del regulador conectado al pin 3.3V del WeMos.
- Pin Z-C del regulador conectado al pin D6 del WeMos.
- Pin PWM del regulador conectado al pin D7 del WeMos.
Corta el cable de alimentación de la lámpara de forma que queden unos 100 mm en el lado de la bombilla. Estaña los extremos con una pequeña cantidad de soldadura, suelda también los cables AC del Hi-Link al cable de alimentación y fija todo en las bornas del regulador, tal como se muestra.
Programando el WeMos D1 mini
Ya utilizo Node-RED y MQTT en mi Raspberry Pi para controlar varios dispositivos de la casa, así que quería integrar esta lámpara de amanecer DIY en el mismo sistema.
La parte principal del código que controla la placa reguladora procede de la página de GitHub de Nassir Malik aquí. Le agradezco mucho su trabajo, porque me sirvió de gran ayuda.
Añadí compatibilidad con Wi-Fi y MQTT, además de una rutina que incrementa progresivamente el brillo de la lámpara durante un periodo de 30 minutos.
#include "hw_timer.h"
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// Change the credentials below, so your ESP8266 connects to your router
const char* ssid = "Your SSID";
const char* password = "Your Password";
// Change the variable to your Raspberry Pi IP address, so it connects to your MQTT broker
const char* mqtt_server = "MQTT Server IP Address";
// Initializes the espClient. You should change the espClient name if you have multiple ESPs running in your home automation system
WiFiClient sunrise;
PubSubClient client(sunrise);
const byte zcPin = 12;
const byte pwmPin = 13;
byte fade = 1;
byte state = 1;
byte tarBrightness = 5;
byte curBrightness = 0;
byte zcState = 0; // 0 = ready; 1 = processing;
void ICACHE_RAM_ATTR zcDetectISR ();
void ICACHE_RAM_ATTR dimTimerISR ();
int val = 1;
int tim = 1;
String lampState = "off";
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("WiFi connected - ESP IP address: ");
Serial.println(WiFi.localIP());
}
void callback(String topic, byte* message, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
String messageTemp;
for (int i = 0; i < length; i++) {
Serial.print((char)message[i]);
messageTemp += (char)message[i];
}
Serial.println();
if (topic == "sunriseLamp/state") {
Serial.print("Turning on Outside light ");
if (messageTemp == "on") {
lampState = "on";
Serial.print("On");
}
else if (messageTemp == "off") {
lampState = "off";
Serial.print("Off");
}
}
Serial.println();
}
// This functions reconnects your ESP8266 to your MQTT broker
// Change the function below if you want to subscribe to more topics with your ESP8266
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("D1Mini_sunriseLamp")) {
Serial.println("connected");
// Subscribe or resubscribe to a topic
// You can subscribe to more topics (to control more LEDs in this example)
client.subscribe("sunriseLamp/state");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
pinMode(zcPin, INPUT_PULLUP);
pinMode(pwmPin, OUTPUT);
attachInterrupt(zcPin, zcDetectISR, RISING); // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
hw_timer_init(NMI_SOURCE, 0);
hw_timer_set_func(dimTimerISR);
}
void mqttCheck() {
if (!client.connected()) {
reconnect();
}
if (!client.loop())
client.connect("D1Mini_sunriseLamp");
}
void loop() {
if (WiFi.status() != WL_CONNECTED) {
delay(1);
setup_wifi();
return;
}
mqttCheck();
if (lampState == "off") state = 0;
if (lampState == "on") {
val = 1;
state = 1;
for (val <= 250; val++;) {
tarBrightness = val;
mqttCheck();
if (lampState == "off") {
state = 0;
Serial.println(lampState);
break;
}
delay(7200);
}
}
}
void dimTimerISR() {
if (fade == 1) {
if (curBrightness > tarBrightness || (state == 0 && curBrightness > 0)) {
--curBrightness;
}
else if (curBrightness < tarBrightness && state == 1 && curBrightness < 255) {
++curBrightness;
}
}
else {
if (state == 1) {
curBrightness = tarBrightness;
}
else {
curBrightness = 0;
}
}
if (curBrightness == 0) {
state = 0;
digitalWrite(pwmPin, 0);
}
else if (curBrightness == 255) {
state = 1;
digitalWrite(pwmPin, 1);
}
else {
digitalWrite(pwmPin, 1);
}
zcState = 0;
}
void zcDetectISR() {
if (zcState == 0) {
zcState = 1;
if (curBrightness < 255 && curBrightness > 0) {
digitalWrite(pwmPin, 0);
int dimDelay = 30 * (255 - curBrightness) + 400;//400
hw_timer_arm(dimDelay);
}
}
}
Configuración en Node-RED
Estoy utilizando tres nodos en este flujo.
- Big Timer Node - para más información, consulta Scargill’s Big-Timer
- Switch Node - utilizado como anulación manual
- Mqtt Output Node
He estado usando la lámpara de amanecer DIY durante unos días y, aunque la luz no me despierta siempre, es agradable no estar completamente a oscuras cuando mi Google Home Mini empieza a reproducir música.