Virtual Pins function loop/stop and RGB Strip fade effects

Hello

So I’ve created a code that can auto-change colors of a led strip, fadng through all of them when, using a virtual pin. I have a few problems with it:

1.The fading doesn’t stop if I turn off the virtual button, reading on the web I’ve found out that the problem might be using delay insteam of simple timer. I’m very new to blynk and coding in general and I’d appreciate if someone would help me use the simpletimer function the same way as the delay is used in this code
2. I’d like to make the functon loop until I turn it off, it loops as many times as I turn it on, but keeping the virtual button on would only loop it once

Here’s the code:

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
char auth[] = "xxxx";
const int red=D0;
const int green=D1;
const int blue=D2;
int redVal=0;
int greenVal=0;
int blueVal=0;
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "xxxx";
char pass[] = "xxxx";

>BlynkTimer timer;

>void stop(){
  digitalWrite(red, LOW);
  digitalWrite(green, LOW);
  digitalWrite(blue, LOW);
}

>void rgb(){
  for(redVal=1023; redVal<1024; redVal++){
      analogWrite(red, redVal);
      delay(10);
    }
       for(greenVal=0; greenVal<1024; greenVal++){
      analogWrite(green, greenVal);
      delay(10);
       }
       for(redVal=1023; redVal>=0; redVal--){
      analogWrite(red, redVal);
      delay(10);
       }
       for(blueVal=0; blueVal<1024; blueVal++){
      analogWrite(blue, blueVal);
      delay(10);
       }
       for(greenVal=1023; greenVal>=0; greenVal--){
      analogWrite(green, greenVal);
      delay(10);
       }
       for(redVal=0; redVal<1024; redVal++){
      analogWrite(red, redVal);
      delay(10);
       }
       for(blueVal=1023; blueVal>=0; blueVal--){
      analogWrite(blue, blueVal);
      delay(10);
       }
}

>BLYNK_WRITE(V5)
{
  if(param.asInt() == 1) {     // if Button sends 1
    rgb();             // start the function
  }
  else stop();
}

>void setup()
{
  // Debug console
  Serial.begin(9600);
pinMode(red, OUTPUT);
pinMode(blue, OUTPUT);
pinMode(green, OUTPUT);
  Blynk.begin(auth, ssid, pass);
}

>void loop()
{
  Blynk.run();
  timer.run();  
}

I’m using nodemcu esp8266. Thank you

UPDATE: So I somehow managed to not use delay, I added A LOT of functions and I don’t know if it’s really necessary. Here is the code:

BLYNK_WRITE(V1) { 
  if (param.asInt() == 1) {
    //redVal = 0;
  rgbTimer();
  } else {
    redVal=1023;
    timer.setTimer(1, FadeRedDOWN, 1023);
     greenVal=1023;
    timer.setTimer(1, FadeGreenDOWN, 1023);
    blueVal=1023;
    timer.setTimer(1, FadeBlueDOWN, 1023);
  }
}

>void FadeRedUP()
{
  analogWrite(red, redVal);
  redVal++;
}
void FadeRedDOWN()
{
  analogWrite(red, redVal);
  redVal--;
}
void FadeGreenUP()
{
  analogWrite(green, greenVal);
  greenVal++;
}
void FadeGreenDOWN()
{
  analogWrite(green, greenVal);
  greenVal--;
}
void FadeBlueUP()
{
  analogWrite(blue, blueVal);
  blueVal++;
}
void FadeBlueDOWN()
{
  analogWrite(blue, blueVal);
  blueVal--;
}

>void rgbTimer(){
   redVal=0;
    timer.setTimer(1, FadeRedUP, 1023);
   greenVal=0;
    timer.setTimer(1, FadeGreenUP, 1023);
   redVal=1023;
    timer.setTimer(1, FadeRedDOWN, 1023);
   blueVal=0;
    timer.setTimer(1, FadeBlueUP, 1023);
   greenVal=1023;
    timer.setTimer(1, FadeGreenDOWN, 1023);
   redVal=0;
    timer.setTimer(1, FadeRedUP, 1023);
   blueVal=1023;
    timer.setTimer(1, FadeBlueDOWN, 1023);
}

