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

  • 1
  • 5
  • 2
  • 2
  • 2
  • 3

0
Online

11.2k
Users

11.1k
Topics

112.5k
Posts