Cómo construir un controlador de tiras LED RGB usando ESP8266

Controlador de tiras LED RGB basado en ESP8266 IoT

En este proyecto vamos a montar un controlador de tiras de LEDs RGB basado en WiFi usando ESP8266 y Arduino IDE. Primero hacemos un controlador básico de LED RGB usando NodeMCU para así entender cómo controlar los colores de LED RGB usando PWM. Luego hacemos un pequeño controlador avanzado de tiras LED RGB con una interfaz de usuario de selección de colores fácil de usar como se muestra a continuación.

Antes de pasar directamente a la programación veamos el funcionamiento y los tipos de LED RGB.

¿Cómo funciona el LED RGB?

LED RGB significa la combinación de tres LEDs Rojo, Azul y Verde en un solo paquete. Los productos LED RGB combinan estos tres colores para producir más de 16 millones de colores de luz.

¿Cómo se hace la mezcla de colores en los LEDs RGB?

Un solo dado de LED sólo puede emitir luz monocromática que podría ser uno de los tres colores primarios – rojo, verde y azul, conocido como RGB. Para obtener más colores, se deben usar tres troqueles de LED juntos para la mezcla de colores RGB. Comúnmente se pueden producir 7 colores controlando el interruptor del canal para cada color primario. Para producir más de 7 colores, cada canal de color debe ser capaz de cambiar de brillo, no sólo de encenderse o apagarse. Un método de control popular es el PWM, del cual el rango de trabajo del ciclo determina los niveles de brillo disponibles. Cuanto más niveles estén disponibles, más colores se pueden producir. Aparte de la popularidad en aplicaciones como la iluminación de decoración exterior en las ciudades, diseños de iluminación de escenarios, iluminación de decoración del hogar y matriz de pantallas LED, la tecnología de mezcla de colores RGB también se puede encontrar recientemente en la retroiluminación de LCD y proyectores.

Controlador de mezcla de colores de LED RGB - Cómo construir un controlador de tiras LED RGB usando ESP8266

¿Cuáles son los tipos de LEDs RGB?

Los LEDs RGB están disponibles en diferentes tamaños, formas y potencia. La tira LED RGB es la más utilizada.

LED tricolor difuso de 5 mm

El LED tricolor de 5mm difuso con chips LED rojos, verdes y azules separados dentro de un paquete de 5mm se utiliza como indicador de estado, por ejemplo, puede mostrar el estado de la conectividad wifi. Tiene un ángulo de visión de 60 grados. Los LEDs RGB difusos mezclan el color dentro de un solo paquete de LEDs en vez de aparecer como 3 LEDs distintos como se muestra a continuación.

5 mm RGB LED - Cómo construir un controlador de tiras LED RGB usando ESP8266Están disponibles en dos tipos: de nodo común y de cátodo común, lo que significa que conectas una clavija a 5V o GND y luego atas las otras tres patas a tierra o a 5V a través de una resistencia. El más utilizado es el de nodo común más que el de CC porque los chips controladores de múltiples LEDs (como el TLC5940/TLC5941) a menudo están diseñados exclusivamente para CA y no se pueden utilizar con el cátodo común.

Especificaciones del LED RGB de 5mm

  • 5mm de diámetro
  • Rojo: Longitud de onda de 630 nm, Verde: 525 nm, Azul: 430 nm
  • Rojo: 2,1-2,5V de tensión de avance, a una corriente de 20mA, Verde: 3.8-4.5V, Azul: 3.8-4.5V
  • Rojo: 500 mcd de brillo típico, Verde: 600 mcd, Azul: 300 mcd

Conexiones de clavijas de LEDs RGB de 5mm:

5mm LED pin conexiones - Cómo construir un controlador de tiras LED RGB usando ESP8266

SMD RGB 5050 LED

SMD 5050 RGB LED - Cómo construir un controlador de tiras LED RGB usando ESP8266

Estos LEDs de superficie son una forma fácil de añadir un montón de puntos de colores a tu proyecto. Se usan comúnmente en las tiras de LEDs RGB, del mismo tamaño y forma. Tienen medio centímetro de lado, lo que los hace pequeños pero no tan pequeños como para que sea difícil de soldar a mano. Hay tres LEDs en el interior, rojo, verde y azul, y debido a que están tan cerca, se mezclan muy bien, sin necesidad de un difusor. El LED es brillante 3800mcd.

Conexiones PIN del LED RGB SMD 5050

conexiones PIN del SMD 5050 RGB LED - Cómo construir un controlador de tiras LED RGB usando ESP8266

 

