Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. OpenHardware.io
  3. 💬 OH MySensors RGBW Controller

💬 OH MySensors RGBW Controller

Scheduled Pinned Locked Moved OpenHardware.io
mysensorspcbrgbwcontroller
106 Posts 18 Posters 29.5k Views 19 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    Stuart Middleton
    wrote on last edited by Stuart Middleton
    #61

    Thanks, @LastSamurai, I went and compared the DIrty PCB files with the v1.3 ones on OpenHardware.IO and they are indeed different. It looks like the DIrtyPCB link is out of date and still has the error on them.
    @Sergio-Rius would be very grateful if you could update those files :)

    Sergio RiusS 1 Reply Last reply
    0
    • S Stuart Middleton

      Thanks, @LastSamurai, I went and compared the DIrty PCB files with the v1.3 ones on OpenHardware.IO and they are indeed different. It looks like the DIrtyPCB link is out of date and still has the error on them.
      @Sergio-Rius would be very grateful if you could update those files :)

      Sergio RiusS Offline
      Sergio RiusS Offline
      Sergio Rius
      wrote on last edited by
      #62

      @Stuart-Middleton Unfortunately my boards are already made and shipped. They made them in just a day (Sunday) and didn't have me time to rectify my order.

      S 1 Reply Last reply
      0
      • Sergio RiusS Sergio Rius

        @Stuart-Middleton Unfortunately my boards are already made and shipped. They made them in just a day (Sunday) and didn't have me time to rectify my order.

        S Offline
        S Offline
        Stuart Middleton
        wrote on last edited by
        #63

        @Sergio-Rius Oh well, it doesn't look too hard to adapt for the error.

        L 1 Reply Last reply
        0
        • S Stuart Middleton

          @Sergio-Rius Oh well, it doesn't look too hard to adapt for the error.

          L Offline
          L Offline
          LastSamurai
          Hardware Contributor
          wrote on last edited by
          #64

          @Stuart-Middleton It really shoudn't be. Just follow the pictures in the project. There are also updated project/gerber files in my github for anyone wanting to order new ones. Once I have used all of the Version 1.3 ones I will order new ones from dirtyPCBs and add the link here.

          1 Reply Last reply
          0
          • J Jan Gatzke

            I have tried to get some kind of non linear fading by calculating the values for 256 steps using Excel and putting them in an array. The result is pretty good. Please test and share your opinion. ;)

            /**
              Based on the MySensors Project: http://www.mysensors.org
            
              This sketch controls a (analog)RGBW strip by listening to new color values from a (domoticz) controller and then fading to the new color.
            
              Version 1.1 - Added save/restore of values to/from controller, removed non linear fading code
              Version 1.0 - Changed pins and gw definition
              Version 0.9 - Oliver Hilsky
            
            **/
            #define MY_DEBUG
            
            #define SN   "RGBW 01"
            #define SV   "1.1"
            #define MY_RADIO_NRF24
            // change the pins to free up the pwm pin for led control
            #define MY_RF24_CE_PIN 4 //<-- NOTE!!! changed, the default is 9
            #define MY_RF24_CS_PIN 10 // default is 10
            // Set LOW transmit power level as default, if you have an amplified NRF-module and
            // power your radio separately with a good regulator you can turn up PA level.
            #define MY_RF24_PA_LEVEL RF24_PA_LOW
            //Uncomment to enable repeater mode
            //#define MY_REPEATER_FEATURE
            //Uncomment to assign static node ID
            //#define MY_NODE_ID 9
            
            
            // Load mysensors library
            #include <MySensors.h>
            // Load Serial Peripheral Interface library
            #include <SPI.h>
            
            // Arduino pin attached to driver pins
            #define RED_PIN 3
            #define WHITE_PIN 9
            #define GREEN_PIN 5
            #define BLUE_PIN 6
            #define NUM_CHANNELS 4 // how many channels, RGBW=4 RGB=3...
            #define CHILD_ID 1
            
            // Smooth stepping between the values
            #define STEP 1
            #define INTERVAL 10
            
            MyMessage lastvalueMsg(CHILD_ID, V_VAR1);
            MyMessage lastisonMsg(CHILD_ID, V_VAR2);
            MyMessage lastdimmMsg(CHILD_ID, V_VAR3);
            
            // Stores the current color settings
            byte channels[4] = {RED_PIN, GREEN_PIN, BLUE_PIN, WHITE_PIN};
            byte values[4] = {0, 0, 0, 0};
            byte target_values[4] = {0, 0, 0, 0};
            //Stores corrected values for each step from 0 to 255. See https://diarmuid.ie/blog/pwm-exponential-led-fading-on-arduino-or-other-platforms/
            byte converted_values[256] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,8,8,8,8,8,9,9,9,9,9,10,10,10,10,11,11,11,11,12,12,12,13,13,13,13,14,14,14,15,15,15,16,16,17,17,17,18,18,19,19,20,20,20,21,21,22,22,23,23,24,24,25,26,26,27,27,28,29,29,30,31,31,32,33,34,34,35,36,37,38,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,54,55,56,57,58,60,61,62,64,65,67,68,70,71,73,75,76,78,80,81,83,85,87,89,91,93,95,97,99,101,104,106,108,111,113,116,118,121,123,126,129,132,135,138,141,144,147,150,154,157,161,164,168,171,175,179,183,187,191,195,200,204,209,213,218,223,228,233,238,243,249,255};
            
            
            // stores dimming level
            byte dimming = 100;
            byte target_dimming = 100;
            
            // tracks if the strip should be on of off
            boolean isOn = false;
            // tracks if the strip's last status was off. This overrides isOn at startup
            boolean wasOff = true;
            //tracks if the old values have bben requested from the controller. This prevents the request from being send multipßle times in the main loop.
            boolean valuesrequested = false;
            // time tracking for updates
            unsigned long lastupdate = millis();
            
            void setup()
            {
              // Set all channels to output (pin number, type)
              for (int i = 0; i < NUM_CHANNELS; i++) {
                pinMode(channels[i], OUTPUT);
              }
              // debug
              if (isOn) {
                Serial.println("RGBW is running...");
              }
            }
            
            void presentation()  {
              // Send the sketch version information to the gateway and Controller
              sendSketchInfo(SN, SV);
            
              // Register this device as Waterflow sensor
              present(CHILD_ID, S_RGBW_LIGHT, SN, true);
            }
            
            void loop()
            {
              if (!valuesrequested) {
                // get old values if this is just a restart
                Serial.println("Requesting old values...");
                //Request RGBW values
                request( CHILD_ID, V_VAR1 );
                wait(200);
                //Request Status
                request( CHILD_ID, V_VAR2 );
                wait(200);
                //Request dimm level
                request( CHILD_ID, V_VAR3 );
                valuesrequested = true;
              }
            
              // set the new light colors
              if (millis() > lastupdate + INTERVAL) {
                updateLights();
                lastupdate = millis();
              }
            }
            
            // callback function for incoming messages
            void receive(const MyMessage &message) {
            
              Serial.print("Got a message - ");
              Serial.print("Messagetype is: ");
              Serial.println(message.type);
            
              // acknoledgment
              if (message.isAck())
              {
                Serial.println("Got ack from gateway");
              }
            
              // new dim level
              else if (message.type == V_DIMMER or message.type == V_VAR3) {
                Serial.println("Dimming to ");
                Serial.println(message.getString());
                target_dimming = message.getByte();
                send(lastdimmMsg.set(target_dimming));
            
                if (!wasOff) {
                  // a new dimmer value also means on, no seperate signal gets send (by domoticz)
                  isOn = true;
                  send(lastisonMsg.set(isOn));
                }
              }
            
              // on / off message
              else if (message.type == V_STATUS or message.type == V_VAR2) {
                Serial.print("Turning light ");
            
                isOn = message.getInt();
            
                if (isOn) {
                  Serial.println("on");
                  wasOff = false;
                } else {
                  Serial.println("off");
                }
                send(lastisonMsg.set(isOn));
              }
            
              // new color value
              else if (message.type == V_RGBW or message.type == V_VAR1) {
                const char * rgbvalues = message.getString();
                send(lastvalueMsg.set(rgbvalues));
                inputToRGBW(rgbvalues);
                if (!wasOff) {
                  // a new color also means on, no seperate signal gets send (by domoticz); needed e.g. for groups
                  isOn = true;
                  send(lastisonMsg.set(isOn));
                }
              }
            }
            
            // this gets called every INTERVAL milliseconds and updates the current pwm levels for all colors
            void updateLights() {
              int convertedvalue=0;
              // update pin values -debug
              //Serial.println(greenval);
              //Serial.println(redval);
              //Serial.println(blueval);
              //Serial.println(whiteval);
            
              //Serial.println(target_greenval);
              //Serial.println(target_redval);
              //Serial.println(target_blueval);
              //Serial.println(target_whiteval);
              //Serial.println("+++++++++++++++");
            
              // for each color
              for (int v = 0; v < NUM_CHANNELS; v++) {
                if (values[v] < target_values[v]) {
                  values[v] += STEP;
                  if (values[v] > target_values[v]) {
                    values[v] = target_values[v];
                  }
                }
            
                if (values[v] > target_values[v]) {
                  values[v] -= STEP;
                  if (values[v] < target_values[v]) {
                    values[v] = target_values[v];
                  }
                }
              }
            
            
              // dimming
              if (dimming < target_dimming) {
                dimming += STEP;
                if (dimming > target_dimming) {
                  dimming = target_dimming;
                }
              }
              if (dimming > target_dimming) {
                dimming -= STEP;
                if (dimming < target_dimming) {
                  dimming = target_dimming;
                }
              }
            
              /*
                // debug - new values
                Serial.println(greenval);
                Serial.println(redval);
                Serial.println(blueval);
                Serial.println(whiteval);
            
                Serial.println(target_greenval);
                Serial.println(target_redval);
                Serial.println(target_blueval);
                Serial.println(target_whiteval);
                Serial.println("+++++++++++++++");
              */
            
              // set actual pin values
              for (int i = 0; i < NUM_CHANNELS; i++) {
                if (isOn) {
                  // normal fading
                  //analogWrite(channels[i], dimming / 100.0 * values[i]);
                  //Fading with corrected values see https://diarmuid.ie/blog/pwm-exponential-led-fading-on-arduino-or-other-platforms/
                  analogWrite(channels[i], dimming / 100.0 * converted_values[values[i]]);
                  
                } else {
                  analogWrite(channels[i], 0);
                }
              }
            }
            
            // converts incoming color string to actual (int) values
            // ATTENTION this currently does nearly no checks, so the format needs to be exactly like domoticz sends the strings
            void inputToRGBW(const char * input) {
              Serial.print("Got color value of length: ");
              Serial.println(strlen(input));
            
              if (strlen(input) == 6) {
                Serial.println("new rgb value");
                target_values[0] = fromhex (& input [0]);
                target_values[1] = fromhex (& input [2]);
                target_values[2] = fromhex (& input [4]);
                target_values[3] = 0;
              } else if (strlen(input) == 9) {
                Serial.println("new rgbw value");
                target_values[0] = fromhex (& input [1]); // ignore # as first sign
                target_values[1] = fromhex (& input [3]);
                target_values[2] = fromhex (& input [5]);
                target_values[3] = fromhex (& input [7]);
              } else {
                Serial.println("Wrong length of input");
              }
            
            
              Serial.print("New color values: ");
              Serial.println(input);
            
              for (int i = 0; i < NUM_CHANNELS; i++) {
                Serial.print(target_values[i]);
                Serial.print(", ");
              }
            
              Serial.println("");
              Serial.print("Dimming: ");
              Serial.println(dimming);
            
            }
            
            // converts hex char to byte
            byte fromhex (const char * str)
            {
              char c = str [0] - '0';
              if (c > 9)
                c -= 7;
              int result = c;
              c = str [1] - '0';
              if (c > 9)
                c -= 7;
              return (result << 4) | c;
            }
            
            
            L Offline
            L Offline
            LastSamurai
            Hardware Contributor
            wrote on last edited by
            #65

            @Jan-Gatzke Did you ever manage to get your non-linear fading to work? I used the predefined values from your sketch and added them to my newer one but whenever I use that the sketch stops working and only rubbish is shown on the serial port.
            Here is my new version: github

            J 1 Reply Last reply
            0
            • L LastSamurai

              @Jan-Gatzke Did you ever manage to get your non-linear fading to work? I used the predefined values from your sketch and added them to my newer one but whenever I use that the sketch stops working and only rubbish is shown on the serial port.
              Here is my new version: github

              J Offline
              J Offline
              Jan Gatzke
              wrote on last edited by
              #66

              @LastSamurai

              Yes, I did! This sketch is working for me:

              /**
                Based on the MySensors Project: http://www.mysensors.org
              
                This sketch controls a (analog)RGBW strip by listening to new color values from a (domoticz) controller and then fading to the new color.
              
                Version 1.1 - Added save/restore of values to/from controller, removed non linear fading code
                Version 1.0 - Changed pins and gw definition
                Version 0.9 - Oliver Hilsky
              
              **/
              #define MY_DEBUG
              
              #define SN   "RGBW 01"
              #define SV   "1.1"
              #define MY_RADIO_NRF24
              #define MY_PARENT_NODE_ID 10
              // change the pins to free up the pwm pin for led control
              #define MY_RF24_CE_PIN 4 //<-- NOTE!!! changed, the default is 9
              #define MY_RF24_CS_PIN 10 // default is 10
              // Set LOW transmit power level as default, if you have an amplified NRF-module and
              // power your radio separately with a good regulator you can turn up PA level.
              #define MY_RF24_PA_LEVEL RF24_PA_LOW
              //Uncomment to enable repeater mode
              //#define MY_REPEATER_FEATURE
              //Uncomment to assign static node ID
              //#define MY_NODE_ID 9
              
              
              // Load mysensors library
              #include <MySensors.h>
              // Load Serial Peripheral Interface library
              #include <SPI.h>
              
              // Arduino pin attached to driver pins
              #define RED_PIN 3
              #define WHITE_PIN 9
              #define GREEN_PIN 5
              #define BLUE_PIN 6
              #define NUM_CHANNELS 4 // how many channels, RGBW=4 RGB=3...
              #define CHILD_ID 1
              
              // Smooth stepping between the values
              #define STEP 1
              #define INTERVAL 10
              
              MyMessage lastvalueMsg(CHILD_ID, V_VAR1);
              MyMessage lastisonMsg(CHILD_ID, V_VAR2);
              MyMessage lastdimmMsg(CHILD_ID, V_VAR3);
              
              // Stores the current color settings
              byte channels[4] = {RED_PIN, GREEN_PIN, BLUE_PIN, WHITE_PIN};
              byte values[4] = {0, 0, 0, 0};
              byte target_values[4] = {0, 0, 0, 0};
              //Stores corrected values for each step from 0 to 255. See https://diarmuid.ie/blog/pwm-exponential-led-fading-on-arduino-or-other-platforms/
              byte converted_values[256] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,8,8,8,8,8,9,9,9,9,9,10,10,10,10,11,11,11,11,12,12,12,13,13,13,13,14,14,14,15,15,15,16,16,17,17,17,18,18,19,19,20,20,20,21,21,22,22,23,23,24,24,25,26,26,27,27,28,29,29,30,31,31,32,33,34,34,35,36,37,38,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,54,55,56,57,58,60,61,62,64,65,67,68,70,71,73,75,76,78,80,81,83,85,87,89,91,93,95,97,99,101,104,106,108,111,113,116,118,121,123,126,129,132,135,138,141,144,147,150,154,157,161,164,168,171,175,179,183,187,191,195,200,204,209,213,218,223,228,233,238,243,249,255};
              
              
              // stores dimming level
              byte dimming = 100;
              byte target_dimming = 100;
              
              // tracks if the strip should be on of off
              boolean isOn = false;
              // tracks if the strip's last status was off. This overrides isOn at startup
              boolean wasOff = true;
              //tracks if the old values have bben requested from the controller. This prevents the request from being send multipßle times in the main loop.
              boolean valuesrequested = false;
              // time tracking for updates
              unsigned long lastupdate = millis();
              
              void setup()
              {
                // Set all channels to output (pin number, type)
                for (int i = 0; i < NUM_CHANNELS; i++) {
                  pinMode(channels[i], OUTPUT);
                }
                // debug
                if (isOn) {
                  Serial.println("RGBW is running...");
                }
              }
              
              void presentation()  {
                // Send the sketch version information to the gateway and Controller
                sendSketchInfo(SN, SV);
              
                // Register this device as Waterflow sensor
                present(CHILD_ID, S_RGBW_LIGHT, SN, true);
              }
              
              void loop()
              {
                if (!valuesrequested) {
                  // get old values if this is just a restart
                  Serial.println("Requesting old values...");
                  //Request RGBW values
                  request( CHILD_ID, V_VAR1 );
                  wait(200);
                  //Request Status
                  request( CHILD_ID, V_VAR2 );
                  wait(200);
                  //Request dimm level
                  request( CHILD_ID, V_VAR3 );
                  valuesrequested = true;
                }
              
                // set the new light colors
                if (millis() > lastupdate + INTERVAL) {
                  updateLights();
                  lastupdate = millis();
                }
              }
              
              // callback function for incoming messages
              void receive(const MyMessage &message) {
              
                Serial.print("Got a message - ");
                Serial.print("Messagetype is: ");
                Serial.println(message.type);
              
                // acknoledgment
                if (message.isAck())
                {
                  Serial.println("Got ack from gateway");
                }
              
                // new dim level
                else if (message.type == V_DIMMER or message.type == V_VAR3) {
                  Serial.println("Dimming to ");
                  Serial.println(message.getString());
                  target_dimming = message.getByte();
                  send(lastdimmMsg.set(target_dimming));
              
                  if (!wasOff) {
                    // a new dimmer value also means on, no seperate signal gets send (by domoticz)
                    isOn = true;
                    send(lastisonMsg.set(isOn));
                  }
                }
              
                // on / off message
                else if (message.type == V_STATUS or message.type == V_VAR2) {
                  Serial.print("Turning light ");
              
                  isOn = message.getInt();
              
                  if (isOn) {
                    Serial.println("on");
                    wasOff = false;
                  } else {
                    Serial.println("off");
                  }
                  send(lastisonMsg.set(isOn));
                }
              
                // new color value
                else if (message.type == V_RGBW or message.type == V_VAR1) {
                  const char * rgbvalues = message.getString();
                  send(lastvalueMsg.set(rgbvalues));
                  inputToRGBW(rgbvalues);
                  if (!wasOff) {
                    // a new color also means on, no seperate signal gets send (by domoticz); needed e.g. for groups
                    isOn = true;
                    send(lastisonMsg.set(isOn));
                  }
                }
              }
              
              // this gets called every INTERVAL milliseconds and updates the current pwm levels for all colors
              void updateLights() {
                int convertedvalue=0;
                // update pin values -debug
                //Serial.println(greenval);
                //Serial.println(redval);
                //Serial.println(blueval);
                //Serial.println(whiteval);
              
                //Serial.println(target_greenval);
                //Serial.println(target_redval);
                //Serial.println(target_blueval);
                //Serial.println(target_whiteval);
                //Serial.println("+++++++++++++++");
              
                // for each color
                for (int v = 0; v < NUM_CHANNELS; v++) {
                  if (values[v] < target_values[v]) {
                    values[v] += STEP;
                    if (values[v] > target_values[v]) {
                      values[v] = target_values[v];
                    }
                  }
              
                  if (values[v] > target_values[v]) {
                    values[v] -= STEP;
                    if (values[v] < target_values[v]) {
                      values[v] = target_values[v];
                    }
                  }
                }
              
              
                // dimming
                if (dimming < target_dimming) {
                  dimming += STEP;
                  if (dimming > target_dimming) {
                    dimming = target_dimming;
                  }
                }
                if (dimming > target_dimming) {
                  dimming -= STEP;
                  if (dimming < target_dimming) {
                    dimming = target_dimming;
                  }
                }
              
                /*
                  // debug - new values
                  Serial.println(greenval);
                  Serial.println(redval);
                  Serial.println(blueval);
                  Serial.println(whiteval);
              
                  Serial.println(target_greenval);
                  Serial.println(target_redval);
                  Serial.println(target_blueval);
                  Serial.println(target_whiteval);
                  Serial.println("+++++++++++++++");
                */
              
                // set actual pin values
                for (int i = 0; i < NUM_CHANNELS; i++) {
                  if (isOn) {
                    // normal fading
                    //analogWrite(channels[i], dimming / 100.0 * values[i]);
                    //Fading with corrected values see https://diarmuid.ie/blog/pwm-exponential-led-fading-on-arduino-or-other-platforms/
                    analogWrite(channels[i], dimming / 100.0 * converted_values[values[i]]);
                    
                  } else {
                    analogWrite(channels[i], 0);
                  }
                }
              }
              
              // converts incoming color string to actual (int) values
              // ATTENTION this currently does nearly no checks, so the format needs to be exactly like domoticz sends the strings
              void inputToRGBW(const char * input) {
                Serial.print("Got color value of length: ");
                Serial.println(strlen(input));
              
                if (strlen(input) == 6) {
                  Serial.println("new rgb value");
                  target_values[0] = fromhex (& input [0]);
                  target_values[1] = fromhex (& input [2]);
                  target_values[2] = fromhex (& input [4]);
                  target_values[3] = 0;
                } else if (strlen(input) == 9) {
                  Serial.println("new rgbw value");
                  target_values[0] = fromhex (& input [1]); // ignore # as first sign
                  target_values[1] = fromhex (& input [3]);
                  target_values[2] = fromhex (& input [5]);
                  target_values[3] = fromhex (& input [7]);
                } else {
                  Serial.println("Wrong length of input");
                }
              
              
                Serial.print("New color values: ");
                Serial.println(input);
              
                for (int i = 0; i < NUM_CHANNELS; i++) {
                  Serial.print(target_values[i]);
                  Serial.print(", ");
                }
              
                Serial.println("");
                Serial.print("Dimming: ");
                Serial.println(dimming);
              
              }
              
              // converts hex char to byte
              byte fromhex (const char * str)
              {
                char c = str [0] - '0';
                if (c > 9)
                  c -= 7;
                int result = c;
                c = str [1] - '0';
                if (c > 9)
                  c -= 7;
                return (result << 4) | c;
              }
              
              
              L 1 Reply Last reply
              0
              • J Jan Gatzke

                @LastSamurai

                Yes, I did! This sketch is working for me:

                /**
                  Based on the MySensors Project: http://www.mysensors.org
                
                  This sketch controls a (analog)RGBW strip by listening to new color values from a (domoticz) controller and then fading to the new color.
                
                  Version 1.1 - Added save/restore of values to/from controller, removed non linear fading code
                  Version 1.0 - Changed pins and gw definition
                  Version 0.9 - Oliver Hilsky
                
                **/
                #define MY_DEBUG
                
                #define SN   "RGBW 01"
                #define SV   "1.1"
                #define MY_RADIO_NRF24
                #define MY_PARENT_NODE_ID 10
                // change the pins to free up the pwm pin for led control
                #define MY_RF24_CE_PIN 4 //<-- NOTE!!! changed, the default is 9
                #define MY_RF24_CS_PIN 10 // default is 10
                // Set LOW transmit power level as default, if you have an amplified NRF-module and
                // power your radio separately with a good regulator you can turn up PA level.
                #define MY_RF24_PA_LEVEL RF24_PA_LOW
                //Uncomment to enable repeater mode
                //#define MY_REPEATER_FEATURE
                //Uncomment to assign static node ID
                //#define MY_NODE_ID 9
                
                
                // Load mysensors library
                #include <MySensors.h>
                // Load Serial Peripheral Interface library
                #include <SPI.h>
                
                // Arduino pin attached to driver pins
                #define RED_PIN 3
                #define WHITE_PIN 9
                #define GREEN_PIN 5
                #define BLUE_PIN 6
                #define NUM_CHANNELS 4 // how many channels, RGBW=4 RGB=3...
                #define CHILD_ID 1
                
                // Smooth stepping between the values
                #define STEP 1
                #define INTERVAL 10
                
                MyMessage lastvalueMsg(CHILD_ID, V_VAR1);
                MyMessage lastisonMsg(CHILD_ID, V_VAR2);
                MyMessage lastdimmMsg(CHILD_ID, V_VAR3);
                
                // Stores the current color settings
                byte channels[4] = {RED_PIN, GREEN_PIN, BLUE_PIN, WHITE_PIN};
                byte values[4] = {0, 0, 0, 0};
                byte target_values[4] = {0, 0, 0, 0};
                //Stores corrected values for each step from 0 to 255. See https://diarmuid.ie/blog/pwm-exponential-led-fading-on-arduino-or-other-platforms/
                byte converted_values[256] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,8,8,8,8,8,9,9,9,9,9,10,10,10,10,11,11,11,11,12,12,12,13,13,13,13,14,14,14,15,15,15,16,16,17,17,17,18,18,19,19,20,20,20,21,21,22,22,23,23,24,24,25,26,26,27,27,28,29,29,30,31,31,32,33,34,34,35,36,37,38,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,54,55,56,57,58,60,61,62,64,65,67,68,70,71,73,75,76,78,80,81,83,85,87,89,91,93,95,97,99,101,104,106,108,111,113,116,118,121,123,126,129,132,135,138,141,144,147,150,154,157,161,164,168,171,175,179,183,187,191,195,200,204,209,213,218,223,228,233,238,243,249,255};
                
                
                // stores dimming level
                byte dimming = 100;
                byte target_dimming = 100;
                
                // tracks if the strip should be on of off
                boolean isOn = false;
                // tracks if the strip's last status was off. This overrides isOn at startup
                boolean wasOff = true;
                //tracks if the old values have bben requested from the controller. This prevents the request from being send multipßle times in the main loop.
                boolean valuesrequested = false;
                // time tracking for updates
                unsigned long lastupdate = millis();
                
                void setup()
                {
                  // Set all channels to output (pin number, type)
                  for (int i = 0; i < NUM_CHANNELS; i++) {
                    pinMode(channels[i], OUTPUT);
                  }
                  // debug
                  if (isOn) {
                    Serial.println("RGBW is running...");
                  }
                }
                
                void presentation()  {
                  // Send the sketch version information to the gateway and Controller
                  sendSketchInfo(SN, SV);
                
                  // Register this device as Waterflow sensor
                  present(CHILD_ID, S_RGBW_LIGHT, SN, true);
                }
                
                void loop()
                {
                  if (!valuesrequested) {
                    // get old values if this is just a restart
                    Serial.println("Requesting old values...");
                    //Request RGBW values
                    request( CHILD_ID, V_VAR1 );
                    wait(200);
                    //Request Status
                    request( CHILD_ID, V_VAR2 );
                    wait(200);
                    //Request dimm level
                    request( CHILD_ID, V_VAR3 );
                    valuesrequested = true;
                  }
                
                  // set the new light colors
                  if (millis() > lastupdate + INTERVAL) {
                    updateLights();
                    lastupdate = millis();
                  }
                }
                
                // callback function for incoming messages
                void receive(const MyMessage &message) {
                
                  Serial.print("Got a message - ");
                  Serial.print("Messagetype is: ");
                  Serial.println(message.type);
                
                  // acknoledgment
                  if (message.isAck())
                  {
                    Serial.println("Got ack from gateway");
                  }
                
                  // new dim level
                  else if (message.type == V_DIMMER or message.type == V_VAR3) {
                    Serial.println("Dimming to ");
                    Serial.println(message.getString());
                    target_dimming = message.getByte();
                    send(lastdimmMsg.set(target_dimming));
                
                    if (!wasOff) {
                      // a new dimmer value also means on, no seperate signal gets send (by domoticz)
                      isOn = true;
                      send(lastisonMsg.set(isOn));
                    }
                  }
                
                  // on / off message
                  else if (message.type == V_STATUS or message.type == V_VAR2) {
                    Serial.print("Turning light ");
                
                    isOn = message.getInt();
                
                    if (isOn) {
                      Serial.println("on");
                      wasOff = false;
                    } else {
                      Serial.println("off");
                    }
                    send(lastisonMsg.set(isOn));
                  }
                
                  // new color value
                  else if (message.type == V_RGBW or message.type == V_VAR1) {
                    const char * rgbvalues = message.getString();
                    send(lastvalueMsg.set(rgbvalues));
                    inputToRGBW(rgbvalues);
                    if (!wasOff) {
                      // a new color also means on, no seperate signal gets send (by domoticz); needed e.g. for groups
                      isOn = true;
                      send(lastisonMsg.set(isOn));
                    }
                  }
                }
                
                // this gets called every INTERVAL milliseconds and updates the current pwm levels for all colors
                void updateLights() {
                  int convertedvalue=0;
                  // update pin values -debug
                  //Serial.println(greenval);
                  //Serial.println(redval);
                  //Serial.println(blueval);
                  //Serial.println(whiteval);
                
                  //Serial.println(target_greenval);
                  //Serial.println(target_redval);
                  //Serial.println(target_blueval);
                  //Serial.println(target_whiteval);
                  //Serial.println("+++++++++++++++");
                
                  // for each color
                  for (int v = 0; v < NUM_CHANNELS; v++) {
                    if (values[v] < target_values[v]) {
                      values[v] += STEP;
                      if (values[v] > target_values[v]) {
                        values[v] = target_values[v];
                      }
                    }
                
                    if (values[v] > target_values[v]) {
                      values[v] -= STEP;
                      if (values[v] < target_values[v]) {
                        values[v] = target_values[v];
                      }
                    }
                  }
                
                
                  // dimming
                  if (dimming < target_dimming) {
                    dimming += STEP;
                    if (dimming > target_dimming) {
                      dimming = target_dimming;
                    }
                  }
                  if (dimming > target_dimming) {
                    dimming -= STEP;
                    if (dimming < target_dimming) {
                      dimming = target_dimming;
                    }
                  }
                
                  /*
                    // debug - new values
                    Serial.println(greenval);
                    Serial.println(redval);
                    Serial.println(blueval);
                    Serial.println(whiteval);
                
                    Serial.println(target_greenval);
                    Serial.println(target_redval);
                    Serial.println(target_blueval);
                    Serial.println(target_whiteval);
                    Serial.println("+++++++++++++++");
                  */
                
                  // set actual pin values
                  for (int i = 0; i < NUM_CHANNELS; i++) {
                    if (isOn) {
                      // normal fading
                      //analogWrite(channels[i], dimming / 100.0 * values[i]);
                      //Fading with corrected values see https://diarmuid.ie/blog/pwm-exponential-led-fading-on-arduino-or-other-platforms/
                      analogWrite(channels[i], dimming / 100.0 * converted_values[values[i]]);
                      
                    } else {
                      analogWrite(channels[i], 0);
                    }
                  }
                }
                
                // converts incoming color string to actual (int) values
                // ATTENTION this currently does nearly no checks, so the format needs to be exactly like domoticz sends the strings
                void inputToRGBW(const char * input) {
                  Serial.print("Got color value of length: ");
                  Serial.println(strlen(input));
                
                  if (strlen(input) == 6) {
                    Serial.println("new rgb value");
                    target_values[0] = fromhex (& input [0]);
                    target_values[1] = fromhex (& input [2]);
                    target_values[2] = fromhex (& input [4]);
                    target_values[3] = 0;
                  } else if (strlen(input) == 9) {
                    Serial.println("new rgbw value");
                    target_values[0] = fromhex (& input [1]); // ignore # as first sign
                    target_values[1] = fromhex (& input [3]);
                    target_values[2] = fromhex (& input [5]);
                    target_values[3] = fromhex (& input [7]);
                  } else {
                    Serial.println("Wrong length of input");
                  }
                
                
                  Serial.print("New color values: ");
                  Serial.println(input);
                
                  for (int i = 0; i < NUM_CHANNELS; i++) {
                    Serial.print(target_values[i]);
                    Serial.print(", ");
                  }
                
                  Serial.println("");
                  Serial.print("Dimming: ");
                  Serial.println(dimming);
                
                }
                
                // converts hex char to byte
                byte fromhex (const char * str)
                {
                  char c = str [0] - '0';
                  if (c > 9)
                    c -= 7;
                  int result = c;
                  c = str [1] - '0';
                  if (c > 9)
                    c -= 7;
                  return (result << 4) | c;
                }
                
                
                L Offline
                L Offline
                LastSamurai
                Hardware Contributor
                wrote on last edited by
                #67

                @Jan-Gatzke Thanks, I'll try that later although it doesn't look much different from mine. May I ask why you are using V_VAR1/2 types in your sketch? And why you send answer messages? Are you using home assistant (thats the only one where this is need imho)?

                J 1 Reply Last reply
                0
                • L LastSamurai

                  @Jan-Gatzke Thanks, I'll try that later although it doesn't look much different from mine. May I ask why you are using V_VAR1/2 types in your sketch? And why you send answer messages? Are you using home assistant (thats the only one where this is need imho)?

                  J Offline
                  J Offline
                  Jan Gatzke
                  wrote on last edited by
                  #68

                  @LastSamurai

                  I am using Domoticz. This was the only way reading initial values from the controller. Directly requesting the value of a child did not work for me. Meanwhile MySensors support in Domoticz seems extremly bugy and uncomplete to me. I am going to give OpenHAB2 a try.

                  L 1 Reply Last reply
                  0
                  • J Jan Gatzke

                    @LastSamurai

                    I am using Domoticz. This was the only way reading initial values from the controller. Directly requesting the value of a child did not work for me. Meanwhile MySensors support in Domoticz seems extremly bugy and uncomplete to me. I am going to give OpenHAB2 a try.

                    L Offline
                    L Offline
                    LastSamurai
                    Hardware Contributor
                    wrote on last edited by
                    #69

                    @Jan-Gatzke Ah ok nice to know. I am facing the same problem. RGBW is not that well supported in domoticz. I am currently trying to switch to openhab2 but having some problems with my RGBW nodes there too. Development on the plugin seems to be very active though. If you want to follow the discussion have a look at the forum thread here or on github ;)
                    Once I got everything up and running in openhab I'll post an update here.

                    Meanwhile the newest sketch from my github should work with Home assistant too.

                    1 Reply Last reply
                    0
                    • Sergio RiusS Offline
                      Sergio RiusS Offline
                      Sergio Rius
                      wrote on last edited by
                      #70

                      I just assembled my first OH! My... :grinning: board and realized that the V2 sketch doesn't work for me.
                      Anyways I'm posting a sample sketch for testing the board:

                      #define RED_PIN 3
                      #define GREEN_PIN 5
                      #define BLUE_PIN 6
                      #define WHITE_PIN 9
                      
                      #define ON 100 // Please, don't burn my eyes
                      #define OFF 0
                      
                      #define ON_INTERVAL (3*1000ul)
                      
                      void setup() {
                        // Setting pins to output and low is not required for analogWrite.
                          Serial.begin(115200);
                      }
                      
                      void loop() {
                          analogWrite(RED_PIN, ON);
                          Serial.println(F("**RED**"));
                          delay(ON_INTERVAL);
                          analogWrite(RED_PIN, OFF);
                          analogWrite(GREEN_PIN, ON);
                          Serial.println(F("**GREEN**"));
                          delay(ON_INTERVAL);
                          analogWrite(GREEN_PIN, OFF);
                          analogWrite(BLUE_PIN, ON);
                          Serial.println(F("**BLUE**"));
                          delay(ON_INTERVAL);
                          analogWrite(BLUE_PIN, OFF);
                          analogWrite(WHITE_PIN, ON);
                          Serial.println(F("**WHITE**"));
                          delay(ON_INTERVAL);
                          analogWrite(WHITE_PIN, OFF);
                      }
                      
                      L 1 Reply Last reply
                      1
                      • Sergio RiusS Sergio Rius

                        I just assembled my first OH! My... :grinning: board and realized that the V2 sketch doesn't work for me.
                        Anyways I'm posting a sample sketch for testing the board:

                        #define RED_PIN 3
                        #define GREEN_PIN 5
                        #define BLUE_PIN 6
                        #define WHITE_PIN 9
                        
                        #define ON 100 // Please, don't burn my eyes
                        #define OFF 0
                        
                        #define ON_INTERVAL (3*1000ul)
                        
                        void setup() {
                          // Setting pins to output and low is not required for analogWrite.
                            Serial.begin(115200);
                        }
                        
                        void loop() {
                            analogWrite(RED_PIN, ON);
                            Serial.println(F("**RED**"));
                            delay(ON_INTERVAL);
                            analogWrite(RED_PIN, OFF);
                            analogWrite(GREEN_PIN, ON);
                            Serial.println(F("**GREEN**"));
                            delay(ON_INTERVAL);
                            analogWrite(GREEN_PIN, OFF);
                            analogWrite(BLUE_PIN, ON);
                            Serial.println(F("**BLUE**"));
                            delay(ON_INTERVAL);
                            analogWrite(BLUE_PIN, OFF);
                            analogWrite(WHITE_PIN, ON);
                            Serial.println(F("**WHITE**"));
                            delay(ON_INTERVAL);
                            analogWrite(WHITE_PIN, OFF);
                        }
                        
                        L Offline
                        L Offline
                        LastSamurai
                        Hardware Contributor
                        wrote on last edited by
                        #71

                        @Sergio-Rius Nice to hear! And good idea with the test sketch.

                        What exactly did not work with my sketch? I would really like to fix it (for others too).

                        Sergio RiusS 2 Replies Last reply
                        0
                        • L LastSamurai

                          @Sergio-Rius Nice to hear! And good idea with the test sketch.

                          What exactly did not work with my sketch? I would really like to fix it (for others too).

                          Sergio RiusS Offline
                          Sergio RiusS Offline
                          Sergio Rius
                          wrote on last edited by Sergio Rius
                          #72

                          @LastSamurai I'm using Domoticz. With your sketch, turning on and off worked.
                          But whenever it had any rgb value, the white light was always 100% on. The RGB leds where all three lit at a time and never more than 20% but slightly responded to dimming control.

                          The above code from @Jan-Gatzke works flawlessy. Even turns the white leds on when reaching the white band on the gradient.
                          Only I would like it to not turn off the color leds until the selected color is totally or almost white, so we could white-wash the selection.

                          Oh, men... soldering those mosfets turned around was so difficult. :) I recommend the next who buys boards to use the new designs.

                          Give me some time and I'll give a turn to the sketch. But I'm still working on the "water-heating-solar-controller", and still have to assemble the energy monitor board, and do something with the meteo board.

                          1 Reply Last reply
                          0
                          • L LastSamurai

                            @Sergio-Rius Nice to hear! And good idea with the test sketch.

                            What exactly did not work with my sketch? I would really like to fix it (for others too).

                            Sergio RiusS Offline
                            Sergio RiusS Offline
                            Sergio Rius
                            wrote on last edited by Sergio Rius
                            #73

                            @LastSamurai I have some doubts on this code, can I ask you?
                            The change between color values is done by a fade, and I understand that you don't want a linear change but an exponential one. Right?

                            One doubt i have is that I'm seeing that the fade is accomplished using a conversion array. So you are doing variable steps depending on the difference of value for each channel. Wouldn't be preferable to always take the same amount of time/steps doing the change?

                            Wouldn't be better to divide the difference for each value on the same steps and then doing the transformation. Then could be fixed without an array.

                            Sorry if I wrote something wrong. My english it's not so good.

                            J 1 Reply Last reply
                            0
                            • Sergio RiusS Sergio Rius

                              @LastSamurai I have some doubts on this code, can I ask you?
                              The change between color values is done by a fade, and I understand that you don't want a linear change but an exponential one. Right?

                              One doubt i have is that I'm seeing that the fade is accomplished using a conversion array. So you are doing variable steps depending on the difference of value for each channel. Wouldn't be preferable to always take the same amount of time/steps doing the change?

                              Wouldn't be better to divide the difference for each value on the same steps and then doing the transformation. Then could be fixed without an array.

                              Sorry if I wrote something wrong. My english it's not so good.

                              J Offline
                              J Offline
                              Jan Gatzke
                              wrote on last edited by
                              #74

                              @Sergio-Rius

                              The problem with the linear fading was that a value of 100 almost looked the same as 150. So the goal was to make the fading look more linear. The logarythmic calculations needed for this cannot be done on an atmega 328p. (I tried it)
                              This is why I calculated the values with MS Excel and put them in an array.

                              Making the fading process alway take the same time would be nice. Feel free to post your implementation. ;)

                              Sergio RiusS 1 Reply Last reply
                              0
                              • J Jan Gatzke

                                @Sergio-Rius

                                The problem with the linear fading was that a value of 100 almost looked the same as 150. So the goal was to make the fading look more linear. The logarythmic calculations needed for this cannot be done on an atmega 328p. (I tried it)
                                This is why I calculated the values with MS Excel and put them in an array.

                                Making the fading process alway take the same time would be nice. Feel free to post your implementation. ;)

                                Sergio RiusS Offline
                                Sergio RiusS Offline
                                Sergio Rius
                                wrote on last edited by Sergio Rius
                                #75

                                @Jan-Gatzke @LastSamurai I've been playing with the formula of the blog post written in comments on the sketch and I see that this isn't something trivial.
                                I think the code in the post has a misconception, that using 0-255 he missed that the graph data is not related to time, but pwm value.

                                So a fixed table for conversion between pwm value and appreciated light has to be built. And you also arrived to this conclusion seeing the array.
                                I'm generating the array on the fly using the formula with 256 steps.
                                (In the blog code there's a bug caused by the mean of zero in intervals and the formula that causes max value to being reached. You have to sum one to interval before using on the formula.)

                                I'm now trying to separate a loop for traveling the array that compensates for in between values so it can handle smaller steps->variable interval.

                                Sorry. Just thinking out loud.

                                1 Reply Last reply
                                0
                                • Sergio RiusS Offline
                                  Sergio RiusS Offline
                                  Sergio Rius
                                  wrote on last edited by Sergio Rius
                                  #76

                                  I've been working on an sketch for this board. Somewhere in the path I started adding functionalities and it ended in a library. Perhaps it's way overkill, but I thought that could be easier add it to NodeManager like that.
                                  It's based on the work done here and some more ideas around the network. Thanks to LastSamurai for the board and code and also to Jan.
                                  You can find the sources there: https://github.com/SergioRius/RGBWDimmer

                                  This thing includes a serial manager that I use myself, but you can remove it and delete all the code for debugging, and perhaps add yourselves if necessary.
                                  Just clone the repo or download and install as a zip library on Arduino IDE.
                                  The example works for the OH! MySensors RGBW board as is.

                                  It's very self explanatory in the code, but in essence:

                                  • It can be used stand-alone or with mysensors
                                  • You simply send to the commands and the class does all for you.
                                  • Uses a non blocking system for the fading.
                                  • Configurable fading time and resolution
                                  • Several configurable fading curves
                                  • Option for gamma (brightness + hue) calibration.

                                  I'm currently debugging the fading curves equations other than linear, as the arduino mcu capabilities are tight and it's so easy to overflow it. Also I'm doing a program for calibrating the hue (arduino with leds and a rotary encoder for manually adjusting), so for now gamma only compensates brightness. You can change the values if you prefer. I'll be a good idea to lower the white channel.

                                  It still lacks some memory optimization, but for now I'm scared about overflows. I got one of those and it was a two days nightmare and I had to revert to ints to get something running.
                                  I'll soon add a stand alone sample and port to NodeManager.
                                  For the while, for using it alone the minimal it's:

                                  #include "RGBWDimmer.h"
                                  RGBWDimmer myDimmer(1, 3, 5, 6, 9);  ///< id (to remove), Red Pin, Green Pin, Blue Pin, White Pin
                                  
                                  bool JustDontBlockLoop = true;
                                  
                                  void loop() {
                                    if(JustDontBlockLoop) {
                                        myDimmer.setNewValues(255, 0, 150, 0);  ///< RGBW decimal values. If you prefer hex, use setNewValuesHex
                                        myDimmer.StartFading();
                                        JustDontBlockLoop = false;
                                    }
                                    myDimmer.loop();
                                  }
                                  

                                  I hope you like it. And if you have any idea for adding functionality, please tell me.

                                  1 Reply Last reply
                                  1
                                  • Sergio RiusS Offline
                                    Sergio RiusS Offline
                                    Sergio Rius
                                    wrote on last edited by
                                    #77

                                    I updated the repo for being easier to download and install.

                                    1 Reply Last reply
                                    0
                                    • L Offline
                                      L Offline
                                      LastSamurai
                                      Hardware Contributor
                                      wrote on last edited by
                                      #78

                                      Wow nice! Might take me some time, but I will take a look at your code (and maybe add some of its features back to my sketches if that fine with you).

                                      Sergio RiusS 1 Reply Last reply
                                      0
                                      • L LastSamurai

                                        Wow nice! Might take me some time, but I will take a look at your code (and maybe add some of its features back to my sketches if that fine with you).

                                        Sergio RiusS Offline
                                        Sergio RiusS Offline
                                        Sergio Rius
                                        wrote on last edited by
                                        #79

                                        @LastSamurai Yes, of course.
                                        Just a question. How did you make the "values curve"? You said in excel and perhaps a graph... did you manage to change graph values and update data in any way?

                                        I've made the sketch for adjusting the gamma values, something with a Serial monitor menu that allows for increasing and decreasing the channels in real time. And adjusted the greens for a better hue (orange being orange, not a greenish yellow) but now I do't know how to adapt the curve.
                                        I refuse to modify the 255 values by hand.

                                        Now I'm making a case for 3d-print. Where do I have to post it, there or in a separate post? I read anything about posts becoming entries at hardware.io and ¿build?

                                        1 Reply Last reply
                                        0
                                        • ThetaDevT Offline
                                          ThetaDevT Offline
                                          ThetaDev
                                          wrote on last edited by
                                          #80

                                          Do you really need an external voltage regulator for this module? I mean the Arduino Pro Mini has its linear regulator already built in. You can only draw about 100ma from it, but wouldn't that be sufficient for the micro, radio and the mosfet gates?

                                          1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          25

                                          Online

                                          11.7k

                                          Users

                                          11.2k

                                          Topics

                                          113.0k

                                          Posts


                                          Copyright 2019 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • MySensors
                                          • OpenHardware.io
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular