Neopixel Node, using 1.6.0 Beta



  • I've been working on a few different concepts about a new node type, called the "Neopixel Node"! Using 1.6.0 Beta MySensors.

    Initially, I thought it would be easy to port the strandtest code over... I was wrong. The code is all blocking with delay() everywhere. It means that your sent messages to this node won't send. And then, what's the point?

    So I am in the works to make the code as non-blocking as I can make it. So far, I have many functions non-blocking with the exception of the theatre crawling lights. And the delay at most is 150ms.

    I pieced everything together on my controller side with Node-Red. I only wanted a basic shell of connecting functionality, whereas you can easily hook it up to a web gui with a few basic blocks.

    And remember, the code is very rough right now. I'm working on making more functions non-blocking along with adding new patterns and cool ideas. But using Node-Red makes a very quick turn-around time for testing and updating! Perhaps we can get a Node-Red as a Controller forum added?

    V_RGB = give this a hex code. 000000 is off, ff0000 is red
    V_VAR1 = Different modes. 2 is slow rainbow. 3 is fast rainbow. 4 is theater chase after you use a hex code.
    V_VAR2 = Speed control for mode 2 and 3 for V_VAR1

    node_red_neopixels.png

    [Node-Red Flow Code]

    [{"id":"c02382bd.ae5","type":"serial-port","z":"387afd49.a6b0fa","serialport":"/dev/ttyUSB0","serialbaud":"115200","databits":"8","parity":"none","stopbits":"1","newline":"\\n","bin":"false","out":"char","addchar":true},{"id":"23d05132.32938e","type":"serial out","z":"387afd49.a6b0fa","name":"","serial":"c02382bd.ae5","x":671,"y":298,"wires":[]},{"id":"db668f27.44ac8","type":"mysdecenc","z":"387afd49.a6b0fa","name":"","x":666,"y":217,"wires":[["23d05132.32938e"]]},{"id":"c18b87a6.cc82d8","type":"mysencap","z":"387afd49.a6b0fa","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":415,"y":110,"wires":[["db668f27.44ac8"]]},{"id":"3542cfac.f962d8","type":"mysencap","z":"387afd49.a6b0fa","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":414,"y":313,"wires":[["db668f27.44ac8"]]},{"id":"186b7cdb.c952e3","type":"mysencap","z":"387afd49.a6b0fa","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":420,"y":470,"wires":[["db668f27.44ac8"]]},{"id":"29819ac0.48d326","type":"function","z":"387afd49.a6b0fa","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":277,"y":109,"wires":[["c18b87a6.cc82d8"]]},{"id":"8cfbe481.6b1de8","type":"function","z":"387afd49.a6b0fa","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":286,"y":312,"wires":[["3542cfac.f962d8"]]},{"id":"f40043ae.2a3dd8","type":"function","z":"387afd49.a6b0fa","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":289,"y":469,"wires":[["186b7cdb.c952e3"]]},{"id":"f5a3d9a5.f04d5","type":"inject","z":"387afd49.a6b0fa","name":"Speed9 (slow)","topic":"","payload":"9","payloadType":"string","repeat":"","crontab":"","once":false,"x":115,"y":506,"wires":[["f40043ae.2a3dd8"]]},{"id":"346a22ac.72f7be","type":"inject","z":"387afd49.a6b0fa","name":"Speed0 (fast)","topic":"","payload":"0","payloadType":"string","repeat":"","crontab":"","once":false,"x":111,"y":431,"wires":[["f40043ae.2a3dd8"]]},{"id":"ccdef1a.ef36e1","type":"inject","z":"387afd49.a6b0fa","name":"rainbow","topic":"","payload":"2","payloadType":"string","repeat":"","crontab":"","once":false,"x":113,"y":267,"wires":[["8cfbe481.6b1de8"]]},{"id":"eeaad340.169418","type":"inject","z":"387afd49.a6b0fa","name":"fast rainbow","topic":"","payload":"3","payloadType":"string","repeat":"","crontab":"","once":false,"x":123,"y":303,"wires":[["8cfbe481.6b1de8"]]},{"id":"43c0b3c7.fd6814","type":"inject","z":"387afd49.a6b0fa","name":"","topic":"","payload":"000000","payloadType":"string","repeat":"","crontab":"","once":false,"x":88,"y":24,"wires":[["29819ac0.48d326"]]},{"id":"24524b50.eb8acc","type":"inject","z":"387afd49.a6b0fa","name":"","topic":"","payload":"ff0000","payloadType":"string","repeat":"","crontab":"","once":false,"x":87,"y":77,"wires":[["29819ac0.48d326"]]},{"id":"1b069543.32c0ab","type":"inject","z":"387afd49.a6b0fa","name":"","topic":"","payload":"00ff00","payloadType":"string","repeat":"","crontab":"","once":true,"x":87,"y":117,"wires":[["29819ac0.48d326"]]},{"id":"e789eab3.9a517","type":"inject","z":"387afd49.a6b0fa","name":"","topic":"","payload":"ffffff","payloadType":"string","repeat":"","crontab":"","once":false,"x":252,"y":23,"wires":[["29819ac0.48d326"]]},{"id":"d912e499.b4cc28","type":"inject","z":"387afd49.a6b0fa","name":"Speed5 (medium)","topic":"","payload":"5","payloadType":"string","repeat":"","crontab":"","once":false,"x":126,"y":471,"wires":[["f40043ae.2a3dd8"]]},{"id":"1087e912.c8ddbf","type":"inject","z":"387afd49.a6b0fa","name":"","topic":"","payload":"0000ff","payloadType":"string","repeat":"","crontab":"","once":false,"x":89,"y":154,"wires":[["29819ac0.48d326"]]},{"id":"2e6a0789.d500b","type":"inject","z":"387afd49.a6b0fa","name":"theater chase","topic":"","payload":"4","payloadType":"string","repeat":"","crontab":"","once":false,"x":128,"y":336,"wires":[["8cfbe481.6b1de8"]]},{"id":"f66f1235.3e7e58","type":"comment","z":"387afd49.a6b0fa","name":"Init solid color before using theater","info":"","x":153,"y":370,"wires":[]},{"id":"afeca932.c1ba68","type":"comment","z":"387afd49.a6b0fa","name":"Hex colors","info":"","x":92,"y":187,"wires":[]}]
    
    

    [Arduino Sketch 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);
      }
    }
    
    
    


  • Neopixel Node Demo – 01:55
    — Josh Conway

    Of what it's capable of doing.



  • Nice work!

    I really like neopixels! I dont know anything about Node-Red.. Can this be used without it?



  • You should be able to. I have this as Node ID 9, and Child ID 0.

    9;0;1;1;40;(HEX) sets a consistent color of the appropriate HEX code.
    9;0;1;1;24;(2 or 3 or 4) sets either slow rainbow, fast rainbow or theater chase
    9;0;1;1;25;(0 through 9) sets speed. 0 is faster and 9 is slower.

    Node-Red is what I use, but this should work with any controller given those settings. Of course, use the standard MySensors serial protocol.

    Tell me how you like it!


  • Hero Member

    @cranky Hi, I have been doing something similar a while ago, moodlight Have you looked at the FastLED library? It contains numerous special light effect functions.



  • @cranky Thanks, I will test when my neopixels arrive from le China!



  • Oh, @msebbe @AWI , I have a FastLED version with a decent web API and web interface available here: http://forum.mysensors.org/topic/2705/fastled-neopixel-ws2811-node-from-arduino-code-to-web-page-with-api

    It's working pretty damn well 😄 Still working on my front end interface, since I'm not a designer (well, I am a 3d cad designer, not web dev).

    Oh, and if you knew my controller's name, you could communicate with it via TOR. Just like corporate solutions, I can communicate and control my gateway from anywhere in the world!


 

200
Online

9.0k
Users

9.7k
Topics

101.3k
Posts