Hue Lamp Clone

Autor: Oscar Gonzalez

Hue Lamp Clone

Tiempo de lectura: 2 minutos

Simple lámpara RGB impresa en 3D controlada con ESP8266

Hue Lamp Clone

  • 0

0 Principiante

Introducción

Si te gusta imprimir en 3D y te gustan los proyectos con LEDS, estás en el sitio adecuado!

Ésta es una simple lámpara RGB controlada con ESP8266 que permite establecer el color que quieras y también tiene algunos efectos de luz pre establecidos.

El cuerpo está impreso en 3D y se imprime sin soportes.

Archivos STL

Si te gusta éste tipo de proyectos y la electrónica, tenemos una lista de correo donde comparto muchos trucos e historias que estoy seguro que te gustarán.

Con tan solo apuntarte a la lista, podrás acceder al enlace para descargar los archivos STL de la lámpara y además entrarás a formar parte de la comunidad de cientos de personas que cada día se divierten y aprenden en nuestra lista. 

Lo pasaremos bien, ¡te lo aseguro!

Apúntate aquí

Lista de materiales

La lámpara necesita de muy poco para funcionar y aquí abajo encontrarás la lista de componentes que necesitas.

Recuerda que la lámpara necesita una alimentación externa de 5V de al menos 2A para funcionar. De 1A tambien puede valer, pero siempre es mejor que sobre un poco.

NodeMCU V3 Wifi - ESP8266, CH340

NodeMCU V3 Wifi - ESP8266, CH340

Placa NodeMCU Wifi para desarrollo IoT basada en ESP8266 / CH340G

3,95€

Comprar


Tira de LED RGB 0.5m 72 LEDs (SK6812)

Tira de LED RGB 0.5m 72 LEDs (SK6812)

Tira de LED RGB indexable de alta densidad con chip SK6812 resistente al agua

31,95€

Comprar


Filamento PLA 850 1Kg - Magic Coal (1.75mm) - Carbón

Filamento PLA 850 1Kg - Magic Coal (1.75mm) - Carbón

Bobina de filamento PLA INGEO 850 de 1.75 mm de alta calidad. Sakata 3D

17,60€

Comprar


Filamento PLA 850 1Kg - Blanco. Sakata 3D

Filamento PLA 850 1Kg - Blanco. Sakata 3D

Bobina de filamento PLA INGEO 850 de 1.75 mm de alta calidad. Sakata 3D

17,60€

Comprar


Código fuente Arduino

El código fuente es muy sencillo y está basado en el típico ejemplo de Webserver de Arduino. Lo que hace es generar una página web que permite mediante unos sliders establecer el color que quieras.

Ten en cuenta que la lámpara debe estar conectada a tu red wifi primero para que funcione.

Utilicé un pequeño truco ya que aprovechando la conexión a Internet, el código genera una página web utilizando Bootstrap (un conjunto de CSS) para hacerla un poco más atractiva.

Tanto Bootstrap como alguna librería de Javascript la pilla de una CDN para ahorrar espacio de memoria. Eso quiere decir que para que todo funcione, imperativamente la lámpara debe tener conexión a Internet.

El control se realiza mediante llamadas asíncronas (AJAX) para que sea lo más responsiva posible. La página web se acopla a diferentes resoluciones de pantalla en función del dispositivo que utilices.

El código está embebido directamente en el código y ocupa entorno a 3kb de memoria. Por lo que si haces alguna modificación, hay que prestar atención de no pasarse mucho para no saturar la memoria.

El código lo puedes encontrar al completo aquí abajo y verás que es muy sencillo. Necesitarás tener instaladas éstas librerías:

  • ESP8266WiFi
  • WiFiClien
  • ESP8266WebServer
  • ESP8266mDNS
  • FastLED

Si no tienes claro cómo hacerlo, no te pierdas mi tutorial sobre cómo instalar librerías en Arduino donde te lo explico todo.