Módulo LED RGB Arduino KY-016

Arduino KY 016 RGB LED modulo - Cómo construir un controlador de tiras LED RGB usando ESP8266

El módulo Led RGB consiste en 5mm RGB y resistencias limitadoras de corriente. Puedes controlar sus colores completos usando PWM.

Código de Arduino para el control de color del Led RGB

Este es un código de ejemplo para el control de color de un LED RGB usando PWM. Haz las conexiones del módulo a Arduino.

ArduinRGB LED Module
9R
10G
11B
+5V+
/*
KY016 RGB LED module
https://descubrearduino.com
PWM LED Color Generation
*/
int redpin = 9; // select the pin for the red LED
int greenpin = 10 ;// select the pin for the green LED
int bluepin = 11; // select the pin for the blue LED

int val;
void setup () {
  pinMode (redpin, OUTPUT);
  pinMode (bluepin, OUTPUT);
  pinMode (greenpin, OUTPUT);
}
void loop ()
{
  for (val = 255; val> 0; val --)
  {
    analogWrite (11, val);
    analogWrite (10, 255-val);
    analogWrite (9, 128-val);
    delay (15);
  }
  for (val = 0; val <255; val ++)
  {
    analogWrite (11, val);
    analogWrite (10, 255-val);
    analogWrite (9, 128-val);
    delay (15);
  }
}

Tira LED RGB

Estas tiras LED RGB vienen en dos tipos, una con LEDs RGB SMD 5050 y otra con WS2812 es una tira LED programable en la que puedes controlar cada color de LED. Tienen 30, 60, etc. LEDs RGB por metro.

Tiras RGB LED 5050

bobina leds - Cómo construir un controlador de tiras LED RGB usando ESP8266

Estos tipos de tiras de LED pueden controlar toda la tira de una vez con cualquier microcontrolador y tres transistores o ULN2003. La forma en que están cableadas, necesitará una fuente de alimentación de 12VDC y luego conectar a tierra los pines R/G/B para encender los tres colores. Utilice cualquier NPN o N-canal MOSFET y PWM las entradas para la mezcla de colores.

Viene con la opción a prueba de intemperie y sin recubrimiento con color de fondo blanco o negro. Hay una tira adhesiva 3M en la parte posterior que debería adherirse a la mayoría de las superficies lisas.

Puedes cortar estas tiras de LEDs muy fácilmente con cortaalambres, hay líneas de corte cada 10cm (3 LEDs cada una), y recortar la cubierta impermeable con un cuchillo. Vienen en rollos de 5 metros con un conector.

Tira LED RGB WS2812 (NeoPixel)

tira de leds neopixels - Cómo construir un controlador de tiras LED RGB usando ESP8266

Estas tiras flexibles de LED RGB son una forma fácil de añadir efectos de iluminación complejos a un proyecto. Cada LED tiene un controlador integrado (WS2812) que le permite controlar el color y el brillo de cada LED de forma independiente. El IC combinado de LED/driver de estas tiras es el extremadamente compacto WS2812B (esencialmente un driver de LED mejorado WS2811 integrado directamente en un LED RGB 5050), que permite mayores densidades de LED. En la imagen se pueden ver las conexiones de +5V, D0 (Datos) y GND solamente.

Este tipo de tiras de LED requiere un tipo especial de controlador. Puedes hacerlo usando Arduino o ESP8266.

controlador leds - Cómo construir un controlador de tiras LED RGB usando ESP8266

Controlador de LED RGB ESP8266

En este simple control de LEDs RGB sobre wifi, servidor web. vamos a entender claramente como se aplican los valores de color a los LEDs RGB

Conexiones del LED RGB con NodeMCU

El LED RGB es del tipo de cátodo común (GND), su terminal común se conecta al pin de GND de NodeMCU y las conexiones R, G, B se hacen con NodeMCU usando una resistencia de 220 Ohm en D6, D7 y D8.

diagrama conexiones leds a Nodemcu - Cómo construir un controlador de tiras LED RGB usando ESP8266

Código del controlador NodoMCU RGB LED para Arduino IDE

Antes de subir el código, introduce el SSID y la contraseña.

/*
 * IoT ESP8266 Based Mood Lamp (RGB LED) Controller Program
 * https://descubrearduino.com
 */
 
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

//SSID and Password of your WiFi router
const char* ssid = "Your SSID";
const char* password = "Your Password";

ESP8266WebServer server(80);

//LED Connections
const int RedLED=15;     //D8  GPIO15
const int GreenLED=12;  //D6  GPIO12
const int BlueLED=13;    //D7  GPIO13

