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.
¿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.
Está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:
SMD RGB 5050 LED
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
Módulo LED RGB Arduino KY-016
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.
Arduin | RGB LED Module |
9 | R |
10 | G |
11 | B |
+5V | + |
/* KY016 RGB LED moduleArduino⭐️ Más de 1000 Proyectos y Tutoriales | Descubrearduino.comPWM 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
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)
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 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.
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.
Después de obtener la dirección IP, ábrela en el navegador web
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.
Conexiones de la tira LED RGB con NodeMCU
Para el conductor puedes usar MOSFET, transistores, ULN2003 o L293D.
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.
Debe estar conectado para enviar un comentario.