The problem is all timers in the rgbTimer function start simultaneously and all the LEDs just fade on, none of them fading of until I press the virtual button again. Is there a way to add a delay between them without using delay and without creating more functions? I would like the succeeding one to start when the previous one ended, like when redVal=1023, start increasing greenVal, when greenVal=1023, start decreasing redVal and so on. I’ve tried making a function for every “timer.setTimer(1,FadeUP,1023)” and then add them to “timer.setinterval” but it doesn’t work, and I really thinks there must be a simpler solution to this.

Also is there any way to use a single functior for fading up and one for fading down? Like instead of having FadeRedUP() have FadeUP(int x, int y), where x would be the pin and y the value, like FadeUP(red,redVal). I tried it this way but the function FadeUP(red,redVal) wouldn’t work inside “timer.setTimer”(1,FadeUP(red,redVal),1023).

It is possible to pass parameters through timer but not in the way you think. I worked it out but don’t have my code to hand at the moment. And I only ended up passing a single parameter but I’m sure you could pass more?

I will post what I have up in a few days when I have my code available.

Also I would look into state machines for the fading when a certain value has reached full brightness. Then you can just use a switch case statement to do the control part.

Would you be able to provide me some more info about the switch case statement procedure? I’ve found some things but I can’t seem to wrap my head around it. Looking forward for the way you did you project, would be a great help. Thank you

@dragos

could you try that ?

void rgb() {
  if (btnState == 1) {
    timer.setTimeout(1000L, []() { // you have to ajust 1000L according your need
      for (redVal = 1023; redVal < 1024; redVal++) {
        analogWrite(red, redVal);
      }

      timer.setTimeout(1000L, []() {
        for (greenVal = 0; greenVal < 1024; greenVal++) {
          analogWrite(green, greenVal);
        }
        timer.setTimeout(1000L, []() {
          for (redVal = 1023; redVal >= 0; redVal--) {
            analogWrite(red, redVal);
          }
          timer.setTimeout(1000L, []() {
            for (blueVal = 0; blueVal < 1024; blueVal++) {
              analogWrite(blue, blueVal);
            }
            timer.setTimeout(1000L, []() {
              for (greenVal = 1023; greenVal >= 0; greenVal--) {
                analogWrite(green, greenVal);
              }
              timer.setTimeout(1000L, []() {
                for (redVal = 0; redVal < 1024; redVal++) {
                  analogWrite(red, redVal);
                }
                timer.setTimeout(1000L, []() {
                  for (blueVal = 1023; blueVal >= 0; blueVal--) {
                    analogWrite(blue, blueVal);
                  }

                });  // END Timer Function
              });  // END Timer Function
            });  // END Timer Function
          });  // END Timer Function
        });  // END Timer Function
      });  // END Timer Function
    });  // END Timer Function
    
  } else {
    break; //if btnState =0
  }
}

BLYNK_WRITE(V5)
{
  int btnState = param.asInt(); // Button sends 1 or 0
  rgb();             // start the function
}
1 Like

Thanks a lot! I’ve made some changes and it kind of works. Here’s my code, using yours:

``BLYNK_WRITE(V2)
{
int btnState = param.asInt(); // Button sends 1 or 0
if (btnState == 1) {
rgb(); // start the function
}
else
digitalWrite(red, LOW);
digitalWrite(green, LOW);
digitalWrite(blue, LOW);
}
void rgb() {

timer.setTimeout(1000L, []() { // you have to ajust 1000L according your need
  for (redVal = 1023; redVal < 1024; redVal++) {
    analogWrite(red, redVal);
  }

  timer.setTimeout(1000L, []() {
    for (greenVal = 0; greenVal < 1024; greenVal++) {
      analogWrite(green, greenVal);
    }
    timer.setTimeout(1000L, []() {
      for (redVal = 1023; redVal >= 0; redVal--) {
        analogWrite(red, redVal);
      }
      timer.setTimeout(1000L, []() {
        for (blueVal = 0; blueVal < 1024; blueVal++) {
          analogWrite(blue, blueVal);
        }
        timer.setTimeout(1000L, []() {
          for (greenVal = 1023; greenVal >= 0; greenVal--) {
            analogWrite(green, greenVal);
          }
          timer.setTimeout(1000L, []() {
            for (redVal = 0; redVal < 1024; redVal++) {
              analogWrite(red, redVal);
            }
            timer.setTimeout(1000L, []() {
              for (blueVal = 1023; blueVal >= 0; blueVal--) {
                analogWrite(blue, blueVal);
              }

            });  // END Timer Function
          });  // END Timer Function
        });  // END Timer Function
      });  // END Timer Function
    });  // END Timer Function
  });  // END Timer Function
});  // END Timer Function
}