String setcolor="#ff00ff"; //Set color for HTML

const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<head>
<title>Mood Lamp (RGB LED Color) Controller</title>
</head>
<body style="background:@@color@@;">

<center>
    Mood Lamp (RGB LED Color) Controller<br><br><br>
  <form method="post" action="/form">
      Color:
      <input type="color" name="color" value="@@color@@">
      <button type="submit" name="state" value="stop">SET</button>
  </form>
<br><br><br>
<a href="https://Descubrearduino.com">Descubrearduino.com</a><br>
</center>
</body>
</html>
)=====";

//=======================================================================
//                    handles main page
//=======================================================================
void handleRoot() {
  String p = MAIN_page;  
  p.replace("@@color@@",setcolor);    //Set page background color and selected color
  server.send(200, "text/html", p);    
}

//=======================================================================
//                    Handle Set Color
//=======================================================================
void handleForm() {
  String color = server.arg("color");
  //form?color=%23ff0000
  setcolor = color; //Store actual color set for updating in HTML
  Serial.println(color);

  //See what we have recived
  //We get #RRGGBB in hex string

  // Get rid of '#' and convert it to integer, Long as we have three 8-bit i.e. 24-bit values
  long number = (int) strtol( &color[1], NULL, 16);

  //Split them up into r, g, b values
  long r = number >> 16;
  long g = (number >> 8) & 0xFF;
  long b = number & 0xFF;
  
  //PWM Correction
  r = r * 4; 
  g = g * 4;
  b = b * 4;
//for ULN2003 or Common Cathode RGB LED not needed
/*
  r = 1024 - r;
  g = 1024 - g;
  b = 1024 - b;
*/
  //ESP supports analogWrite All IOs are PWM
  analogWrite(RedLED,r);
  analogWrite(GreenLED,g);
  analogWrite(BlueLED,b);

  server.sendHeader("Location", "/");
  server.send(302, "text/plain", "Updated-- Press Back Button");
 
  delay(500);  
}
//=======================================================================
//                    SETUP
//=======================================================================
void setup(){
  Serial.begin(115200);   //Start serial connection  
  
  pinMode(RedLED,OUTPUT);
  pinMode(GreenLED,OUTPUT);
  pinMode(BlueLED,OUTPUT);
  
    WiFi.begin(ssid, password);     //Connect to your WiFi router
  Serial.println("");
  
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  //If connection successful show IP address in serial monitor
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());  //IP address assigned to your ESP
  
  server.on("/", handleRoot);  //Associate handler function to path
  server.on("/form",handleForm);
    
  server.begin();                           //Start server
  Serial.println("HTTP server started");
}
//=======================================================================
//                    LOOP
//=======================================================================
void loop(){
  server.handleClient();
}

Resultados y pruebas

Después de subir el código, abre el monitor serial y obtén la dirección IP.

serial monitor datos - Cómo construir un controlador de tiras LED RGB usando ESP8266

Después de obtener la dirección IP, ábrela en el navegador web

controlador lampara de colores - Cómo construir un controlador de tiras LED RGB usando ESP8266

Selecciona el color y presione el botón de ajuste. Verás que el LED RGB también cambia de color según la selección.

Controlador de lámpara de colores con tira LED RGB y NodeMCU

Con esto estamos haciendo un completo controlador de tiras LED RGB con una interfaz de usuario genial como una lámpara de colores.

elección de colores led - Cómo construir un controlador de tiras LED RGB usando ESP8266

Conexiones de la tira LED RGB con NodeMCU

Para el conductor puedes usar MOSFET, transistores, ULN2003 o L293D.

conexiones leds a Nodemcu - Cómo construir un controlador de tiras LED RGB usando ESP8266

Código para el IDE de Arduino del NodeMCU RGB LED Strip Controller

El código se divide en dos partes: HTML y Código NodeMCU

main.ino

/*
 * IoT ESP8266 Based Mood Lamp (RGB LED) Controller Program
 * https://descubrearduino.com
 */
 
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

#include "index.h"

//SSID and Password of your WiFi router
const char* ssid = "Your SSID";
const char* password = "Your Password";

ESP8266WebServer server(80);

//LED Connections
const int BlueLED = 16; // D0
const int RedLED = 5;    // D1 
const int GreenLED = 4; // D2

//=======================================================================
//                    handles main page
//=======================================================================
void handleRoot() {
  Serial.println("Root Page Requested");
  server.send(200, "text/html", MAIN_page);
}

