Sequence of time-dependent operations

Hi to all.
This is my very first experience with Blynk and Arduino IDE, so i try to expose my problem in the better way.

This is my configuration:

  • Wemos D1 Mini (esp8266)
  • 8-channel relay board (i use only 6)

I succesfully connect Wemos to Server and i set each relay with a specific Virtual Pin using this format:

    BLYNK_WRITE(VPin) 
    {
        Relay1State = param.asInt();
        digitalWrite(DigitalPin,Relay1State );
    }

In this way, i can command each relay through Virtual Pin. This is fantastic and for me is a great conquest.

Now i want create a routine in which, activating a Virtual Switch, the Wemos execute this sequence:
A) Activate Relay 1 For 5 seconds. Then Deactivate .
B) Activate Relay 2 For 8 seconds
C) Activate Relay 1 For 5 seconds
D) Activate Relay 3 until i OFF the virtual Switch

The next step will probabily create sliders for time input and imposing a for cycle for A-B-C actions. But not now: proceed step by step

I tried to read FAQ, old topics and guide related to Blynk.Timer but i don’t understand how can i create this sequence.

I tried to use setTimeout without success (i attacch a part of the code):

    BLYNK_WRITE(VPinSequence) {
      if (param.asInt()==1)
    			timer.setTimeout(5000L,[](){
          		Relay1State = 1;
    			digitalWrite(Digital1Pin, Relay1State);
          		Blynk.virtualWrite(VPin1, Relay1State);
        });
    			Relay1State = 0;	
    			digitalWrite(Digital1Pin, Relay1State);
    			Blynk.virtualWrite(VPin1, Relay1State);				
    }

I need some help :sleepy:

Okay, what your trying to do is quite tricky when using timeout timers.

First of all, it helps if you use tab indents in a sensible way when you write your code, and it also helps to add lots of comments (these are good things to do anyway, it make your code more readable).

This is what the code for a single timeout timer would look like…

BLYNK_WRITE(VPinSequence)
{
  if (param.asInt()==1)
  {   
    // we do the following if the VPinSequence switch widget is ON...
    
    // your code in here to Activate Relay 1 For 5 seconds...
    Relay1State = 1;
    digitalWrite(Digital1Pin, Relay1State);
    Blynk.virtualWrite(VPin1, Relay1State);    
    
    // now that Relay1 is on, we start a timer...
    timer.setTimeout(5000L,[]()
    {
    // the following code will execute when the timeout ends...
      //
      Relay1State = 0;  
      digitalWrite(Digital1Pin, Relay1State);
      Blynk.virtualWrite(VPin1, Relay1State);
      // If you wanted to trigger another timeout timer when this one completes
      // then that code would need to go in here...
       
    }); // End of the timeout timer lambda function
  }
  else
  {
    // We get here if the VPinSequence switch widget is OFF...
    // You can add your code in here to turn off all of your relays
  }
}

As you can see, you were previously turning your relay ON in the part of the code that is executed when the timeout timer ends.
The whole idea of using BlynkTimer in a timeout mode is that it’s non-blocking, but this causes a problem for you. Once the timer is started, the rest of the sketch is executed, and in your case this meant that these three lines of code were executed, which turned the relay OFF…

So, I’d imagine that when you turned the widget button on, the relay went off, then came on after 5 seconds and stayed on.

This non-blocking feature is also going to mean that you can’t simply add one timeout timer after another, they have to be nested within each other - I’ve added a comment saying:

  // If you wanted to trigger another timeout timer when this one completes
  // then that code would need to go in here...

This obviously gets very messy, even if you’ve structured and commented the code well.

I’ve explained this issue with an example in the “Timeout Timers” section of this tutorial…

There is also another potential issue. What do you want to happen if you turn the widget button off, before the sequence has ended and you’ve reached point “D” in your sequence?
If you’re happy to wait until the full 18 second sequence has ended then that’s fine, otherwise your code will need more refinements.

So, the simplest solution is not to use the Lambda function when using your timeout timers. Instead simply have the timers call a function when they have completed, and use that function to call the next timer in the sequence. Like this,