The RGB functions works, it changes colors consecutively, just as I wanted to, the only problem being they don’t fade, they just turn on and off after the specified time. Any workaround for this?

If you are willing to and you have the time, would you be able to explain the timer function that you used? As I see it, all of them should start simultaneously 1 second after pressing the button, I don’t really understand it.

Also, the break function doesn’t work, I’ve replaced it with digitalWrite(‘color’ , LOW) so each color would be turned off if the button is switched off, but it works properly only after the function ends (it only repeats once). If I try to stop it while the function is doing it’s thing, colors just flash randomly or some random color would stay up.

I’d also like it to repeat forever until I turn it off. This will be done by adding a timer functon inside my BLYNK_WRITE(V2) and telling it to repeat void rgb,right?

Thanks a lot for taking your time helping me, really been a great help.

1 Like

The timer function executes the code inside the curly braces after the time specified when doing it that way.

It saves creating a separate void function and calling it.

As for repeating it. I would create a global bool and use it inside your RGB function.

bool repeat = false;

BLYNK_WRITE(V2)
{
    repeat= param.asInt();
}

void rgb()
{
    If (repeat)
    {
        // code here
    }
}

*sorry for the formatting I’m replying on my phone.

1 Like

And about the fading effects between colors, any idea about that? As I said they only work on/off, no fading.

Ah yes sorry about that. The code is incrementing the value each cycle but because there is no delay in that code then it will look like it’s going from off to on instantly.

You would need another delay of some kind in there. I’ll have a think what you can do and let you know.

Why the “for next” function don’t run???