//=======================================================================
//                    Handle Set Color
//=======================================================================
void handleForm() {
  //Saperate Colors are sent through javascript
  String red = server.arg("r");
  String green = server.arg("g");
  String blue = server.arg("b");
  int r = red.toInt();
  int g = green.toInt();
  int b = blue.toInt();

  Serial.print("Red:");Serial.println(r);
  Serial.print("Green:");Serial.println(g);
  Serial.print("Blue:");Serial.println(b);
  
  //PWM Correction 8-bit to 10-bit
  r = r * 4; 
  g = g * 4;
  b = b * 4;

  //for ULN2003 or Common Cathode RGB Led not needed
  /*
  r = 1024 - r;
  g = 1024 - g;
  b = 1024 - b;
  */
  //ESP supports analogWrite All IOs are PWM
  analogWrite(RedLED,r);
  analogWrite(GreenLED,g);
  analogWrite(BlueLED,b);

  server.sendHeader("Location", "/");
  server.send(302, "text/plain", "Updated-- Press Back Button");
 
  delay(500);  
}
//=======================================================================
//                    SETUP
//=======================================================================
void setup(){
  Serial.begin(115200);   //Start serial connection  
  
  pinMode(RedLED,OUTPUT);
  pinMode(GreenLED,OUTPUT);
  pinMode(BlueLED,OUTPUT);
  
  WiFi.mode(WIFI_STA);
  
  WiFi.begin(ssid, password);     //Connect to your WiFi router
  Serial.println("");
  
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  //If connection successful show IP address in serial monitor
  Serial.println("");
  Serial.print("Connected to ");  
  Serial.println("WiFi");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());  //IP address assigned to your ESP
  
  server.on("/", handleRoot);  //Associate handler function to path
  server.on("/setRGB",handleForm);
    
  server.begin();                           //Start server
  Serial.println("HTTP server started");
}
//=======================================================================
//                    LOOP
//=======================================================================
void loop(){
  server.handleClient();
}

index.h

Este archivo es un poco más grande debido a javascript. Guárdalo como archivo de cabecera en el mismo lugar donde está el archivo ino.

Importante eliminar esta “—Keep only script tag” debido a la razón de seguridad de wordpress no permite la etiqueta de script

const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<head><title>descubrearduino.com | RGB LED Color Control</title>
<style>
.color-picker-container {
display: inline-block;
background: #00A8A9 none repeat scroll 0% 0%;
border-radius: 4px;
border: 2px solid #f8fafb;
}
.color-picker-container .picker-container .canvas-container {
margin: 20px;
position: relative;
float: left;
width: 200px;
display: inline-block;
background: #00A8A9;
}
.color-picker-container .picker-container .canvas-container.active {
display: block;
}
.color-picker-container .picker-container .canvas-container canvas {
cursor: crosshair;
border-radius: 50%;
box-shadow: 0 0 0 4px #E8E8E8;
background: #E6D3D3;
}
.color-picker-container .picker-container .canvas-container .pointer {
width: 15px;
height: 15px;
border: 2px solid #fff;
border-radius: 50%;
position: absolute;
pointer-events: none;
background: rgba(0, 0, 0, 0.1);
}
.color-picker-container .picker-container .canvas-container input {
margin-top: 10px;
width: 100%;
height: 30px;
text-align: center;
background: #353738;
border: 0;
color: #fff;
}
.color-picker-container .picker-container .slider-container {
width: 15px;
float: right;
position: relative;
margin: 15px;
}
.color-picker-container .picker-container .slider-container .slider {
width: 15px;
height: 249px;
background: #000;
}
.color-picker-container .picker-container .slider-container .pointer {
width: 0;
height: 0;
border-style: solid;
border-width: 5px 0 5px 10px;
border-color: transparent transparent transparent #ffffff;
position: absolute;
left: -8px;
}
.color-picker-container .palletes-container {
float: right;
width: 275px;
}
.color-picker-container .palletes-container .palette {
width: 35px;
height: 35px;
float: right;
border-radius: 4px;
margin: 5px;
box-shadow: inset 0px 2px 1px rgba(0, 0, 0, 0.28);
cursor: pointer;
}
.color-picker-container .palletes-container .palette.active {
box-shadow: 0 0 0 3px #3F3F40;
}
.color-picker-container .palletes-container .palette.add {
border: 2px dashed #bababa;
box-shadow: inherit;
position: relative;
}
.color-picker-container .palletes-container .palette.add:after {
content: '+';
font-size: 24px;
color: #bababa;
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
text-align: center;
line-height: 30px;
}