/*************************************************************
  NodeLamp
  Oscar Gonzalez - Abril 2020
  www.BricoGeek.com
 *************************************************************/

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <FastLED.h>

#define NUM_LEDS 72
#define DATA_PIN 4

CRGB leds[NUM_LEDS];
ESP8266WebServer server ( 80 );

int current_mode = 0;

int color_red=0;
int color_green=0;
int color_blue=0;

uint8_t gHue = 0; // rotating "base color" used by many of the patterns

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "YOU_WIFI_SSID";
char pass[] = "MEGA_SECRET_PASSWORD";

void handleRoot() {
  char temp[2900];
  int sec = millis() / 1000;
  int min = sec / 60;
  int hr = min / 60;

  snprintf ( temp, 2900,
"<html lang="en">
<head>
  <meta charset="utf-8">
  <title>NodeHuePlay Lamp</title>
  <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
  <link href="http://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
  <script src="http://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"crossorigin="anonymous"></script>  
  <style>
    body { text-align:center; background-color: #fff; font-family: Arial, Helvetica, Sans-Serif; Color: #000; }
    .slidecontainer{width:100%%}.slider{-webkit-appearance:none;width:100%%;height:13%%;background:#d3d3d3;outline:0;opacity:.7;-webkit-transition:.2s;transition:opacity .2s}.slider:hover{opacity:1}.slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:10%%;height:100%%;background:#4caf50;cursor:pointer}.slider::-moz-range-thumb{width:65px;height:65px;background:#4caf50;cursor:pointer}
  </style>  
</head>
<body>  
    <div class="container text-center">            
      <h1 class="display-1"id="t">NodeHuePlay Lamp</h1>
      <h2>www.BricoGeek.com</h2>
      <div class="slidecontainer">
        <p><input type="range" min="0" max="254" value="%02d" class="slider" id="slider_r"></p>
        <p><input type="range" min="0" max="254" value="%02d" class="slider" id="slider_g"></p>
        <p><input type="range" min="0" max="254" value="%02d" class="slider" id="slider_b"></p>
        <p><span id="rgbvalue"></span></p>
      </div>
      <a onClick="return setmode(0);" href="#" class="btn btn-warning btn-lg btn-block">Manual RGB</a> <a onClick="return setmode(1);" href="#" class="btn btn-primary btn-lg btn-block">Random</a> <a onClick="return setmode(2);" href="#" class="btn btn-success btn-lg btn-block">Rainbow</a> <a onClick="return setmode(3);" href="#" class="btn btn-info btn-lg btn-block">Lava</a>            
    </div>
    <script>
      var r=0;var g=0;var b=0;
      $('#slider_r').on('touchend', function(){
        r = $(this).val();$.ajax({url: '/set/?r=' r '&g=' g '&b=' b, success: function(result){upd(r, g, b);}});        
      });
      $('#slider_g').on('touchend', function(){
        g = $(this).val();$.ajax({url: '/set/?r=' r '&g=' g '&b=' b, success: function(result){upd(r, g, b);}});
      });
      $('#slider_b').on('touchend', function(){
        b = $(this).val();$.ajax({url: '/set/?r=' r '&g=' g '&b=' b, success: function(result){upd(r, g, b);}});
      });      
      function setmode(n) { $.ajax({url: '/set/?mode=' n, success: function(result){ }}); return false; }
      function upd(r, g, b) { $('#rgbvalue').html('RED: ' r ' GREEN: ' g ' BLUE: ' b); $('#t').css('background', 'rgb(' r ',' g ',' b ')'); };
    </script>    
 </body>
</html>",
    color_red, color_green, color_blue
  );
  
  server.send ( 200, "text/html", temp );  
}

void handleNotFound() {  
  String message = "File Not Foundnn";
  message  = "URI: ";
  message  = server.uri();
  message  = "nMethod: ";
  message  = ( server.method() == HTTP_GET ) ? "GET" : "POST";
  message  = "nArguments: ";
  message  = server.args();
  message  = "n";

  for ( uint8_t i = 0; i < server.args(); i   ) {
    message  = " "   server.argName ( i )   ": "   server.arg ( i )   "n";
  }

  server.send ( 404, "text/plain", message );  
}

void clearLeds()
{
  for (int i=0 ; i<NUM_LEDS ; i  ) { leds[i] = CRGB::Black; }  
  FastLED.show();
}

void setFullColor(int r, int g, int b)
{
  for (int i=0 ; i<NUM_LEDS ; i  ) { leds[i] = CRGB(r,g,b); } 
  FastLED.show(); 
}

void setup()
{
  // Debug console
  Serial.begin(9600);
      
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);  
  clearLeds();
  //leds[3] = CRGB(0,255,0);  
  FastLED.show();
  delay(50);

  // Start Wifi
  WiFi.mode ( WIFI_STA );
  WiFi.begin ( ssid, pass );
  Serial.println ( "" );

  // Wait for connection
  int nled = 0;
  while ( WiFi.status() != WL_CONNECTED ) {    
    leds[nled] = CRGB(0,255,0);  
    FastLED.show();
    Serial.print ( "." );
    delay ( 10 );
    nled  ;
    if (nled > NUM_LEDS) { nled=0; }
  }  
  clearLeds();
  FastLED.show();
  Serial.println ( "" );
  Serial.print ( "Connected to " );
  Serial.println ( ssid );
  Serial.print ( "IP address: " );
  Serial.println ( WiFi.localIP() );

  if ( MDNS.begin ( "nodehuelamp" ) ) {
    Serial.println ( "MDNS responder started" );
  }

  // Start Webserver
  server.on ( "/", handleRoot );

  // Update LED colors
  server.on ( "/set/", []() {    

    Serial.println("* SET");

    String message = "Number of args received:";
    message  = server.args();
    
    for (int i = 0; i < server.args(); i  ) {

      if (server.argName(i) == "r") { color_red = server.arg(i).toInt(); current_mode=0; }      
      if (server.argName(i) == "g") { color_green = server.arg(i).toInt(); current_mode=0; }      
      if (server.argName(i) == "b") { color_blue = server.arg(i).toInt(); current_mode=0; }      
      if (server.argName(i) == "mode") { current_mode = server.arg(i).toInt(); }      
    }

    Serial.print("MODE: ");
    Serial.println(current_mode);    
    server.send ( 200, "text/plain", message );

    setFullColor(color_red, color_green, color_blue);
  
  } );  

  server.onNotFound ( handleNotFound );
  server.begin();
  Serial.println ( "HTTP server started" );  

}

void loop()
{
  server.handleClient();   

  int pos=0;

    switch (current_mode)
    {
      case 0: // Manual RGB
        setFullColor(color_red, color_green, color_blue);        
      break;  
  
      case 1: // Random
        // random colored speckles that blink in and fade smoothly
        fadeToBlackBy( leds, NUM_LEDS, 10);
        pos = random16(NUM_LEDS);
        leds[pos]  = CHSV( gHue   random8(64), 200, 255);          
      break;  
  
      case 2: // Rainbow
          EVERY_N_MILLISECONDS( 20 ) { gHue  ; }
          fill_rainbow( leds, NUM_LEDS, gHue, 7);
      break;  
  
      case 3: // Lava
        // a colored dot sweeping back and forth, with fading trails
        fadeToBlackBy( leds, NUM_LEDS, 20);
        pos = beatsin16( 13, 0, NUM_LEDS-1 );
        leds[pos]  = CHSV( gHue, 255, 192);          
      break;              
    }

    // Update leds
    FastLED.show();
    FastLED.delay(1000 / 100); // 100 Hz   

}

Si te ha gustado el proyecto y montas una, no dudes en enviarnos unas fotos!