FastLED / Neopixel (ws2811) Node, From Arduino code to Web page (with API)
-
This is running Dev 1.6.0 , so beware. You will have to convert it to 1.5.0 if you aren't running crazy like me!
Edited: There was a bug in the code where it had an unroutable IP address along with a script hosted at Google. Fixed.
Arduino Neopixel Node code
//#define MY_DEBUG #define MY_RADIO_NRF24 #define MY_NODE_ID 9 #include <SPI.h> #include <MySensor.h> #include <Adafruit_NeoPixel.h> #include <avr/power.h> Adafruit_NeoPixel strip = Adafruit_NeoPixel(38, 3, NEO_GRB + NEO_KHZ800); unsigned int requestedMode = 0 ; unsigned int requestedSpeed = 0 ; unsigned int currentSpeed = 0 ; int messageType = 0 ; long hexColor = -1 ; unsigned long previousTime = 0 ; int j = 0 ; int q = 0 ; void setup() { Serial.begin(115200); strip.begin(); strip.show(); Serial.println("Neopixel Node device ready"); } void presentation() { sendSketchInfo("Neopixel Node", "1.0"); present(0, S_RGB_LIGHT, "Makes strip said color", true); } void loop() { switch (messageType) { case (1): Serial.print("Hex color override: "); Serial.println(hexColor); colorWipe(hexColor); messageType = 0 ; break; case (2): if ( (previousTime + (long) currentSpeed) < millis() ){ if (requestedMode == 2) { if (j > 256) { j = 0;} for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, Wheel((i+j) & 255)) ; strip.show(); } j++; if ( (j%255) == 0 ) { Serial.println("Rainbow completed, continuing");} } if (requestedMode == 3) { if (j > 256) { j = 0;} for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255)); strip.show(); } j = j + 5; if ( (j%255) == 0 ) { Serial.println("Rainbow cycle completed, continuing");} } if (requestedMode == 4) { if (j > 10) { j = 0;} if (q > 3) { q = 0;} for (int j=0; j<10; j++) { for (q=0; q < 3; q++) { for (int i=0; i < strip.numPixels(); i=i+3) { strip.setPixelColor(i+q, hexColor ); } strip.show(); delay(50); for (int i=0; i < strip.numPixels(); i=i+3) { strip.setPixelColor(i+q, 0); } } } } previousTime = millis(); } break; case (3): // Adjust timing of case 2 using non-blocking code (no DELAYs) Serial.print("Case 3 received. Speed set to: "); Serial.print(requestedSpeed * 10); Serial.println(" ms."); currentSpeed = requestedSpeed * 10; messageType = 2 ; break; } } void receive(const MyMessage &message) { Serial.println("Message received: "); if (message.type == V_RGB) { messageType = 1 ; String hexstring = message.getString(); Serial.print("RGB color: "); Serial.println(hexstring); hexColor = strtol( &hexstring[0], NULL, 16); } if (message.type == V_VAR1) { String junkString = message.getString(); Serial.println(junkString); requestedMode = junkString.charAt(0) - 48; messageType = 2 ; Serial.print("Neo mode: "); Serial.println(requestedMode); } if (message.type == V_VAR2) { // This line is for the speed of said mode String junkString = message.getString(); Serial.println(junkString); requestedSpeed = junkString.charAt(0) - 48; messageType = 3 ; Serial.print("Neo speed: "); Serial.println(requestedSpeed); } } //************* Neopixel subroutines, with DELAYs removed. *************** void rainbowCycle() { Serial.println("Rainbow Cycle loop"); uint16_t i, j; for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel for (i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));} strip.show(); } } void colorWipe(long number) { long r = hexColor >> 16; long g = hexColor >> 8 & 0xFF; long b = hexColor & 0xFF; for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, r,g,b); strip.show(); } } uint32_t Wheel(byte WheelPos) { WheelPos = 255 - WheelPos; if (WheelPos < 85) { return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); } else if (WheelPos < 170) { WheelPos -= 85; return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); } else { WheelPos -= 170; return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); } }
Node-Red Neopixel Node subroutine
[{"id":"5bb468f1.8ac468","type":"subflow","name":"Neopixel Node","info":"","in":[{"x":27,"y":212,"wires":[{"id":"b168409e.83cfa"}]}],"out":[{"x":721,"y":215,"wires":[{"id":"18fb6ecc.c732b9","port":0}]}]},{"id":"18fb6ecc.c732b9","type":"mysdecenc","z":"5bb468f1.8ac468","name":"","x":608,"y":214,"wires":[[]]},{"id":"d4cbf034.7f9f4","type":"mysencap","z":"5bb468f1.8ac468","name":"Solid RGB set","nodeid":"9","childid":0,"subtype":"40","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":453,"y":175,"wires":[["18fb6ecc.c732b9"]]},{"id":"f841fa59.3ad42","type":"mysencap","z":"5bb468f1.8ac468","name":"Mode Call","nodeid":"9","childid":0,"subtype":"24","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":446,"y":211,"wires":[["18fb6ecc.c732b9"]]},{"id":"43e75cfc.4fd6f4","type":"mysencap","z":"5bb468f1.8ac468","name":"Speed Call","nodeid":"9","childid":0,"subtype":"25","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":451,"y":248,"wires":[["18fb6ecc.c732b9"]]},{"id":"78baceb2.c1add","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":315,"y":174,"wires":[["d4cbf034.7f9f4"]]},{"id":"4aa5e51d.b8370c","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":318,"y":210,"wires":[["f841fa59.3ad42"]]},{"id":"fdfcef4c.e51f8","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":320,"y":247,"wires":[["43e75cfc.4fd6f4"]]},{"id":"b168409e.83cfa","type":"function","z":"5bb468f1.8ac468","name":"","func":"var hexcolor = msg.payload.hexcolor;\nvar mode = msg.payload.mode;\nvar speed = msg.payload.speed;\n\nif (hexcolor !== undefined ){ // Pass the hexcolor down the path\n msg.payload = hexcolor ;\n return [msg, null, null];\n}\n\nif (mode !== undefined ){ // Pass the pattern mode down the path\n msg.payload = mode ;\n return [null, msg, null];\n}\n\nif (speed !== undefined ){ // Pass the speed down the path\n msg.payload = speed ;\n return [null, null, msg];\n}","outputs":"3","noerr":0,"x":166,"y":211,"wires":[["78baceb2.c1add"],["4aa5e51d.b8370c"],["fdfcef4c.e51f8"]]},{"id":"e2669ab0.c9db9","type":"subflow:5bb468f1.8ac468","z":"395349b4.bbb1be","name":"","x":529,"y":263,"wires":[["d34e424a.c3ba6"]]}]
Node-Red Neopixel Web API
[{"id":"57fddc52.c8549c","type":"serial-port","z":"395349b4.bbb1be","serialport":"/dev/ttyUSB0","serialbaud":"115200","databits":"8","parity":"none","stopbits":"1","newline":"\\n","bin":"false","out":"char","addchar":false},{"id":"5bb468f1.8ac468","type":"subflow","name":"Neopixel Node","info":"","in":[{"x":27,"y":212,"wires":[{"id":"b168409e.83cfa"}]}],"out":[{"x":721,"y":215,"wires":[{"id":"18fb6ecc.c732b9","port":0}]}]},{"id":"18fb6ecc.c732b9","type":"mysdecenc","z":"5bb468f1.8ac468","name":"","x":608,"y":214,"wires":[[]]},{"id":"d4cbf034.7f9f4","type":"mysencap","z":"5bb468f1.8ac468","name":"Solid RGB set","nodeid":"9","childid":0,"subtype":"40","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":453,"y":175,"wires":[["18fb6ecc.c732b9"]]},{"id":"f841fa59.3ad42","type":"mysencap","z":"5bb468f1.8ac468","name":"Mode Call","nodeid":"9","childid":0,"subtype":"24","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":446,"y":211,"wires":[["18fb6ecc.c732b9"]]},{"id":"43e75cfc.4fd6f4","type":"mysencap","z":"5bb468f1.8ac468","name":"Speed Call","nodeid":"9","childid":0,"subtype":"25","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":451,"y":248,"wires":[["18fb6ecc.c732b9"]]},{"id":"78baceb2.c1add","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":315,"y":174,"wires":[["d4cbf034.7f9f4"]]},{"id":"4aa5e51d.b8370c","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":318,"y":210,"wires":[["f841fa59.3ad42"]]},{"id":"fdfcef4c.e51f8","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":320,"y":247,"wires":[["43e75cfc.4fd6f4"]]},{"id":"b168409e.83cfa","type":"function","z":"5bb468f1.8ac468","name":"","func":"var hexcolor = msg.payload.hexcolor;\nvar mode = msg.payload.mode;\nvar speed = msg.payload.speed;\n\nif (hexcolor !== undefined ){ // Pass the hexcolor down the path\n msg.payload = hexcolor ;\n return [msg, null, null];\n}\n\nif (mode !== undefined ){ // Pass the pattern mode down the path\n msg.payload = mode ;\n return [null, msg, null];\n}\n\nif (speed !== undefined ){ // Pass the speed down the path\n msg.payload = speed ;\n return [null, null, msg];\n}","outputs":"3","noerr":0,"x":166,"y":211,"wires":[["78baceb2.c1add"],["4aa5e51d.b8370c"],["fdfcef4c.e51f8"]]},{"id":"944f576d.f793c8","type":"http in","z":"395349b4.bbb1be","name":"","url":"/neopixel","method":"get","swaggerDoc":"","x":84,"y":182,"wires":[["f7981706.1d0b08"]]},{"id":"512f4e11.a571b8","type":"template","z":"395349b4.bbb1be","name":"Prints data ","field":"payload","format":"handlebars","template":"Hexcolor: {{payload.hexcolor}} \nMode: {{payload.mode}} \nSpeed: {{payload.speed}}","x":528,"y":164,"wires":[["98fabd8f.db8f8"]]},{"id":"e2669ab0.c9db9","type":"subflow:5bb468f1.8ac468","z":"395349b4.bbb1be","name":"","x":529,"y":263,"wires":[["d34e424a.c3ba6"]]},{"id":"98fabd8f.db8f8","type":"http response","z":"395349b4.bbb1be","name":"","x":731,"y":164,"wires":[]},{"id":"2e9eb2d7.d49bfe","type":"debug","z":"395349b4.bbb1be","name":"","active":true,"console":"false","complete":"false","x":536,"y":73,"wires":[]},{"id":"5b91c6df.ea9e18","type":"http in","z":"395349b4.bbb1be","name":"","url":"/neopixel","method":"post","swaggerDoc":"","x":82,"y":145,"wires":[["f7981706.1d0b08"]]},{"id":"9c565a2d.52db08","type":"comment","z":"395349b4.bbb1be","name":"Valid commands ~readme~","info":"hexcolor:000000~ffffff\n First 2 are red, second 2 are green, last 2 are blue. \n Just like standard HTML hexcolors without #\nmode:2~4\n 2 is slow rainbow\n 3 is fast rainbow\n 4 is theater chase. Must set a hexcolor before doing this\nspeed:0~9\n 0 is fastest, as 0 ms (0*10 ms) per loop\n 9 is slowest, as 90 ms (9*10 ms) per loop","x":124,"y":266,"wires":[]},{"id":"d34e424a.c3ba6","type":"serial out","z":"395349b4.bbb1be","name":"","serial":"57fddc52.c8549c","x":743,"y":263,"wires":[]},{"id":"f7981706.1d0b08","type":"function","z":"395349b4.bbb1be","name":"Combine Post/Get","func":"return msg;","outputs":1,"noerr":0,"x":298,"y":163,"wires":[["2e9eb2d7.d49bfe","512f4e11.a571b8","e2669ab0.c9db9"]]}]
Node-Red Neopixel Web interface
[{"id":"9d9299f7.ff826","type":"http in","z":"163c57ed.326588","name":"","url":"/index.html","method":"get","swaggerDoc":"","x":173,"y":84,"wires":[["8b6f494e.e388b8"]]},{"id":"8b6f494e.e388b8","type":"template","z":"163c57ed.326588","name":"index.html","field":"payload","format":"html","template":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\" />\n\t<title>Neopixel MySensors Configuration</title>\n\t<script src=\"/jquery.min.js\"></script>\n\t\n\t<script type=\"text/javascript\">\n $(document).ready(function(){\n $(\"button[name='rainbow']\").click(function(){ $.post(\"/neopixel\",{ mode: \"2\"}, function() {} ); });\n });\n </script>\n \n <script type=\"text/javascript\">\n $(document).ready(function(){\n $(\"button[name='fastrainbow']\").click(function(){ $.post(\"/neopixel\",{ mode: \"3\"}, function() {} ); });\n });\n </script>\n \n <script type=\"text/javascript\">\n $(document).ready(function(){\n $(\"button[name='chase']\").click(function(){ $.post(\"/neopixel\",{ mode: \"4\"}, function() {} ); });\n });\n </script>\n \n \n\n</head>\n<body>\n\n<div align=\"center\">\n<canvas width=\"550\" height=\"450\" id=\"canvas_picker\"></canvas>\n<div id=\"hex\">HEX: <input type=\"text\"></input></div>\n\n<button name=\"rainbow\">Rainbow</button>\n<button name=\"fastrainbow\">Fast Rainbow</button>\n<button name=\"chase\">Chase</button><br><br>\n0 (fast) <input type=\"range\" min=\"0\" max=\"10\" onchange=\"emitValue(this.value)\"/> (slow) 10\n</div>\n\n<script type=\"text/javascript\">\n\tvar canvas = document.getElementById('canvas_picker').getContext('2d');\n\n\t// create an image object and get it’s source\n\tvar img = new Image();\n\timg.src = '/colorwheel3.png';\n\n\t// copy the image to the canvas\n\t$(img).load(function(){ canvas.drawImage(img,0,0); });\n\n\t// http://www.javascripter.net/faq/rgbtohex.htm\n\tfunction rgbToHex(R,G,B) {return toHex(R)+toHex(G)+toHex(B)}\n\tfunction toHex(n) {\n\t n = parseInt(n,10);\n\t if (isNaN(n)) return \"00\";\n\t n = Math.max(0,Math.min(n,255));\n\t return \"0123456789ABCDEF\".charAt((n-n%16)/16) + \"0123456789ABCDEF\".charAt(n%16);\n\t}\n\t$('#canvas_picker').click(function(event){\n\t // getting user coordinates\n\t var x = event.pageX - this.offsetLeft;\n\t var y = event.pageY - this.offsetTop;\n\t // getting image data and RGB values\n\t var img_data = canvas.getImageData(x, y, 1, 1).data;\n\t var R = img_data[0];\n\t var G = img_data[1];\n\t var B = img_data[2]; var rgb = R + ',' + G + ',' + B;\n\t // convert RGB to HEX\n\t var hex = rgbToHex(R,G,B);\n\t // making the color the value of the input\n\t $('#rgb input').val(rgb);\n\t $('#hex input').val(hex);\n\t $.post( \"/neopixel\", { hexcolor: hex } ); }\n\t );\n</script>\n\n<script type=\"text/javascript\">\nfunction emitValue(newValue)\n { $.post(\"/neopixel\",{ speed: newValue}, function() {} ); }\n</script>\n\n\n</body>\n</html>","x":373,"y":82,"wires":[["bf09f135.39cec8"]]},{"id":"fa066d3a.ea6ff8","type":"http in","z":"163c57ed.326588","name":"","url":"/colorwheel3.png","method":"get","swaggerDoc":"","x":153,"y":134,"wires":[["eafd1d33.cc13b8"]]},{"id":"eafd1d33.cc13b8","type":"file in","z":"163c57ed.326588","name":"","filename":"/home/josh/colorwheel3.png","format":"","x":388,"y":134,"wires":[["bf09f135.39cec8"]]},{"id":"bf09f135.39cec8","type":"http response","z":"163c57ed.326588","name":"","x":638,"y":103,"wires":[]},{"id":"5e929b72.ba9364","type":"http in","z":"163c57ed.326588","name":"","url":"/jquery.min.js","method":"get","swaggerDoc":"","x":175,"y":186,"wires":[["521c39b0.344748"]]},{"id":"521c39b0.344748","type":"file in","z":"163c57ed.326588","name":"","filename":"/home/josh/jquery.min.js","format":"","x":397,"y":184,"wires":[["bf09f135.39cec8"]]}]
Location for the jquery.min.js : https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js
Image for Color-Wheel:
Results:
-
I am looking at an Arduino code rewrite using FastLED. But for right now, this works and works well.
I think I might have found a bug in the 1.6.0 beta MySensors. I need to confirm it's not my coding, but because of that, expect Speed call to change internally. Ideally, the API will stay the same, or be added to.
I will replicate with my ServoActuator to see if it's my coding or the beta.
-
FastLED Arduino sketch is done, along with appropriate Node-red subflow and website.
And it was surprisingly easy! FastLED is a cinch to work with
I'll probably call it ws2811 (Neopixel/FastLED) Node
Arduino code:
//#define MY_DEBUG #define MY_RADIO_NRF24 #define MY_NODE_ID 9 #include <SPI.h> #include <MySensor.h> #include "FastLED.h" FASTLED_USING_NAMESPACE #if defined(FASTLED_VERSION) && (FASTLED_VERSION < 3001000) #warning "Requires FastLED 3.1 or later; check github for latest code." #endif #define DATA_PIN 3 //#define CLK_PIN 4 #define LED_TYPE WS2811 #define COLOR_ORDER GRB #define NUM_LEDS 38 CRGB leds[NUM_LEDS]; uint8_t gHue = 0; unsigned int currentSpeed = 0 ; int brightness = 96; unsigned int requestedMode = 0 ; int messageType = 0 ; int previousMessageType = -1; String hexColor = "000000" ; unsigned long previousTime = 0 ; void setup() { delay(1000); Serial.begin(115200); FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); FastLED.setBrightness(brightness); FastLED.show(); } void presentation() { sendSketchInfo("FastLED Node", "1.0"); present(0, S_RGB_LIGHT, "Makes strip said color", true); } void loop() { switch (messageType) { //************** CASE 1 ************** case (1): Serial.print("Hex color override: "); Serial.println(hexColor); colorWipe(); messageType = 0 ; break; //************** CASE 2 ************** case (2): if ( (previousTime + (long) currentSpeed ) < millis() ) { if (requestedMode == 2) {rainbow(); FastLED.show(); } if (requestedMode == 3) {rainbowWithGlitter();FastLED.show(); } if (requestedMode == 4) {addGlitter(80);FastLED.show(); } if (requestedMode == 5) {confetti();FastLED.show(); } if (requestedMode == 6) {sinelon();FastLED.show(); } if (requestedMode == 7) {bpm();FastLED.show(); } if (requestedMode == 8) {juggle();FastLED.show(); } previousTime = millis(); } break; //************** CASE 3 ************** case (3): // Adjust timing of case 2 using non-blocking code (no DELAYs) Serial.print("Case 3 received. Speed set to: "); Serial.print(currentSpeed); Serial.println(" ms."); messageType = 2; break; //************** CASE 4 ************** case (4): // Adjust brightness of whole strip of case 2 using non-blocking code (no DELAYs) Serial.print("Case 4 received. Brightness set to: "); Serial.println(brightness); FastLED.setBrightness(brightness); FastLED.show(); messageType = previousMessageType ; // We get off type 4 ASAP break; } } void receive(const MyMessage &message) { Serial.println("Message received: "); if (message.type == V_RGB) { messageType = 1 ; hexColor = message.getString(); Serial.print("RGB color: "); Serial.println(hexColor); } if (message.type == V_VAR1) { requestedMode = message.getInt(); Serial.println(requestedMode); messageType = 2 ; Serial.print("Neo mode: "); Serial.println(requestedMode); } if (message.type == V_VAR2) { // This line is for the speed of said mode currentSpeed = message.getInt() ; Serial.println(currentSpeed); messageType = 3 ; Serial.print("Neo speed: "); Serial.println(currentSpeed); } if (message.type == V_VAR3) { // This line is for the brightness of said mode brightness = message.getInt() ; //if(brightness > 255) {brightness = 255;} //if(brightness < 0) {brightness = 0;} Serial.println(brightness); previousMessageType = messageType; messageType = 4 ; Serial.print("Neo brightness: "); Serial.println(brightness); } } //********************** FastLED FUNCTIONS *********************** void colorWipe() { for (int i = 0; i < NUM_LEDS ; i++) { leds[i] = strtol( &hexColor[0], NULL, 16); FastLED.show(); } } void rainbow() { // FastLED's built-in rainbow generator fill_rainbow( leds, NUM_LEDS, gHue++, 7); } void rainbowWithGlitter() { // built-in FastLED rainbow, plus some random sparkly glitter fill_rainbow( leds, NUM_LEDS, gHue++, 7); FastLED.show(); addGlitter(80); } void addGlitter( fract8 chanceOfGlitter) { if ( random8() < chanceOfGlitter) { leds[ random16(NUM_LEDS) ] += CRGB::White; } } void confetti() { // random colored speckles that blink in and fade smoothly fadeToBlackBy( leds, NUM_LEDS, 10); int pos = random16(NUM_LEDS); leds[pos] += CHSV( gHue + random8(64), 200, 255); } void sinelon() { // a colored dot sweeping back and forth, with fading trails fadeToBlackBy( leds, NUM_LEDS, 20); int pos = beatsin16(13, 0, NUM_LEDS); leds[pos] += CHSV( gHue, 255, 192); } void bpm() { // colored stripes pulsing at a defined Beats-Per-Minute (BPM) uint8_t BeatsPerMinute = 62; CRGBPalette16 palette = PartyColors_p; uint8_t beat = beatsin8( BeatsPerMinute, 64, 255); for ( int i = 0; i < NUM_LEDS; i++) { //9948 leds[i] = ColorFromPalette(palette, gHue + (i * 2), beat - gHue + (i * 10)); } } void juggle() { // eight colored dots, weaving in and out of sync with each other fadeToBlackBy( leds, NUM_LEDS, 20); byte dothue = 0; for ( int i = 0; i < 8; i++) { leds[beatsin16(i + 7, 0, NUM_LEDS)] |= CHSV(dothue, 200, 255); dothue += 32; } }
FastLED Node subflow:
[{"id":"5bb468f1.8ac468","type":"subflow","name":"Neopixel Node","info":"","in":[{"x":67,"y":225,"wires":[{"id":"b168409e.83cfa"}]}],"out":[{"x":731,"y":237,"wires":[{"id":"18fb6ecc.c732b9","port":0}]}]},{"id":"18fb6ecc.c732b9","type":"mysdecenc","z":"5bb468f1.8ac468","name":"","x":627,"y":237,"wires":[[]]},{"id":"d4cbf034.7f9f4","type":"mysencap","z":"5bb468f1.8ac468","name":"Solid RGB set","nodeid":"9","childid":0,"subtype":"40","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":453,"y":175,"wires":[["18fb6ecc.c732b9"]]},{"id":"f841fa59.3ad42","type":"mysencap","z":"5bb468f1.8ac468","name":"Mode Call","nodeid":"9","childid":0,"subtype":"24","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":446,"y":211,"wires":[["18fb6ecc.c732b9"]]},{"id":"43e75cfc.4fd6f4","type":"mysencap","z":"5bb468f1.8ac468","name":"Speed Call","nodeid":"9","childid":0,"subtype":"25","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":451,"y":248,"wires":[["18fb6ecc.c732b9"]]},{"id":"78baceb2.c1add","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":302,"y":174,"wires":[["d4cbf034.7f9f4"]]},{"id":"4aa5e51d.b8370c","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":305,"y":210,"wires":[["f841fa59.3ad42"]]},{"id":"fdfcef4c.e51f8","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":307,"y":247,"wires":[["43e75cfc.4fd6f4"]]},{"id":"b168409e.83cfa","type":"function","z":"5bb468f1.8ac468","name":"","func":"var hexcolor = msg.payload.hexcolor;\nvar mode = msg.payload.mode;\nvar speed = msg.payload.speed;\nvar brightness = msg.payload.brightness;\n\nif (hexcolor !== undefined ){ // Pass the hexcolor down the path\n msg.payload = hexcolor ;\n return [msg, null, null, null];\n}\n\nif (mode !== undefined ){ // Pass the pattern mode down the path\n msg.payload = mode ;\n return [null, msg, null, null];\n}\n\nif (speed !== undefined ){ // Pass the speed down the path\n msg.payload = speed ;\n return [null, null, msg, null];\n}\n\nif (brightness !== undefined ){ // Pass the speed down the path\n msg.payload = brightness ;\n return [null, null, null, msg];\n}","outputs":"4","noerr":0,"x":155,"y":225,"wires":[["78baceb2.c1add"],["4aa5e51d.b8370c"],["fdfcef4c.e51f8"],["9eae602d.d13d88"]]},{"id":"842664d8.6ea65","type":"mysencap","z":"5bb468f1.8ac468","name":"Brightness Call","nodeid":"9","childid":0,"subtype":"26","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":455,"y":288,"wires":[["18fb6ecc.c732b9"]]},{"id":"9eae602d.d13d88","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":305,"y":285,"wires":[["842664d8.6ea65"]]},{"id":"e2669ab0.c9db9","type":"subflow:5bb468f1.8ac468","z":"395349b4.bbb1be","name":"","x":529,"y":263,"wires":[["d34e424a.c3ba6"]]}]
FastLED Node Web API
[{"id":"57fddc52.c8549c","type":"serial-port","z":"395349b4.bbb1be","serialport":"/dev/ttyUSB0","serialbaud":"115200","databits":"8","parity":"none","stopbits":"1","newline":"\\n","bin":"false","out":"char","addchar":false},{"id":"5bb468f1.8ac468","type":"subflow","name":"Neopixel Node","info":"","in":[{"x":67,"y":225,"wires":[{"id":"b168409e.83cfa"}]}],"out":[{"x":731,"y":237,"wires":[{"id":"18fb6ecc.c732b9","port":0}]}]},{"id":"18fb6ecc.c732b9","type":"mysdecenc","z":"5bb468f1.8ac468","name":"","x":627,"y":237,"wires":[[]]},{"id":"d4cbf034.7f9f4","type":"mysencap","z":"5bb468f1.8ac468","name":"Solid RGB set","nodeid":"9","childid":0,"subtype":"40","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":453,"y":175,"wires":[["18fb6ecc.c732b9"]]},{"id":"f841fa59.3ad42","type":"mysencap","z":"5bb468f1.8ac468","name":"Mode Call","nodeid":"9","childid":0,"subtype":"24","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":446,"y":211,"wires":[["18fb6ecc.c732b9"]]},{"id":"43e75cfc.4fd6f4","type":"mysencap","z":"5bb468f1.8ac468","name":"Speed Call","nodeid":"9","childid":0,"subtype":"25","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":451,"y":248,"wires":[["18fb6ecc.c732b9"]]},{"id":"78baceb2.c1add","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":302,"y":174,"wires":[["d4cbf034.7f9f4"]]},{"id":"4aa5e51d.b8370c","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":305,"y":210,"wires":[["f841fa59.3ad42"]]},{"id":"fdfcef4c.e51f8","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":307,"y":247,"wires":[["43e75cfc.4fd6f4"]]},{"id":"b168409e.83cfa","type":"function","z":"5bb468f1.8ac468","name":"","func":"var hexcolor = msg.payload.hexcolor;\nvar mode = msg.payload.mode;\nvar speed = msg.payload.speed;\nvar brightness = msg.payload.brightness;\n\nif (hexcolor !== undefined ){ // Pass the hexcolor down the path\n msg.payload = hexcolor ;\n return [msg, null, null, null];\n}\n\nif (mode !== undefined ){ // Pass the pattern mode down the path\n msg.payload = mode ;\n return [null, msg, null, null];\n}\n\nif (speed !== undefined ){ // Pass the speed down the path\n msg.payload = speed ;\n return [null, null, msg, null];\n}\n\nif (brightness !== undefined ){ // Pass the speed down the path\n msg.payload = brightness ;\n return [null, null, null, msg];\n}","outputs":"4","noerr":0,"x":155,"y":225,"wires":[["78baceb2.c1add"],["4aa5e51d.b8370c"],["fdfcef4c.e51f8"],["9eae602d.d13d88"]]},{"id":"842664d8.6ea65","type":"mysencap","z":"5bb468f1.8ac468","name":"Brightness Call","nodeid":"9","childid":0,"subtype":"26","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":455,"y":288,"wires":[["18fb6ecc.c732b9"]]},{"id":"9eae602d.d13d88","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":305,"y":285,"wires":[["842664d8.6ea65"]]},{"id":"944f576d.f793c8","type":"http in","z":"395349b4.bbb1be","name":"","url":"/neopixel","method":"get","swaggerDoc":"","x":84,"y":182,"wires":[["f7981706.1d0b08"]]},{"id":"512f4e11.a571b8","type":"template","z":"395349b4.bbb1be","name":"Prints data ","field":"payload","format":"handlebars","template":"Hexcolor: {{payload.hexcolor}} \nMode: {{payload.mode}} \nSpeed: {{payload.speed}}","x":528,"y":164,"wires":[["98fabd8f.db8f8"]]},{"id":"e2669ab0.c9db9","type":"subflow:5bb468f1.8ac468","z":"395349b4.bbb1be","name":"","x":529,"y":263,"wires":[["d34e424a.c3ba6"]]},{"id":"98fabd8f.db8f8","type":"http response","z":"395349b4.bbb1be","name":"","x":731,"y":164,"wires":[]},{"id":"2e9eb2d7.d49bfe","type":"debug","z":"395349b4.bbb1be","name":"","active":true,"console":"false","complete":"false","x":536,"y":73,"wires":[]},{"id":"5b91c6df.ea9e18","type":"http in","z":"395349b4.bbb1be","name":"","url":"/neopixel","method":"post","swaggerDoc":"","x":82,"y":145,"wires":[["f7981706.1d0b08"]]},{"id":"9c565a2d.52db08","type":"comment","z":"395349b4.bbb1be","name":"Valid commands ~readme~","info":"hexcolor:000000~ffffff\n First 2 are red, second 2 are green, last 2 are blue. \n Just like standard HTML hexcolors without #\nmode:2~4\n 2 is rainbow\n 3 is glitter rainbow rainbow\n 4 is glitter. kind of boring\n 5 is confetti\n 6 is Cylon tracers\n 7 is a Beats per minute. currently staticly set to 62bpm in code\n 8 is juggle\nspeed:0~9\n Number is milliseconds since last time.\n 0ms is little delay as possible\n 200ms is max for website but can go longer (why?)","x":124,"y":266,"wires":[]},{"id":"d34e424a.c3ba6","type":"serial out","z":"395349b4.bbb1be","name":"","serial":"57fddc52.c8549c","x":743,"y":263,"wires":[]},{"id":"f7981706.1d0b08","type":"function","z":"395349b4.bbb1be","name":"Combine Post/Get","func":"return msg;","outputs":1,"noerr":0,"x":298,"y":163,"wires":[["2e9eb2d7.d49bfe","512f4e11.a571b8","e2669ab0.c9db9"]]}]
FastLED Node Webpage
[{"id":"9d9299f7.ff826","type":"http in","z":"163c57ed.326588","name":"","url":"/index.html","method":"get","swaggerDoc":"","x":173,"y":84,"wires":[["8b6f494e.e388b8"]]},{"id":"8b6f494e.e388b8","type":"template","z":"163c57ed.326588","name":"index.html","field":"payload","format":"html","template":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\" />\n\t<title>Neopixel MySensors Configuration</title>\n\t<script src=\"/jquery.min.js\"></script>\n\t\n\t<script type=\"text/javascript\">\n $(document).ready(function(){\n $(\"button[name='rainbow']\").click(function(){ $.post(\"/neopixel\",{ mode: \"2\"}, function() {} ); });\n });\n </script>\n \n <script type=\"text/javascript\">\n $(document).ready(function(){\n $(\"button[name='glitterrainbow']\").click(function(){ $.post(\"/neopixel\",{ mode: \"3\"}, function() {} ); });\n });\n </script>\n \n <script type=\"text/javascript\">\n $(document).ready(function(){\n $(\"button[name='glitter']\").click(function(){ $.post(\"/neopixel\",{ mode: \"4\"}, function() {} ); });\n });\n </script>\n \n <script type=\"text/javascript\">\n $(document).ready(function(){\n $(\"button[name='confetti']\").click(function(){ $.post(\"/neopixel\",{ mode: \"5\"}, function() {} ); });\n });\n </script>\n \n <script type=\"text/javascript\">\n $(document).ready(function(){\n $(\"button[name='cylon']\").click(function(){ $.post(\"/neopixel\",{ mode: \"6\"}, function() {} ); });\n });\n </script>\n \n <script type=\"text/javascript\">\n $(document).ready(function(){\n $(\"button[name='bpm']\").click(function(){ $.post(\"/neopixel\",{ mode: \"7\"}, function() {} ); });\n });\n </script>\n \n <script type=\"text/javascript\">\n $(document).ready(function(){\n $(\"button[name='juggle']\").click(function(){ $.post(\"/neopixel\",{ mode: \"8\"}, function() {} ); });\n });\n </script>\n \n \n\n</head>\n<body>\n\n<div align=\"center\">\n<canvas width=\"850\" height=\"450\" id=\"canvas_picker\"></canvas>\n<div id=\"hex\">HEX: <input type=\"text\"></input></div>\n\n<button name=\"rainbow\">Rainbow</button>\n<button name=\"glitterrainbow\">Glitter Rainbow</button>\n<button name=\"glitter\">Glitter</button>\n<button name=\"confetti\">Confetti</button>\n<button name=\"cylon\">Cylon</button>\n<button name=\"bpm\">BPM</button>\n<button name=\"juggle\">Juggle</button>\n\n<br><br>\n0 ms. <input type=\"range\" min=\"0\" max=\"200\" onchange=\"emitSpeed(this.value)\"/> 200 ms.<br>\n0 <input type=\"range\" min=\"0\" max=\"255\" onchange=\"emitBrightness(this.value)\"/> 255\n</div>\n\n<script type=\"text/javascript\">\n\tvar canvas = document.getElementById('canvas_picker').getContext('2d');\n\n\t// create an image object and get it’s source\n\tvar img = new Image();\n\timg.src = '/colorwheel3.png';\n\n\t// copy the image to the canvas\n\t$(img).load(function(){ canvas.drawImage(img,0,0); });\n\n\t// http://www.javascripter.net/faq/rgbtohex.htm\n\tfunction rgbToHex(R,G,B) {return toHex(R)+toHex(G)+toHex(B)}\n\tfunction toHex(n) {\n\t n = parseInt(n,10);\n\t if (isNaN(n)) return \"00\";\n\t n = Math.max(0,Math.min(n,255));\n\t return \"0123456789ABCDEF\".charAt((n-n%16)/16) + \"0123456789ABCDEF\".charAt(n%16);\n\t}\n\t$('#canvas_picker').click(function(event){\n\t // getting user coordinates\n\t var x = event.pageX - this.offsetLeft;\n\t var y = event.pageY - this.offsetTop;\n\t // getting image data and RGB values\n\t var img_data = canvas.getImageData(x, y, 1, 1).data;\n\t var R = img_data[0];\n\t var G = img_data[1];\n\t var B = img_data[2]; var rgb = R + ',' + G + ',' + B;\n\t // convert RGB to HEX\n\t var hex = rgbToHex(R,G,B);\n\t // making the color the value of the input\n\t $('#rgb input').val(rgb);\n\t $('#hex input').val(hex);\n\t $.post( \"/neopixel\", { hexcolor: hex } ); }\n\t );\n</script>\n\n<script type=\"text/javascript\">\nfunction emitSpeed(fast)\n { $.post(\"/neopixel\",{ speed: fast}, function() {} ); }\n</script>\n\n<script type=\"text/javascript\">\nfunction emitBrightness(bright)\n { $.post(\"/neopixel\",{ brightness: bright}, function() {} ); }\n</script>\n\n\n</body>\n</html>","x":373,"y":82,"wires":[["bf09f135.39cec8"]]},{"id":"fa066d3a.ea6ff8","type":"http in","z":"163c57ed.326588","name":"","url":"/colorwheel3.png","method":"get","swaggerDoc":"","x":153,"y":134,"wires":[["eafd1d33.cc13b8"]]},{"id":"eafd1d33.cc13b8","type":"file in","z":"163c57ed.326588","name":"","filename":"/home/josh/colorwheel3.png","format":"","x":388,"y":134,"wires":[["bf09f135.39cec8"]]},{"id":"bf09f135.39cec8","type":"http response","z":"163c57ed.326588","name":"","x":638,"y":103,"wires":[]},{"id":"5e929b72.ba9364","type":"http in","z":"163c57ed.326588","name":"","url":"/jquery.min.js","method":"get","swaggerDoc":"","x":175,"y":186,"wires":[["521c39b0.344748"]]},{"id":"521c39b0.344748","type":"file in","z":"163c57ed.326588","name":"","filename":"/home/josh/jquery.min.js","format":"","x":397,"y":184,"wires":[["bf09f135.39cec8"]]}]
-
@cranky said:
1.6.0 beta MySensors
Hi,
Definitly want to try it.
I have some ws2801 ledstrip left, can it work with ?
Where to get 1.6 Mysensors lib ? got to much error to post them here with dev branch lib.
-
1.6 is the dev branch. It will likely not be released as 1.6 though, it seems more likely that it will be called 2.0.
-
I can change it back to a 1.5.* code. It'll be a day or so, as I'm busy right now (homework, etc).
-
Hello,
I know this is an old post.
But i am trying the script getting to work in combination with Domoticz.
A did a little rebuild to 2.1.0, and i am getting a RGD light which i can switch to dimmable in Domoticz.
I can select color and dim the strip but i am struggeling with the Speed (V_VAR2) and Mode (V_VAR1).
How can I adress these two in Domoticz so it is picked up by the node?
So i want to set the mode and or the speed from Domoticz to.// Enable debug prints to serial monitor #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 #define MY_RF24_PA_LEVEL RF24_PA_MAX // Enabled repeater feature for this node #define MY_REPEATER_FEATURE #define MY_NODE_ID 9 #include <MySensors.h> #include <DHT.h> #include "FastLED.h" FASTLED_USING_NAMESPACE #if defined(FASTLED_VERSION) && (FASTLED_VERSION < 3001000) #warning "Requires FastLED 3.1 or later; check github for latest code." #endif #define DATA_PIN 3 //#define CLK_PIN 4 #define LED_TYPE WS2811 #define COLOR_ORDER GRB #define NUM_LEDS 60 CRGB leds[NUM_LEDS]; uint8_t gHue = 0; unsigned int currentSpeed = 0 ; int brightness = 96; unsigned int requestedMode = 0 ; int messageType = 0 ; int previousMessageType = -1; String hexColor = "000000" ; unsigned long previousTime = 0 ; void setup() { delay(1000); Serial.begin(115200); FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); FastLED.setBrightness(brightness); FastLED.show(); } void presentation() { sendSketchInfo("FastLED Node", "1.0"); present(0, S_RGB_LIGHT, "Makes strip said color", true); } void loop() { switch (messageType) { //************** CASE 1 ************** case (1): Serial.print("Hex color override: "); Serial.println(hexColor); colorWipe(); messageType = 0 ; break; //************** CASE 2 ************** case (2): if ( (previousTime + (long) currentSpeed ) < millis() ) { if (requestedMode == 2) {rainbow(); FastLED.show(); } if (requestedMode == 3) {rainbowWithGlitter();FastLED.show(); } if (requestedMode == 4) {addGlitter(80);FastLED.show(); } if (requestedMode == 5) {confetti();FastLED.show(); } if (requestedMode == 6) {sinelon();FastLED.show(); } if (requestedMode == 7) {bpm();FastLED.show(); } if (requestedMode == 8) {juggle();FastLED.show(); } previousTime = millis(); } break; //************** CASE 3 ************** case (3): // Adjust timing of case 2 using non-blocking code (no DELAYs) Serial.print("Case 3 received. Speed set to: "); Serial.print(currentSpeed); Serial.println(" ms."); messageType = 2; break; //************** CASE 4 ************** case (4): // Adjust brightness of whole strip of case 2 using non-blocking code (no DELAYs) Serial.print("Case 4 received. Brightness set to: "); Serial.println(brightness); FastLED.setBrightness(brightness); FastLED.show(); messageType = previousMessageType ; // We get off type 4 ASAP break; } } void receive(const MyMessage &message) { Serial.println("Message received: "); if (message.type == V_RGB) { messageType = 1 ; hexColor = message.getString(); Serial.print("RGB color: "); Serial.println(hexColor); } if (message.type == V_VAR1) { requestedMode = message.getInt(); Serial.println(requestedMode); messageType = 2 ; Serial.print("Neo mode: "); Serial.println(requestedMode); } if (message.type == V_VAR2) { // This line is for the speed of said mode currentSpeed = message.getInt() ; Serial.println(currentSpeed); messageType = 3 ; Serial.print("Neo speed: "); Serial.println(currentSpeed); } if (message.type == V_VAR3) { // This line is for the brightness of said mode brightness = message.getInt() ; //if(brightness > 255) {brightness = 255;} //if(brightness < 0) {brightness = 0;} Serial.println(brightness); previousMessageType = messageType; messageType = 4 ; Serial.print("Neo brightness: "); Serial.println(brightness); } } //********************** FastLED FUNCTIONS *********************** void colorWipe() { for (int i = 0; i < NUM_LEDS ; i++) { leds[i] = strtol( &hexColor[0], NULL, 16); FastLED.show(); } } void rainbow() { // FastLED's built-in rainbow generator fill_rainbow( leds, NUM_LEDS, gHue++, 7); } void rainbowWithGlitter() { // built-in FastLED rainbow, plus some random sparkly glitter fill_rainbow( leds, NUM_LEDS, gHue++, 7); FastLED.show(); addGlitter(80); } void addGlitter( fract8 chanceOfGlitter) { if ( random8() < chanceOfGlitter) { leds[ random16(NUM_LEDS) ] += CRGB::White; } } void confetti() { // random colored speckles that blink in and fade smoothly fadeToBlackBy( leds, NUM_LEDS, 10); int pos = random16(NUM_LEDS); leds[pos] += CHSV( gHue + random8(64), 200, 255); } void sinelon() { // a colored dot sweeping back and forth, with fading trails fadeToBlackBy( leds, NUM_LEDS, 20); int pos = beatsin16(13, 0, NUM_LEDS); leds[pos] += CHSV( gHue, 255, 192); } void bpm() { // colored stripes pulsing at a defined Beats-Per-Minute (BPM) uint8_t BeatsPerMinute = 62; CRGBPalette16 palette = PartyColors_p; uint8_t beat = beatsin8( BeatsPerMinute, 64, 255); for ( int i = 0; i < NUM_LEDS; i++) { //9948 leds[i] = ColorFromPalette(palette, gHue + (i * 2), beat - gHue + (i * 10)); } } void juggle() { // eight colored dots, weaving in and out of sync with each other fadeToBlackBy( leds, NUM_LEDS, 20); byte dothue = 0; for ( int i = 0; i < 8; i++) { leds[beatsin16(i + 7, 0, NUM_LEDS)] |= CHSV(dothue, 200, 255); dothue += 32; } }
With Regards, and thanks in advance.
Peter