BLYNK_WRITE(VPinSequence)
{
  if (param.asInt()==1)
  {   
    // we do the following if the VPinSequence switch widget is ON...
    
    // call the function that starts the cascading sequnece of timers
    relay1_on();
  }
  else
  {
    // We get here if the VPinSequence switch widget is OFF...
    // You can add your code in here to turn off all of your relays
  }
}

void relay1_on()
{
  // start by turning relay 1 on...  
  
  Relay1State = 1;
  digitalWrite(Digital1Pin, Relay1State);
  Blynk.virtualWrite(VPin1, Relay1State);   
  
  // then start a timer that will call the relay1_off_relay2_on function when it completes...
  timer.setTimeout(5000L, relay1_off_relay2_on);
}

void relay1_off_relay2_on()
{
  // start by turning relay 1 off...
  Relay1State = 0;  
  digitalWrite(Digital1Pin, Relay1State);
  Blynk.virtualWrite(VPin1, Relay1State);
  
  // then turn relay 2 on...
  Relay2State = 1;
  digitalWrite(Digital2Pin, Relay2State);
  Blynk.virtualWrite(VPin2, Relay2State);     
  
  // then start a timer that will call the relay2_off_relay1_on_again function when it completes...  
  timer.setTimeout(8000L, relay2_off_relay1_on_again);  
}

void relay2_off_relay1_on_again()
{
  // start by turning relay 2 off...
  Relay2State = 0;  
  digitalWrite(Digital2Pin, Relay2State);
  Blynk.virtualWrite(VPin2, Relay2State);

  // then turn relay 1 on (again)...
  Relay1State = 1;
  digitalWrite(Digital1Pin, Relay1State);
  Blynk.virtualWrite(VPin1, Relay1State); 
  
  // then start a timer that will call the relay1_off_relay3_on function when it completes...  
  timer.setTimeout(5000L, relay1_off_relay3_on);  
}


void relay1_off_relay3_on()
{
  // start by turning relay 1 off...
  Relay1State = 0;  
  digitalWrite(Digital1Pin, Relay1State);
  Blynk.virtualWrite(VPin1, Relay1State);

  // then turn relay 3 on...
  Relay3State = 1;
  digitalWrite(Digital3Pin, Relay3State);
  Blynk.virtualWrite(VPin3, Relay3State); 
  
  // No timer this time, relay 3 just stays on  
}

Pete.

1 Like

If you’re using the new blynk ( IOT ), then automation is also a very good solution in your case, you can use it to make something like this


without coding.

The final result
https://mega.nz/file/hIEyRYgL#UVxsh0xGy3lhQlKw5p16TWdAyqJajLT3uqlP1rybR5c

1 Like

Thank you @PeteKnight .
The correct solution is the last and i’m writing the code for repeat the state two times befor activating the last relay: in this case i use a lot of void function but maybe it can works.

  • A ON
  • Timeout
  • A OFF - B ON
  • Timeout
  • B OFF - A ON
  • Timeout
  • A OFF - B ON
  • Timeout
  • B OFF - C ON

Tomorrow i will test it.

@John93 thank you for the help. Maybe it’s a good solution and very easy to implement in my case: but for the next step i would use time as variable choosing through slider widget. I don’t know if there is the possibility to insert time as variable instead fix number.

If you would like to automation then it’s too easy, you can simply go to the automation configuration and change the delay time as you wish.

Hi @PeteKnight ,
the code works perfectly now! I’m very satisfied. I also add slider to control time variable.

But, there is a problem: if i change the status of the VPin general from 1 to 0, the sequence continue until Blynk actives the last relay C.

I want interrupt the sequence and LOW all the relay if i change the status of VPinSequence.
Maybe i can add an if statement that read the status of VPinSequence in each on/off function?

So, how can i force the stop of the sequence?

I suspected that you’d want to do that. Here’s what you do…

Create a global Boolean variable, let’s call it run.

Set run = true when you turn the widget on, and run = false when you turn it off.
You’ll also turn all of your relays off when the widget is off.

Before you execute each of your cascading timers, you check if(run == true).

This prevents the next cascaded timer function being called if the widget has been turned off.

Pete.

It’s working. :heart_eyes:
Thank you!

1 Like