function to control an rgb led

Posted on
  • Hi, forgive me for my bad english.

    I'm trying to control a simple RGB led. My actual code is working, but I'd make it more ... fluid:

    function fade(led) {
      for (i=0; i<=255; i++) {
        digitalWrite(led, i);
      }
    }
    

    I call this funtion with the pin number of the led to control. But I'd like an async function that can run a "sequence" of colours while checking in the same time the state of a push button (to turn on/off).

    I'm really not a developper, but I know that someone could help me to finish my little led lamp project for my daughter :)

  • Hi! As you saw, your problem is really that you're not writing async code (plus digitalWrite only takes a digital value, not an analog one). Ideally you'd call analogWrite every so often to update the output

    You probably want something like this:

    var colFrom = [0,0,1]; // blue
    var colTo = [1,0,0]; // red
    var colFade = 0;
    var colors = [
      [0,1,0],
      [1,1,0],
      [0,1,1],
      [0,0,0]
    ];
    
    function onTimer() {
      // fade a bit more...
      colFade += 0.05;
      // we've completed fading
      if (colFade>=1) {
        // try and fade to a new color
        if (colors.length) {
          colFrom = colTo;
          colTo = colors.shift();
          colFade = 0;
        } else {
          // no more colors - stop for now
          colFade = 1;
        }
      }
      // you may not need soft:true - it depends on your board and what pins you're using
      analogWrite(LED1,colFrom[0]*(1-colFade) + colTo[0]*colFade, {soft:true});
      analogWrite(LED2,colFrom[1]*(1-colFade) + colTo[1]*colFade, {soft:true});
      analogWrite(LED3,colFrom[2]*(1-colFade) + colTo[2]*colFade, {soft:true});
    }
    
    function onButton() {
      // add a new, random color
      colors.push([Math.random(),Math.random()­,Math.random()]);
    }
    setInterval(onTimer, 100);
    setWatch(onButton, BTN, {repeat:true, edge:"rising", debounce:50});
    

    This starts off fading through colors, but when you press a button it'll add a new color to the end of colors to fade to

  • wow, i'll test this asap :)

  • it's working but is it possible to fade from 0 (black) to randoms colours automatically ?
    Exemple:

    • Push button --> start led sequence from 0, 0, 0 (R, G, B)
    • calculate new random values for each led
    • fade from 0, 0, 0 to new values a, b, c
    • When fade done, calculate new random values
    • fade from a, b, c to new values d, e, f

    I have a big logical problem for that. I presume that it is not so difficult but I can't really understand how it works !

  • Sure - if you're doing that, it sounds like you don't need the colors array at all.

    • set colFrom to [0,0,0] - to start the sequence from black
    • set colFade to 0 (to reset the fade to start from the beginning)
    • set colTo to [a,b,c]
    • Then, in the if (colFade>=1) if statement, replace what's there with:

      colFade = 0; // restart fade again
      colFrom = colTo; // fade from what we faded *to* last time
      colTo = [....]; // your random values
      

    You could also look at using this function: http://www.espruino.com/Reference#l_E_HS­BtoRGB

    Probably what you want is a random hue, but keeping the same brightness and saturation, and that function will help you. You will however need to extract the RGB values from the 24 bit number, which is a bit cryptic:

    var c = E.HSBtoRGB(Math.random(),1,1);
    colTo = [ (c&0xFF)/256, ((c>>8)&0xFF)/256, ((c>>16)&0xFF)/256 ];
    
  • There is something I missed. When the board starts, the led is off. Good. When I press the button, the led start directly and is not fading. The color jump from one to another one

    function setLeds() {
      colFade += 0.05;
      if (colFade>=1) {
        colFade = 0;
        colFrom = colTo;
        var c = E.HSBtoRGB(Math.random(),1,1);
        colTo = [ (c&0xFF)/256, ((c>>8)&0xFF)/256, ((c>>16)&0xFF)/256 ];
      }
      analogWrite(LED1,colFrom[0]*(1-colFade) + colTo[0]*colFade, {soft:true});
      analogWrite(LED2,colFrom[1]*(1-colFade) + colTo[1]*colFade, {soft:true});
      analogWrite(LED3,colFrom[2]*(1-colFade) + colTo[2]*colFade, {soft:true});
    }
    
  • That looks good - but what code have you got for the button press?

  • Sorry for the late answer. I can't access to my personal documents from work.
    Here it i the full code:

    // variables to set
    var wifiSSID = "xxxx";
    var wifiPass = "xxxx";
    
    // do not touch after this line
    var LED1 = D5;
    var LED2 = D14;
    var LED3 = D12;
    var button = D4;
    var colFrom = [0,0,0];
    var colTo = [0,0,0];
    var colFade = 0;
    pinMode(button, 'input_pulldown');
    
    function setLeds() {
      colFade += 0.05;
      if (colFade>=1) {
        colFade = 0;
        colFrom = colTo;
        var c = E.HSBtoRGB(Math.random(),1,1);
        colTo = [ (c&0xFF)/256, ((c>>8)&0xFF)/256, ((c>>16)&0xFF)/256 ];
      }
    
      analogWrite(LED1,colFrom[0]*(1-colFade) + colTo[0]*colFade, {soft:true});
      analogWrite(LED2,colFrom[1]*(1-colFade) + colTo[1]*colFade, {soft:true});
      analogWrite(LED3,colFrom[2]*(1-colFade) + colTo[2]*colFade, {soft:true});
    }
    
    function power(state) {
      if (state === "on") {
        powerState = "on";
        setInterval(setLeds, 500);
      }
      if (state === "off") {
        powerState = "off";
        analogWrite(LED1, false);
        analogWrite(LED2, false);
        analogWrite(LED3, false);
      }
    }
    
    function startServer() {
      // start future http server
      var powerState = "off";
      power("off");
      setWatch(function(){
        if (powerState === "off") {
          power("on");
          powerState = "on";
        } else {
          if (powerState === "on") {
            power("off");
            powerState = "off";
          }
        }
      }, button, {repeat:true, edge:"rising", debounce:50});
    }
    
    function onInit() {
      var wifi = require('Wifi');
      wifi.stopAP();
      wifi.connect(wifiSSID, {password:wifiPass}, function(err, data){
        if (err) {
          print('Error while connecting to access point' + wifiSSID);
          return;
        }
    
        print("connected? err=", err, "info=", wifi.getIP());
        startServer();
      });
    }
    
    E.on('init', onInit());
    save();
    
  • So you're actually using this on an ESP8266? Why did you post on the official boards forum?

  • Hello,

    I use nodemcu. Ordinary I post in other boards topic. For this I have done a mistake.

    Sorry for that.

  • Ok, no problem. Obviously it takes a while for me to write that code for you, and I can't afford to keep doing that for folks that aren't using official boards :) I'll move this to the 'General' other boards section.

    Some obvious stuff I notice:

    • Calling power("on") twice will set up 2 intervals - so you need to either only call setInterval once at the start, or make sure that power("off") clears the interval
    • E.on('init', onInit()); is broken - just remove that line
    • save() shouldn't be on the right-hand side of the IDE, it could cause problems
  • hello,

    I've just make corrections suggested. It's working. But the colors jumps from color to another one. How can I make a fading animation between colors ?

    // variables to set
    var wifiSSID = "xxxx";
    var wifiPass = "xxxx";
    
    // do not touch after this line
    var LED1 = D5;
    var LED2 = D14;
    var LED3 = D12;
    var button = D4;
    var colFrom = [0,0,0];
    var colTo = [0,0,0];
    var colFade = 0;
    var powerState = "off";
    pinMode(button, 'input_pulldown');
    
    function setLeds() {
      colFade += 0.5;
      if (colFade>=1) {
        colFade = 0;
        colFrom = colTo;
        var c = E.HSBtoRGB(Math.random(),1,1);
        colTo = [ (c&0xFF)/256, ((c>>8)&0xFF)/256, ((c>>16)&0xFF)/256 ];
      }
    
      analogWrite(LED1,colFrom[0]*(1-colFade) + colTo[0]*colFade, {soft:true});
      analogWrite(LED2,colFrom[1]*(1-colFade) + colTo[1]*colFade, {soft:true});
      analogWrite(LED3,colFrom[2]*(1-colFade) + colTo[2]*colFade, {soft:true});
    }
    
    function power(state) {
      if (state === "on") {
        powerState = "on";
        setInterval(setLeds, 500);
      }
      if (state === "off") {
        powerState = "off";
        clearInterval();
        analogWrite(LED1, false);
        analogWrite(LED2, false);
        analogWrite(LED3, false);
      }
    }
    
    function startServer() {
      setWatch(function(){
        if (powerState === "off") {
          power("on");
          powerState = "on";
        } else {
          if (powerState === "on") {
            power("off");
            powerState = "off";
          }
        }
      }, button, {repeat:true, edge:"rising", debounce:50});
    }
    
    function onInit() {
      var wifi = require('Wifi');
      wifi.stopAP();
      wifi.connect(wifiSSID, {password:wifiPass}, function(err, data){
        if (err) {
          print('Error while connecting to access point' + wifiSSID);
          return;
        }
    
        print("connected? err=", err, "info=", wifi.getIP());
        startServer();
      });
    }
    power('off');
    
  • @azer

    Have you attempted this tutorial yet?
    http://www.espruino.com/Individually+Add­ressable+LEDs

    It has a fading effect between colors, similar to that which you might be seeking.

    @Gordon has spent a considerable amount of his valuable time coding a framework for you to hang your work on. It would be prudent to blend the above tutorial example into your work to get the desired effect you are after.

    It is difficult for anyone to write a solution to an idea you have firmly cemented in your mind. A bit of study should provide the insight to a solution to that which you envision. I'm sure you will be proud of your own effort once you achieve success.

    “There are no secrets to success. It is the result of preparation, hard work and learning from failure.” - Colin Powell

  • Hi. I've already tried lot of tutos found over the net. But there is a lot of them for official espruino boards so it doesn't works on mine. I'm not a big pro developper but i have lots of boards programed by myself. But i never had to use rgb leds with this board.

    I've just tried to control my led using an Arduino Uno. It works very well. So while looking for fading on esp, i found that esp can't use hard pwm. That's why all my test codes doesn't works as expected.

    I have found a soft pwm fonction to do the same work. I'll try it.

    https://www.espruino.com/Software+PWM

    Thank you for all helps @Gordon

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

function to control an rgb led

Posted by Avatar for azer @azer

Actions