Errors with Custom MySensors actuator (Neopixel/ws2812 Node)



  • Greetings,

    I've been working with sensor networks with MySensors for quite some time. So far, it's one of the nicest APIs I've worked with in networking. But I wanted to build an actuator that would follow somewhat complicated commands to actuate a Neopixel strip.

    I already have the code written, and from after reading all the documentation, should indeed work.

    #include <Adafruit_NeoPixel.h>
    #include <avr/power.h>
    #include <MySensor.h>
    #include <SPI.h>
    Adafruit_NeoPixel strip = Adafruit_NeoPixel(38, 3, NEO_GRB + NEO_KHZ800);
    
    MySensor gw;
    
    
    void setup() {
      Serial.begin(115200);
      
      gw.begin(incomingMessage, 10, false);
      gw.sendSketchInfo("Neopixel Node", "1.0");
      gw.present(0, S_CUSTOM);
      
      strip.begin();
      strip.show(); 
      Serial.println("Neopixel Node device ready");
    }
    
    void loop() {
      gw.process();
    }
    
    
    
    void incomingMessage(const MyMessage &message) {
      Serial.println("Incoming message");
      
      if (message.type == V_STATUS){
        // Turns on or off
        if (message.getInt() == 0){lightsOut(10);}
      }
      
      if (message.type == V_RGB){
        // Makes it a solid color
        String hexstring = message.getString();
        long number = (long) strtol( &hexstring[0], NULL, 16);
        colorWipe(number, 10);
      }
      
      if (message.type == V_VAR1){
        //Where we put the modes
        switch( message.getInt() ){
          
          case 1:
          Serial.println("Rainbow mode activated");
          rainbow(20);
          break;
          
          case 2:
          Serial.println("Rainbow Cycle mode activated");
          rainbowCycle(20);
          break;
          
          case 3:
          Serial.println("Theater chase lights mode activated");
          theaterChaseRainbow(50);
          break;
          
          default:
          break;
          
         }
      }
      
    }
    
    
    
    
    
    
    void lightsOut(uint8_t wait) {
      for(uint16_t i=0; i<strip.numPixels(); i++) {
          strip.setPixelColor(i, 0);
          strip.show();
          delay(wait);
      }
    }
    
    
    // Fill the dots one after the other with a color
    void colorWipe(uint32_t c, uint8_t wait) {
      for(uint16_t i=0; i<strip.numPixels(); i++) {
          strip.setPixelColor(i, c);
          strip.show();
          delay(wait);
      }
    }
    
    void rainbow(uint8_t wait) {
      uint16_t i, j;
    
      for(j=0; j<256; j++) {
        for(i=0; i<strip.numPixels(); i++) {
          strip.setPixelColor(i, Wheel((i+j) & 255));
        }
        strip.show();
        delay(wait);
      }
    }
    
    // Slightly different, this makes the rainbow equally distributed throughout
    void rainbowCycle(uint8_t wait) {
      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();
        delay(wait);
      }
    }
    
    //Theatre-style crawling lights.
    void theaterChase(uint32_t c, uint8_t wait) {
      for (int j=0; j<10; j++) {  //do 10 cycles of chasing
        for (int q=0; q < 3; q++) {
          for (int i=0; i < strip.numPixels(); i=i+3) {
            strip.setPixelColor(i+q, c);    //turn every third pixel on
          }
          strip.show();
         
          delay(wait);
         
          for (int i=0; i < strip.numPixels(); i=i+3) {
            strip.setPixelColor(i+q, 0);        //turn every third pixel off
          }
        }
      }
    }
    
    //Theatre-style crawling lights with rainbow effect
    void theaterChaseRainbow(uint8_t wait) {
      for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
        for (int q=0; q < 3; q++) {
            for (int i=0; i < strip.numPixels(); i=i+3) {
              strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
            }
            strip.show();
           
            delay(wait);
           
            for (int i=0; i < strip.numPixels(); i=i+3) {
              strip.setPixelColor(i+q, 0);        //turn every third pixel off
            }
        }
      }
    }
    
    // Input a value 0 to 255 to get a color value.
    // The colours are a transition r - g - b - back to r.
    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);
      }
    }
    
    

    But when I compile, it works. Then I get the nice chirps from the gateway showing the devices are talking. I get no st:FAIL or anything. It's all OK in the debug.

    As an example, from Node-red, I see the following when the Neopixel Node comes online

    12/23/2015, 3:51:35 PM84cc7d74.87704msg : Object{ "payload": "1.5\n", "_msgid": "cdb13c1a.324ec", "rawData": [ "10", "255", "0", "0", "17", "1.5\n" ], "nodeId": 10, "childSensorId": 255, "messageType": 0, "ack": 0, "subType": 17 }
    
    12/23/2015, 3:51:35 PM84cc7d74.87704msg : Object{ "payload": "0\n", "_msgid": "ff17a410.00e858", "rawData": [ "10", "255", "3", "0", "6", "0\n" ], "nodeId": 10, "childSensorId": 255, "messageType": 3, "ack": 0, "subType": 6 }
    
    12/23/2015, 3:51:37 PM84cc7d74.87704msg : Object{ "payload": "Neopixel Node\n", "_msgid": "1e786c77.e18794", "rawData": [ "10", "255", "3", "0", "11", "Neopixel Node\n" ], "nodeId": 10, "childSensorId": 255, "messageType": 3, "ack": 0, "subType": 11 }
    
    12/23/2015, 3:51:37 PM84cc7d74.87704msg : Object{ "payload": "1.0\n", "_msgid": "2dbec95b.d24136", "rawData": [ "10", "255", "3", "0", "12", "1.0\n" ], "nodeId": 10, "childSensorId": 255, "messageType": 3, "ack": 0, "subType": 12 }
    
    12/23/2015, 3:51:37 PM84cc7d74.87704msg : Object{ "payload": "\n", "_msgid": "a4060382.5bfa", "rawData": [ "10", "0", "0", "0", "23", "\n" ], "nodeId": 10, "childSensorId": 0, "messageType": 0, "ack": 0, "subType": 23 }
    
    1. Is this an improper use of S_CUSTOM? If so, can you guide me to the docs that indicate how to properly construct it?

    2. Is it possible that my Node-red MYSENCAP node is improperly configured? My settings for it are
      {"message-type": "set",
      "Node ID" : "10" ,
      "Child ID" : "0" ,
      "Child Type" : "V_VAR1",
      "ACK" : "off" ,
      "Presentation" : "off"}

    And then I proceed to send a "2" through an Inject node. That should send my Neopixel Node into a rainbowCycle() call.

    1. I would rather have each ws2312 on its own childID. That way, I could individually address them with "HEX color/childID" and program more emergent behavior. How would the pros at MySensors approach this?

    Thank you,
    Josh Conway


Log in to reply
 

Suggested Topics

30
Online

11.6k
Users

11.2k
Topics

113.0k
Posts