RGB Leds Light - Mood Light



  • I think most people have already seen that 15 dollars multisensor build by Ben from BruhAutomation.
    Here is the link: https://www.youtube.com/watch?v=jpjfVc-9IrQ

    Unfortunately (at least for this community) he uses a NomeMCU board instead of using a MySensors connection.

    It would be awesome porting that whole sketch and project to a MySensors battery powered node... sorry if I am missing somebody´s work that already did that.

    All the sensors together are relatively easy to build on mysensor, but what I can´t figure out is that awesome RGB LED wich turns into a complete Light Component, with fade, color changing and transitions.

    Could someone share a mysensors node or help porting that Bruh Sketch, specially the RGB Led part?

    It would be something like a Mood Light!

    Here is original code:
    https://github.com/bruhautomation/ESP-MQTT-JSON-Multisensor


  • Contest Winner



  • Thanks @BartE !

    Three more questions:

    • Will it work with a single 4 pin RGB LED common cathode instead of a LED strip?
    • Will it work with Home Assistant Controller like a ordinary RGB Light?
    • Could it run on batteries?

    Thanks again.


  • Contest Winner

    Hi @OliverDog , yes this should work

    • Will it work with a single 4 pin RGB LED common cathode instead of a LED strip?
      --> Uncomment this line "#define RGBW 1" to make it three color (RGB) in stead of four (RGBW).

    • Will it work with Home Assistant Controller like a ordinary RGB Light?
      --> Should work with HAC since it presents it self as a RGB module

    • Could it run on batteries?
      --> Yes why not, but please do read some forum posts about what to think about when running mysensors on batteries, there are several of them



  • Finally I tried this weekend but no success...

    First I have updated your sketch to 2.0 version (I think I made everything right)
    Didn't work on Home Assistant because the sketch don't send an initial value for each configuration of the Leds, such as Dimmer, RGB, Light, Fade, etc.

    I did not figure out how to create an initial value loop because there are no MyMessage msg(Child_, V_) on the sketch...

    Could you help me again?
    Thanks very much...

    Here is the updated sketch:

    // RBG led strip plug in.
    // by Bart Eversdijk (c) 2015.
    
    #define MY_DEBUG
    #define MY_RADIO_NRF24
    #define MY_NODE_ID 3
    
    #include <MySensors.h>
    #include <SPI.h>
    
    #define SUBID  1  // sensor number needed in the custom devices set up
    
    #define RED   6  // Arduino PWM pin for Red
    #define GREEN 5 // Arduino PWM pin for Green
    #define BLUE  3  // Arduino PWM pin for Blue
    #define NODENAME "RGB Led2"
    
    enum ANIMATIOMODES {RAINBOW=0,RANDONMIZE,FADERGB,FADEMULTICOLR,FLASHCOLOR,LAST_PROGRAM};
    
    byte FADE_RGB_COLOR_MODES[]   = {0b0010,0b0011,0b0100,0b0101,0b1000,0b1001, 0xFF};
    byte FADE_MULTI_COLOR_MODES[] = {0b0010,0b0011,0b0110,0b0111,0b0100,0b0101,0b1100,0b1101,0b1000,0b1001,0b1010,0b1011,0xFF};
    
    static bool first_message_sent = false;
    
    byte rgb_pins[]   = {RED, GREEN, BLUE};
    byte ledOffValues[] = {0, 0, 0, 0};
    byte rgb_values[]   = {0, 0, 0, 0};
    
    
    void incomingMessage(const MyMessage &message);
    #define NUM_OF_COLORS sizeof(rgb_pins)
    int speedtable[] = { 0, 100, 50, 2 };
    #define NUM_OF_SPEEDS sizeof(speedtable)
    
    struct
    {
       byte values[4];
       byte speedsetting;
       byte mode;
       bool status;
    } rgb = { {0,0,0,0}, 0, RAINBOW, false};
    
    bool    flashOn      = true;
    int     syscounter   = 0;
    int     lastUpdate   = 0;
    bool    newSetting   = false;
    
    void before() {
        // Set the rgb(w) pins in output mode
        for (int i = 0; i < NUM_OF_COLORS; i++) {
            pinMode(rgb_pins[i], OUTPUT);
        }
        recallEeprom();
        setLedValues(rgb.values, true);
        
        Serial.println("Init done");
    }
    
    void presentation()
    {
      sendSketchInfo(NODENAME, "1.0");
      present(SUBID, S_RGB_LIGHT);
    }
    
    void loop()
    {
        // Alway process incoming messages whenever possible
        if (speedtable[rgb.speedsetting] > 0) {
            if ((syscounter % speedtable[rgb.speedsetting]) == 0) {
               switch (rgb.mode)
               {
                   case RAINBOW:
                     animateRainbowStep();
                     break;
    
                   case FADERGB:
                     animateFadeColorStep(FADE_RGB_COLOR_MODES);
                     break;
    
                   case FADEMULTICOLR:
                     animateFadeColorStep(FADE_MULTI_COLOR_MODES);
                     break;
                 
                  case FLASHCOLOR:
                     setLedValues(flashOn ? ledOffValues : rgb.values, false);
                     flashOn = !flashOn;
                     break;
                                 
                   case RANDONMIZE:
                     long number = random(0, 0xFFFFFF);
                     rgb_values[0] = number >> 16 & 0xFF ;
                     rgb_values[1] = number >> 8 & 0xFF ;
                     rgb_values[2] = number & 0xFF;
                     setLedValues(rgb_values, false);
                     break;
               }
            }
            delay(rgb.mode == RANDONMIZE || rgb.mode == FLASHCOLOR ? 50 : 1);
        }
        if (newSetting && (lastUpdate + 30000 < syscounter)) {   
            // Wait for a couple of seconds be fore actual storing the current setting in to EEPROM
            // This will save the EEPROM's life time, when playing around with colors
            Serial.println(" Store EERPOM");
            storeEeprom();
            newSetting = false;
        } 
        delay(1);
        syscounter++;
    }
    
    void animateRainbowStep()
    {    
        static float counter = 0;
        float        pi      = 3.14159; 
        counter++;
        rgb_values[0] = map(sin(counter/100         )*1000,-1000,1000,0,255);
        rgb_values[1] = map(sin(counter/100 + pi*2/3)*1000,-1000,1000,0,255);
        rgb_values[2] = map(sin(counter/100 + pi*4/3)*1000,-1000,1000,0,255);
        setLedValues(rgb_values, false);
    }
    
    void animateFadeColorStep(byte *modes)
    {    
        static int modecnt = 0;
        if (updateRGBValues(modes[modecnt] >> 1, (modes[modecnt] & 0x1) == 0x1)) { 
            modecnt = (modes[modecnt+1] == 0xFF ? 0 : modecnt + 1);
        }
    }
    
    bool updateRGBValues(byte mode, bool down)
    {
        bool endReached = false;
        for (byte i = 0; i < 3; i++) {
            if (((mode >> i) & 0x1) == 0x1) {
               rgb_values[i] += (down ? -1 : 1);
               endReached    |= (down && (rgb_values[i] == 0x00)) || (!down && (rgb_values[i] == 0xFF));
            }
        }
        setLedValues(rgb_values, false);
        return endReached;
    }
    
    
    void incomingMessage(const MyMessage &message) {
        if (message.type == V_RGB || message.type == V_RGBW) {
      // starting to process the hex code
            String hexstring = message.getString();
    
            long number;
    #ifdef RGBW
            char white[3];
            white[0] = hexstring[6];
            white[1] = hexstring[7];
            white[2] = 0;
            number = (long) strtol( &white[0], NULL, 16);
            rgb.values[3] = number & 0xFF;
    #endif        
            hexstring[6] = 0;
            number = (long) strtol( &hexstring[0], NULL, 16);
            rgb.values[0] = number >> 16 & 0xFF ;
            rgb.values[1] = number >> 8 & 0xFF ;
            rgb.values[2] = number & 0xFF;
            
            rgb.speedsetting = 0;
            setLedValues(rgb.values, true);
            lastUpdate = syscounter;
            newSetting = true;
        }
        
        if (message.type == V_STATUS) {
          if (message.getBool()) {
              Serial.println("ON: Switch to last known color values");
              setLedValues(rgb_values, true);
          } else {
             Serial.println("OFF: Switch colors off");
             setLedValues(ledOffValues, true);
          }
          rgb.speedsetting = 0;
          rgb.status = message.getBool();
          lastUpdate = syscounter;
          newSetting = true;
        }
        
        if (message.type == V_VAR1) {
           Serial.println("Set speed and program value"); 
           byte newsetting = message.getByte();
           rgb.speedsetting = (newsetting >> 4) & 0x0F;
           byte newmode = newsetting & 0x0F;
    
           if (newmode != rgb.mode) {
               for (byte i = 0; i < NUM_OF_COLORS; i++) {
                   rgb_values[i] = 0;
               }
               rgb.mode = newmode;
           }
           if (rgb.speedsetting > 0) {
             rgb.status = true;
           }
           lastUpdate = syscounter;
           newSetting = true;
          
           Serial.print("Data 0x");
           Serial.print(newsetting, HEX);
           Serial.print(" speed:");
           Serial.print(rgb.speedsetting);
           Serial.print(" mode:");
           Serial.println(rgb.mode);
        }
    }
    
    void setLedValues(byte *rgb, bool show)
    {
        for (int i = 0; i < NUM_OF_COLORS; i++) {
            analogWrite(rgb_pins[i], rgb[i]);
        }  
     
        if (show) {
          Serial.print("Red: " );
          Serial.print(rgb[0], HEX);
          Serial.print("  Green: " );
          Serial.print(rgb[1], HEX);
          Serial.print("  Blue: " );
          Serial.print(rgb[2], HEX);
     #ifdef RGBW
            Serial.print("  White is " );
            Serial.print(rgb[3], HEX);
     #endif
          Serial.println();
        }
    }
    
    void storeEeprom()
    {
        byte address = 0;
        byte *p = (byte *)&(rgb);
        for (byte i = 0; i < sizeof(rgb); i++) {
           saveState(address++, p[i]);
        }
    }
    
    void recallEeprom()
    {
        byte address = 0;
        byte *p = (byte *)&(rgb);
        for (byte i = 0; i < sizeof(rgb); i++) {
           p[i] = loadState(address++);
        }
    }
    


  • I tried another sketch from
    https://forum.mysensors.org/topic/6765/rgb-led-strip

    It worked with HASS but there is no response based on transitions time.

    /**
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     * LED STRIP sketch for Mysensors
     *******************************
     *
     * REVISION HISTORY
     * 1.0 
     *   Based on the example sketch in mysensors
     * 1.1
     *   fadespeed parameter (send as V_VAR1 message)
     *   HomeAssistant compatible (send status to ack)
     */
    
    #define MY_NODE_ID AUTO
    #define MY_DEBUG
    #define MY_RADIO_NRF24
    
    #include <MySensors.h>
    
    #define CHILD_ID_LIGHT 1
    
    #define SN "LED Strip"
    #define SV "1.1"
    
    MyMessage lightMsg(CHILD_ID_LIGHT, V_LIGHT);
    MyMessage rgbMsg(CHILD_ID_LIGHT, V_RGB);
    MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER);
    
    byte red = 255;
    byte green = 255;
    byte blue = 255;
    byte r0 = 255;
    byte g0 = 255;
    byte b0 = 255;
    char rgbstring[] = "ffffff";
    
    int on_off_status = 0;
    int dimmerlevel = 100;
    int fadespeed = 0;
    
    #define REDPIN 6
    #define GREENPIN 5
    #define BLUEPIN 3
    
    void setup()
    {
      // Fix the PWM timer. Without this the LEDs will flicker.
      TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00);
    
      // Output pins
      pinMode(REDPIN, OUTPUT);
      pinMode(GREENPIN, OUTPUT);
      pinMode(BLUEPIN, OUTPUT);
      
    }
    
    void presentation()
    {
    	// Send the Sketch Version Information to the Gateway
    	sendSketchInfo(SN, SV);
    	present(CHILD_ID_LIGHT, S_RGB_LIGHT);
    }
    
    void loop()
    {
      static bool first_message_sent = false;
      if ( first_message_sent == false ) {
        Serial.println( "Sending initial state..." );
        set_hw_status();
        send_status();
        first_message_sent = true;
      }
    }
    
    void receive(const MyMessage &message)
    {
      int val;
      
    	if (message.type == V_RGB) {
    		Serial.println( "V_RGB command: " );
        Serial.println(message.data);
        long number = (long) strtol( message.data, NULL, 16);
    
        // Save old value
        strcpy(rgbstring, message.data);
        
        // Split it up into r, g, b values
        red = number >> 16;
        green = number >> 8 & 0xFF;
        blue = number & 0xFF;
    
        send_status();
        set_hw_status();
    
    	} else if (message.type == V_LIGHT || message.type == V_STATUS) {
        Serial.println( "V_LIGHT command: " );
        Serial.println(message.data);
        val = atoi(message.data);
        if (val == 0 or val == 1) {
          on_off_status = val;
          send_status();
          set_hw_status();
        }
        
      } else if (message.type == V_DIMMER || message.type == V_PERCENTAGE) {
        Serial.print( "V_DIMMER command: " );
        Serial.println(message.data);
        val = atoi(message.data);
        if (val >= 0 and val <=100) {
          dimmerlevel = val;
          send_status();
          set_hw_status();
        }
        
      } else if (message.type == V_VAR1 ) {
        Serial.print( "V_VAR1 command: " );
        Serial.println(message.data);
        val = atoi(message.data);
        if (val >= 0 and val <= 2000) {
          fadespeed = val;
        }
        
    	} else {
    		Serial.println( "Invalid command received..." );
    		return;
    	}
    
    }
    
    void set_rgb(int r, int g, int b) {
      analogWrite(REDPIN, r);
      analogWrite(GREENPIN, g);
      analogWrite(BLUEPIN, b);
    }
    
    void set_hw_status() {
      int r = on_off_status * (int)(red * dimmerlevel/100.0);
      int g = on_off_status * (int)(green * dimmerlevel/100.0);
      int b = on_off_status * (int)(blue * dimmerlevel/100.0);
    
      if (fadespeed >0) {
        
        float dr = (r - r0) / float(fadespeed);
        float db = (b - b0) / float(fadespeed);
        float dg = (g - g0) / float(fadespeed);
        
        for (int x = 0;  x < fadespeed; x++) {
          set_rgb(r0 + dr*x, g0 + dg*x, b0 + db*x);
          delay(100);
        }
      }
    
      set_rgb(r, g, b);
     
      r0 = r;
      b0 = b;
      g0 = g;
      
    }
    
    
    void send_status() {
      send(rgbMsg.set(rgbstring));
      send(lightMsg.set(on_off_status));
      send(dimmerMsg.set(dimmerlevel));
    }
    

Log in to reply
 

Suggested Topics

1
Online

11.4k
Users

11.1k
Topics

112.7k
Posts