</style>
</head>
<body>
<div id="picker"></div>
<script---Keep only script tag>
var ColorPicker;

(function() {

function insertBefore(element, before) {
parent = before.parentNode;
parent.insertBefore(element, before);
}

function extend(defaults, options) {
var extended = {};
var prop;
for (prop in defaults) {
if (Object.prototype.hasOwnProperty.call(defaults, prop)) {
extended[prop] = defaults[prop];
}
}
for (prop in options) {
if (Object.prototype.hasOwnProperty.call(options, prop)) {
extended[prop] = options[prop];
}
}
return extended;
};

function hasClass(element, classname) {
var className = " " + classname + " ";
if ((" " + element.className + " ").replace(/[\n\t]/g, " ").indexOf(" " + classname + " ") > -1) {
return true;
}
return false;
}

function removeClass(node, className) {
node.className = node.className.replace(
new RegExp('(^|\\s+)' + className + '(\\s+|$)', 'g'),
'$1'
).replace(/ +(?= )/g, '').trim();
}

function addClass(element, className) {
if (!hasClass(element, className)) {
element.className += ' ' + className;
element.className = element.className.replace(/ +(?= )/g, '').trim()
}
}

ColorPicker = function(element, options) {

this.options = extend({
color: '#e7e7e7',
palettes: ['#646fff', '#fffa1d', '#ffa21f', '#ff391d'],
onUpdate: function() {}
}, options);

this.options.palettes.unshift(this.options.color);

this.hex = this.options.color;
this.rgb = this.HEXtoRGB(this.hex);
this.hsv = this.RGBtoHSV(this.rgb[0], this.rgb[1], this.rgb[2]);
this.dom = {};
this.dom.container = document.createElement('div');
this.dom.container.className = 'color-picker-container';

element.appendChild(this.dom.container);

this.initPicker();

this.initPalettes();
}

ColorPicker.prototype.initPicker = function() {

this.dom.picker = {};
this.dom.picker.container = document.createElement('div');
this.dom.picker.container.className = 'picker-container';

this.dom.container.appendChild(this.dom.picker.container);

this.dom.picker.canvas = {};

this.dom.picker.canvas.container = document.createElement('div');
this.dom.picker.canvas.container.className = 'canvas-container';
this.dom.picker.container.appendChild(this.dom.picker.canvas.container);

this.dom.picker.canvas.canvas = document.createElement('canvas');
this.dom.picker.canvas.canvas.className = 'canvas';

this.dom.picker.canvas.pointer = document.createElement('div');
this.dom.picker.canvas.pointer.className = 'pointer';

var ctx = this.dom.picker.canvas.canvas.getContext('2d'),
image = new Image,
$this = this,
dragging = false;

this.dom.picker.canvas.canvas.setAttribute('width', 200);
this.dom.picker.canvas.canvas.setAttribute('height', 200);
this.dom.picker.canvas.container.appendChild(this.dom.picker.canvas.canvas);
this.dom.picker.canvas.container.appendChild(this.dom.picker.canvas.pointer);

// image.src = 'images/wheel copy.png';
image.src = 'data:image/png;base64';

image.onload = function() {
$this.updateCanvasBounds();
ctx.drawImage(image, 0, 0, 200, 200);
$this.updateCoordinates($this.dom.picker.canvas.canvas.bounds.centerX, $this.dom.picker.canvas.canvas.bounds.centerY);
coordinates = $this.getPositionFromColor($this.hex);
if (coordinates != null) {
$this.x = coordinates.x;
$this.y = coordinates.y;
$this.updateColor($this.HEXtoRGB($this.hex));
$this.updateAll();
}
$this.options.onUpdate($this.rgb);
};

this.dom.picker.canvas.canvas.addEventListener('mousedown', function(e) {
e.preventDefault();
dragging = true;
$this.updateCoordinates(e.clientX, e.clientY);
imageData = ctx.getImageData($this.x, $this.y, 1, 1);
$this.updateColor(imageData.data);
$this.hsv[2] = 1;
$this.updateAll();
});

document.addEventListener('mousemove', function(e) { // mouse move handler
if (dragging) {
$this.updateCoordinates(e.pageX, e.pageY);
imageData = ctx.getImageData($this.x, $this.y, 1, 1);
$this.updateColor(imageData.data);
$this.hsv[2] = 1;
$this.updateAll();
}
});

document.addEventListener('mouseup', function(e) { // click event handler
dragging = false;
});

this.dom.picker.canvas.input = document.createElement('input'),

this.dom.picker.canvas.container.appendChild(this.dom.picker.canvas.input);

this.dom.picker.canvas.input.addEventListener('keyup', function() {
if(this.value == $this.hex || '#' + this.value == $this.hex){
return;
}
coordinates = $this.getPositionFromColor(this.value);
if (coordinates != null) {
$this.x = coordinates.x;
$this.y = coordinates.y;
$this.updateColor($this.HEXtoRGB(this.value));
$this.updateAll();
}
});

this.initSlider();

}

ColorPicker.prototype.initSlider = function() {

this.dom.slider = {};
this.dom.slider.container = document.createElement('div');
this.dom.slider.container.className = 'slider-container';

this.dom.slider.slider = document.createElement('div');
this.dom.slider.slider.className = 'slider';

this.dom.slider.pointer = document.createElement('div');
this.dom.slider.pointer.className = 'pointer';

this.dom.slider.container.appendChild(this.dom.slider.pointer);
this.dom.slider.container.appendChild(this.dom.slider.slider);
this.dom.picker.container.appendChild(this.dom.slider.container);

this.dom.slider.slider.bounds = this.dom.slider.slider.getBoundingClientRect();
this.dom.slider.pointer.bounds = this.dom.slider.pointer.getBoundingClientRect();

this.redrawSlider();

var dragging = false,
$this = this;

this.dom.slider.slider.addEventListener('mousedown', function(e) {
e.preventDefault();
dragging = true;
total = $this.updateSliderCursor(e.clientY);
$this.updateColor($this.HSVtoRGB($this.hsv[0], $this.hsv[1], 1 - total));
$this.updateAll();
});

this.dom.slider.pointer.addEventListener('mousedown', function(e) {
e.preventDefault();
dragging = true;
total = $this.updateSliderCursor(e.clientY);
$this.updateColor($this.HSVtoRGB($this.hsv[0], $this.hsv[1], 1 - total));
$this.updateAll();
});

document.addEventListener('mousemove', function(e) {
if (!dragging) {
return;
}
total = $this.updateSliderCursor(e.clientY);
$this.updateColor($this.HSVtoRGB($this.hsv[0], $this.hsv[1], 1 - total));
$this.updateAll();
});

document.addEventListener('mouseup', function() {
dragging = false;
});
};

ColorPicker.prototype.updateColor = function(pixel) {
this.hex = hex = this.RGBtoHEX(pixel[0], pixel[1], pixel[2]);
this.hsv = this.RGBtoHSV(pixel[0], pixel[1], pixel[2]);
this.rgb = [
pixel[0],
pixel[1],
pixel[2]
];
}

ColorPicker.prototype.updateCoordinates = function(x, y) {
var angle = Math.atan2((y - this.dom.picker.canvas.canvas.bounds.centerY), (x - this.dom.picker.canvas.canvas.bounds.centerX));
radius = Math.sqrt(Math.pow(x - this.dom.picker.canvas.canvas.bounds.centerX, 2) + Math.pow(y - this.dom.picker.canvas.canvas.bounds.centerY, 2));
if (radius > this.dom.picker.canvas.canvas.bounds.radius - (this.dom.picker.canvas.pointer.bounds.width / 2)) {
cos = Math.cos(angle);
sin = Math.sin(angle);
x = cos * (this.dom.picker.canvas.canvas.bounds.radius - (this.dom.picker.canvas.pointer.bounds.width / 2)) + this.dom.picker.canvas.canvas.bounds.centerX;
y = sin * (this.dom.picker.canvas.canvas.bounds.radius - (this.dom.picker.canvas.pointer.bounds.width / 2)) + this.dom.picker.canvas.canvas.bounds.centerY;
}
this.x = Math.floor(x - this.dom.picker.canvas.canvas.bounds.left);
this.y = Math.floor(y - this.dom.picker.canvas.canvas.bounds.top);
}

ColorPicker.prototype.initPalettes = function() {
this.dom.palettes = {};
this.dom.palettes.list = [];
this.dom.palettes.container = document.createElement('div');
addClass(this.dom.palettes.container, 'palletes-container');
this.dom.container.appendChild(this.dom.palettes.container);
this.dom.palettes.add = document.createElement('div');
addClass(this.dom.palettes.add, 'palette add');
this.dom.palettes.container.appendChild(this.dom.palettes.add);
var $this = this;
this.dom.palettes.add.addEventListener('click', function() {
addClass($this.dom.picker.canvas.container, 'active');
$this.updateCanvasBounds();
palette = $this.addPalette($this.RGBtoHEX($this.rgb[0], $this.rgb[1], $this.rgb[2]));
for (var i = 0; i < $this.dom.palettes.list.length; i++) {
removeClass($this.dom.palettes.list[i], 'active');
}
addClass(palette, 'active');
$this.selectedPalette = palette;
});
for (var i = 0; i < this.options.palettes.length; i++) {
this.addPalette(this.options.palettes[i]);
}
}

ColorPicker.prototype.addPalette = function(color) {
var palette = document.createElement('div');
palette.style.background = color;
palette.color = color;
var $this = this;
palette.addEventListener('click', function() {
for (var i = 0; i < $this.dom.palettes.list.length; i++) {
removeClass($this.dom.palettes.list[i], 'active');
}
addClass(this, 'active');
$this.selectedPalette = this;
rgb = $this.HEXtoRGB(this.color);
coordinates = $this.getPositionFromColor(color);
$this.x = coordinates.x;
$this.y = coordinates.y;
$this.updateColor(rgb);
$this.updateAll();
});
addClass(palette, 'palette');
insertBefore(palette, this.dom.palettes.add);
this.dom.palettes.list.push(palette);
return palette;
}

ColorPicker.prototype.updateAll = function() {
this.redrawSlider();
this.updatePointers();
this.dom.picker.canvas.input.value = this.hex;
this.options.onUpdate(this.rgb);
if (this.selectedPalette) {
this.selectedPalette.style.background = this.hex;
}
}
ColorPicker.prototype.getPositionFromColor = function(color) {
color = this.HEXtoRGB(color);
if (color == null) {
return null;
}
this.hsv = this.RGBtoHSV(color[0], color[1], color[2]);
return this.getSVGPositionFromHS(this.hsv[0], this.hsv[1]);
}

ColorPicker.prototype.updateSliderCursor = function(y) {
total = y - this.dom.slider.slider.bounds.top - 6;
total = this.dom.slider.slider.bounds.height - total;
total = total / this.dom.slider.slider.bounds.height;
total = total.toFixed(2);
if (total < 0) {
total = 0;
} else if (total > 1) {
total = 1;
}
total = 1 - total;
this.dom.slider.pointer.style.top = this.dom.slider.slider.bounds.height * total - (this.dom.slider.pointer.bounds.height / 2) + 'px';
return total;
}

ColorPicker.prototype.redrawSlider = function() {
rgb = this.HSVtoRGB(this.hsv[0], this.hsv[1], 1);
hex = this.RGBtoHEX(rgb[0], rgb[1], rgb[2]);
gradient = this.makeGradient(hex, '#000');
this.dom.slider.slider.setAttribute('style', gradient);
this.updatePointers();
};

ColorPicker.prototype.updatePointers = function() {
if (this.dom.picker.canvas.pointer.bounds) {
this.dom.picker.canvas.pointer.style.left = this.x - (this.dom.picker.canvas.pointer.bounds.width / 2) + 'px';
this.dom.picker.canvas.pointer.style.top = this.y - (this.dom.picker.canvas.pointer.bounds.height / 2) + 'px';
}
if (this.dom.slider.slider.bounds) {
position = this.dom.slider.slider.bounds.height * (1 - this.hsv[2]) - (this.dom.slider.pointer.bounds.height / 2);
this.dom.slider.pointer.style.top = position + 'px';
}
}

ColorPicker.prototype.updateCanvasBounds = function() {
this.dom.picker.canvas.canvas.bounds = this.dom.picker.canvas.canvas.getBoundingClientRect();
this.dom.picker.canvas.pointer.bounds = this.dom.picker.canvas.pointer.getBoundingClientRect();
this.dom.picker.canvas.canvas.bounds.centerX = this.dom.picker.canvas.canvas.bounds.left + (this.dom.picker.canvas.canvas.bounds.width / 2);
this.dom.picker.canvas.canvas.bounds.centerY = this.dom.picker.canvas.canvas.bounds.top + (this.dom.picker.canvas.canvas.bounds.height / 2);
this.dom.picker.canvas.canvas.bounds.radius = this.dom.picker.canvas.canvas.bounds.width / 2;
}
// https://codepen.io/benknight/pen/nADpy
// Get a coordinate pair from hue and saturation components.
ColorPicker.prototype.getSVGPositionFromHS = function(h, s) {
var hue = this.scientificToArtisticSmooth(h * 360);
var theta = hue * (Math.PI / 180);
var y = Math.sin(theta) * this.dom.picker.canvas.canvas.bounds.radius * s;
var x = Math.cos(theta) * this.dom.picker.canvas.canvas.bounds.radius * s;
return {
x: x + this.dom.picker.canvas.canvas.bounds.radius,
y: this.dom.picker.canvas.canvas.bounds.radius - y
}

};

//https://codepen.io/benknight/pen/nADpy
ColorPicker.prototype.scientificToArtisticSmooth = function(hue) {
return (
hue < 35 ? hue * (60 / 35) :
hue < 60 ? this.mapRange(hue, 35, 60, 60, 122) :
hue < 120 ? this.mapRange(hue, 60, 120, 122, 165) :
hue < 180 ? this.mapRange(hue, 120, 180, 165, 218) :
hue < 240 ? this.mapRange(hue, 180, 240, 218, 275) :
hue < 300 ? this.mapRange(hue, 240, 300, 275, 330) :
this.mapRange(hue, 300, 360, 330, 360));
}

//https://codepen.io/benknight/pen/nADpy
ColorPicker.prototype.mapRange = function(value, fromLower, fromUpper, toLower, toUpper) {
return (toLower + (value - fromLower) * ((toUpper - toLower) / (fromUpper - fromLower)));
}

//https://gist.github.com/Arahnoid/9923989
ColorPicker.prototype.HEXtoRGB = function(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? [
parseInt(result[1], 16),
parseInt(result[2], 16),
parseInt(result[3], 16)
] : null;
}

//http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
ColorPicker.prototype.RGBtoHSV = function(r, g, b) {
r = r / 255, g = g / 255, b = b / 255;
var max = Math.max(r, g, b),
min = Math.min(r, g, b);
var h, s, v = max;

var d = max - min;
s = max == 0 ? 0 : d / max;

if (max == min) {
h = 0; // achromatic
} else {
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return [h, s, v];
}

//http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
ColorPicker.prototype.HSVtoRGB = function(h, s, v) {
var r, g, b;
var i = Math.floor(h * 6);
var f = h * 6 - i;
var p = v * (1 - s);
var q = v * (1 - f * s);
var t = v * (1 - (1 - f) * s);
switch (i % 6) {
case 0:
r = v, g = t, b = p;
break;
case 1:
r = q, g = v, b = p;
break;
case 2:
r = p, g = v, b = t;
break;
case 3:
r = p, g = q, b = v;
break;
case 4:
r = t, g = p, b = v;
break;
case 5:
r = v, g = p, b = q;
break;
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}

//https://gist.github.com/Arahnoid/9923989
ColorPicker.prototype.RGBtoHEX = function(r, g, b) {
function componentToHex(c) {
var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}

//http://jsfiddle.net/barney/D9W4v/
ColorPicker.prototype.makeGradient = function(colour1, colour2) {
var gradientString = '\
/* Mozilla Firefox */ \
background-image: -moz-linear-gradient(top, {colour1} 0%, {colour2} 100%);\
/* Opera */ \
background-image: -o-linear-gradient(top, {colour1} 0%, {colour2} 100%);\
/* Webkit (Safari/Chrome 10) */ \
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, {colour1}), color-stop(1, {colour2}));\
/* Webkit (Chrome 11+) */ \
background-image: -webkit-linear-gradient(top, {colour1} 0%, {colour2} 100%);\
/* IE10+ */\
background: -ms-linear-gradient(top, {colour1} 0%,{colour2} 100%);\
/* W3C */\
background: linear-gradient(top, {colour1} 0%,{colour2} 100%);\
';

return gradientString.replace(/\{colour1\}/g, colour1).replace(/\{colour2\}/g, colour2)
};
}());

var picker = new ColorPicker(document.getElementById('picker'), {
onUpdate: function(rgb) {
document.body.style.background = "rgb(" + rgb[0] + ", " + rgb[1] + ", " + rgb[2] + ")";
changeColor(rgb[0],rgb[1],rgb[2]);
}
});

//setInterval(changeColor, 2000);

function changeColor(red, green, blue){
//Set RGB LED Color
console.log(red,green,blue);
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var txt = this.responseText;
}
};
xhttp.open("GET", "setRGB?r="+red+"&g="+green+"&b="+blue, true); //Handle readADC server on ESP8266
xhttp.send();
}
</script---Keep only script tag>
</body>
</html>
)=====";

Resultados y pruebas

Abre el monitor de serie, obten la dirección IP e introdúcela en el navegador web.

Hazlo funcionar y verás los cambios de color. A continuación se muestra la configuración de una prueba con NodeMCU y la tira de LED RGB.

prueba leds y nodemcu - Cómo construir un controlador de tiras LED RGB usando ESP8266

Pin It on Pinterest

Shares