please insert serial.print and see what happens
maybe timer.setTimeout(1000L… is too short ?

for (greenVal = 0; greenVal < 1024; greenVal++) {
      Serial.println(greenVal);
      analogWrite(green, greenVal);
  }

I’ve personally not tried the inline timer fucntion code before so I’m not exaclty sure how it adds the timers to the callback list and executes exactly so if you could try adding this for each colour and let us know:

~ snip ~
timer.setTimeout(1000L, []() {
  for (redVal = 1023; redVal < 1024; redVal++) {
    timer.setTimeout(10L, []() { // <--- new code to add
      analogWrite(red, redVal);
    }); // <--- new code to add
  }
  timer.setTimeout(1000L, []() {
~ snip ~

If this code only carries on executing after each timer has run then this should add a 10ms delay before each analog write which should give you a fade effect.

If all leds are coming on instantly again then we can look at doing a state machine.

@dragos :wink:

Video_2019-04-29_120251

1 Like

Sorry for the long reply time. @Blynk_Coeur it doesn’t work. Seems like for green it goes up from 50% or so to 100% then suddenly turn off. The rest just turn on/off after the set interval. Also, after completing the function it gets tuck on blue and red. I can’t nteract in any way with the board unless I restart it. I’ll post the function below:

void rgb() {

    timer.setTimeout(1000L, []() { // you have to ajust 1000L according your need
      for (redVal = 1023; redVal < 1024; redVal++) {
        Serial.println(redVal);
        analogWrite(red, redVal);
      }

      timer.setTimeout(1000L, []() {
        for (greenVal = 0; greenVal < 1024; greenVal++) {
          Serial.println(greenVal);
          analogWrite(green, greenVal);
        }
        timer.setTimeout(1000L, []() {
          for (redVal = 1023; redVal >= 0; redVal--) {
            Serial.println(redVal);
            analogWrite(red, redVal);
          }
          timer.setTimeout(1000L, []() {
            for (blueVal = 0; blueVal < 1024; blueVal++) {
              Serial.println(blueVal);
              analogWrite(blue, blueVal);
            }
            timer.setTimeout(1000L, []() {
              for (greenVal = 1023; greenVal >= 0; greenVal--) {
                Serial.println(greenVal);
                analogWrite(green, greenVal);
              }
              timer.setTimeout(1000L, []() {
                for (redVal = 0; redVal < 1024; redVal++) {
                  Serial.println(redVal);
                  analogWrite(red, redVal);
                }
                timer.setTimeout(1000L, []() {
                  for (blueVal = 1023; blueVal >= 0; blueVal--) {
                    Serial.println(blueVal);
                    analogWrite(blue, blueVal);
                  }

                });  // END Timer Function
              });  // END Timer Function
            });  // END Timer Function
          });  // END Timer Function
        });  // END Timer Function
      });  // END Timer Function
    });  // END Timer Function
    
  }

Would you be able to post the code used in the gif that you posted above?

@JustBertC tried adding the code to each color… still no good results. Only on/off after specified interval.

1 Like

yes I’ll post my code tomorrow.
it’s a little bit different than yours.
but my code works well with led widget.
I can’t test it with real LEDs

@dragos


//init section
#include <WidgetRTC.h>
BlynkTimer timer,
WidgetRTC rtc;
WidgetLED red(11);
WidgetLED green(12);
WidgetLED blue(13);

int btnState;
int redVal, greenVal, blueVal;

//setup section
RGBTimer = timer.setInterval(20000L, rgb);
timer.disable(RGBTimer);

//function
void rgb() {
  Serial.print("btnState ");
  Serial.println(btnState);

  //increase
  timer.setTimeout(1000L, []() { // you have to ajust 1000L according your need
    for (redVal = 0; redVal < 256; redVal = redVal + 10) {
      red.setValue(redVal); //v11
      Serial.print("redVal ");
      Serial.println(redVal);
    }
    timer.setTimeout(1000L, []() {
      for (greenVal = 0; greenVal < 256; greenVal = greenVal + 10) {
        green.setValue(greenVal);//V12
        Serial.print("greenVal ");
        Serial.println(greenVal);
      }
      timer.setTimeout(1000L, []() {
        for (blueVal = 0; blueVal < 256; blueVal = blueVal + 10) {
          blue.setValue(blueVal);//21
          Serial.print("blueVal ");
          Serial.println(blueVal);
        }

        //Decrease
        timer.setTimeout(1000L, []() {
          for (redVal = 255; redVal >= 0; redVal = redVal - 10) {
            red.setValue(redVal);
            Serial.print("redVal ");
            Serial.println(redVal);
          }
          timer.setTimeout(1000L, []() {
            for (greenVal = 255; greenVal >= 0; greenVal = greenVal - 10) {
              green.setValue(greenVal);
              Serial.print("greenVal ");
              Serial.println(greenVal);
            }
            timer.setTimeout(1000L, []() {
              for (blueVal = 255; blueVal >= 0; blueVal = blueVal - 10) {
                blue.setValue(blueVal);
                Serial.print("blueVal ");
                Serial.println(blueVal);
              }
            });  // END Timer Function
          });  // END Timer Function
        });  // END Timer Function
      });  // END Timer Function
    });  // END Timer Function
  });  // END Timer Function

}

//start / stop button
BLYNK_WRITE(V47)
{
  btnState = param.asInt(); // Button sends 1 or 0
  Serial.println("btnstate push");
  if (btnState == 1) {
    timer.enable(RGBTimer);           // start the function
  } else {
    btnState = 0;
    timer.disable(RGBTimer);
    timer.setTimeout(20000L, []() {
      red.setValue(0);
      green.setValue(0);
      blue.setValue(0);
    });  // END Timer Function
  }
}

void loop() {
  timer.run();
  Blynk.run();
}

After a quick search online I found this code:

int value, value2 ;
int ledpin = 10;      // light connected to digital pin 10
int ledpin2 = 11;    // light connected to digital pin 11
long time=0;

int periode = 2000;
int displace = 500;

void setup() 
{ 
 // nothing for setup 
} 

void loop() 
{ 
 time = millis();
 value = 128+127*cos(2*PI/periode*time);
 value2 = 128+127*cos(2*PI/periode*(displace-time));
 analogWrite(ledpin, value);           // sets the value (range from 0 to 255) 
 analogWrite(ledpin2, value2);           // sets the value (range from 0 to 255) 
}

I haven’t tested it but apparently gives a nice fade function (and doesn’t use delay so won’t interrupt void loop)

Found it here, credit to author:
https://forum.arduino.cc/index.php?topic=12004.0

yes but don’t work with blynk because of the loop !
:wink:

Nope, would need to put it inside a timer function and run it every 50ms or so.

yes you can , but @dragos need help, not a code from Google :joy:
I’m not sure this code corresponds to what he wants to do.

1 Like

That is very true. It’s hard to write the code on a phone though :crazy_face: haha!