Delay() issue in Blynk 2.0

In my alarm project, I need to blip my alarm buzzer once when the alarm is switched on, and twice when it is swiched off.
In my 'legacy Blynk’code, which works fine, I use the following code (yes I know that the use of delay() is naughty, but there is no requirement for other code to be running during this very short period of time):

void singleBleep() {    // alarm ON    
    digitalWrite(bell,LOW);
    delay(100);
    digitalWrite(bell,HIGH);  
}

void doubleBleep() {     // alarm OFF
    digitalWrite(bell,LOW);
    delay(100);
    digitalWrite(bell,HIGH);  
    delay(80);
    digitalWrite(bell,LOW);
    delay(100);
    digitalWrite(bell,HIGH);  
}

As stated, this works fine in legacy Blynk. But the time period entered into the delay() function seems to have no effect in Blynk 2.0.
No matter whether I enter delay(100) or delay(10000), all I get is a really fast blip.

Is there something in Blynk 2.0 which is causing this?

Don’t use Delay, try Blynktimer.

Sorry, this is not a question about what else to try. It’s more about whether there is an issue with the delay() function in Blynk 2.

There’s an issue with using delays period for most things. You got lucky previously.

You might fix the issue by increasing the heartbeat but that isn’t actually solving anything it’s just band aiding the problem.

Blynk should not have any impact on the built-in delay() function. You did not specify the device you’re using, so it’s hard to help

Both wemos d1 mini and NodeMCU devices show the same issue. They work fine with delay() in legacy, but show a minimal time period in Blynk 2.
What’s the best way to work around this using Blynk Timer, then? Any guidance on the best code?

Try that

timer.setTimeout(100, []() {
   digitalWrite(bell,LOW);
    timer.setTimeout(100, []() {
     digitalWrite(bell,HIGH);  
      timer.setTimeout(100, []() {
       digitalWrite(bell,LOW);
        timer.setTimeout(100, []() {
         digitalWrite(bell,HIGH);  
          });  // END Timer Function
        });  // END Timer Function
    });  // END Timer Function
  });  // END Timer Function
2 Likes

The code works like a dream. And so much simpler than my attempt!

Thank you very much, Blynk_Coeur.

1 Like

The code stated earlier works great for that example.
But I have another situation where i really need the effects of the delay() function to stop running any further code until the delay has finished.
Example: my code is for controlling a generator. I need the following sequence - switch on control panel - pause 1 second - switch on heater for x seconds - switch off heater - switch on starter motor for y seconds - switch off starter motor, etc, etc.
This was easily achieved in legacy Blynk where I could switch on a relay, pause via delay() code, then switch off the relay. The delay() function works perfectly for this.
However, as delay() does not seem to work in Blynk 2, I am struggling to understand the code required to pause everything.
Whatever I am attempting to write might throw in a delay before switching off the same relay, but in the meantime the next process has already started. ie heater relay on, starter relay on, heater relay off after x seconds, starter relay off after y seconds. This tries to start the generator before the heater has had a chance to work!
Please could some-one help me with this (and save what is left of my sanity)?

could you provide the code with delay() or a block diagram because I don’t understand the logic of this example :thinking:

This is the code for starting (and monitoring) the engine:

void startGen() {
      digitalWrite(relayA, LOW); // switch on generator panel
      Serial.println("Generator panel ON");
      Blynk.virtualWrite(V0,1);
      delay(500);
      digitalWrite(relayA, HIGH);
      delay(1000);

      panelSensorState = digitalRead(panelSensor); 
      engineSensorState = digitalRead(engineSensor);
       if (panelSensorState == HIGH) {
           ledPanel.on();
         }
       else {
           ledPanel.off();
         }
 
     if (panelSensorState == HIGH && engineSensorState == HIGH) {
       Blynk.setProperty(V4,"color","#00FC00"); // green
       ledEngineOK.on();
//       Blynk.virtualWrite(V0,1);
      }
     else if (panelSensorState == HIGH && engineSensorState == LOW){
       Blynk.setProperty(V4,"color","#FC0000"); // red
       ledEngineOK.on();
      } 
    else {   
       ledEngineOK.off(); 
    }
    
      delay(1000);
      digitalWrite(relayHeater, LOW); // switch on heater
      Serial.println("Heater ON");
      ledHeater.on();
      delay(heaterTime);
      digitalWrite(relayHeater, HIGH); // switch off heater
      Serial.println("Heater OFF");
      ledHeater.off();
      delay(500);
      
       digitalWrite(relayStarter, LOW); // switch on starter
       Serial.println("Starting");
       ledStarter.on();
       delay(starterTime);
       digitalWrite(relayStarter, HIGH); // switch off starter
       ledStarter.off();
       delay(500);
       
       triggerTime = millis();
       Serial.println("Generator RUNNING.");
}

The sequence is:
switch on control panel relay [relayA] (send control pulse)
pause
switch off control panel relay
monitor engine status
switch on heater relay [relayHeater]
pause for x secs
switch off heater relay
switch on starter motor relay (relayStarter]
pause for y secs
switch off starter motor relay

These processes must take place in sequence. I do not want the starter relay firing before the heating process has completed.

X (heaterTime) and Y (starterTime) are both adjustable/programmable delays.

I hope this makes things a little clearer.

this a clue

void startGen() {
  int heaterTime = 10000;
  Serial.println("Generator panel ON");
  timer.setTimeout(500, []()  {
    Serial.println("ON");
    Serial.println("wait for 500");
  }); 

  timer.setTimeout(1000, []()  {
    Serial.println("OFF");
        Serial.println("wait for 1000");
  });  


  Serial.println("Heater ON");
  timer.setTimeout(heaterTime, []()  {
    Serial.println("Heater OFF");
    Serial.println("wait for 10000");
  });  

}

20:08:24.174 -> Generator panel ON
20:08:24.174 -> Heater ON
20:08:24.694 -> ON
20:08:24.694 -> wait for 500
20:08:25.174 -> OFF
20:08:25.174 -> wait for 1000
20:08:34.183 -> Heater OFF
20:08:34.183 -> wait for 10000

I have to say that I was extremely sceptical about this, but decided to do some tests and I can confirm that there is a problem, which seems to be connected with the ticker.h library.

If you comment-out the #define USE_TICKER line in Settings.h of the Edgent_ESP8266 example sketch then delays work as normal.
With this line enabled, delays complete in around 20ms, regardless of their duration.

The problem is worse when using the latest ESP8266 core (v3.0.1).
I thought it might be connected with having an old version of the Ticker library installed, but when I compile the Edgent example sketch, it’s the ESP 3.0.1 library that’s providing the Ticker library:

Using library Ticker at version 1.0 in folder: C:\Users\Pete Knight\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.1\libraries\Ticker

To re-create the problem, add these lines to Edgent_ESP8266.ino

void loop() {
  BlynkEdgent.run();
  random_delay();
}


void random_delay()
{
  long delay_time = random(50,6000);
  long start_millis = millis();
  Serial.print("Starting ");
  Serial.print(delay_time);
  Serial.println(" milleseconds delay...");
  delay(delay_time);
  long duration = millis() - start_millis;
  Serial.print("Delay completed - time taken = ");
  Serial.print(duration);
  if (duration < delay_time)
  {
    Serial.print(" <<<<< ERROR!!");
  }
  Serial.println();
  Serial.println(); 
}

With ESP Core 3.0.1 I get results like this, with a NodeMCU…

Starting 486 milleseconds delay...
Delay completed - time taken = 20 <<<<< ERROR!!

Starting 3796 milleseconds delay...
Delay completed - time taken = 19 <<<<< ERROR!!

Starting 2080 milleseconds delay...
Delay completed - time taken = 20 <<<<< ERROR!!

Starting 2855 milleseconds delay...
Delay completed - time taken = 20 <<<<< ERROR!!

Starting 5064 milleseconds delay...
Delay completed - time taken = 20 <<<<< ERROR!!

Starting 1447 milleseconds delay...
Delay completed - time taken = 20 <<<<< ERROR!!

Starting 2018 milleseconds delay...
Delay completed - time taken = 19 <<<<< ERROR!!

If I comment-out #define USE_TICKER (still using ESP Core 3.0.1) then I get results like this…

Starting 4070 milleseconds delay...
Delay completed - time taken = 4070

Starting 5041 milleseconds delay...
Delay completed - time taken = 5041

Starting 2156 milleseconds delay...
Delay completed - time taken = 2156

Starting 5790 milleseconds delay...
Delay completed - time taken = 5790

Starting 3834 milleseconds delay...
Delay completed - time taken = 3834

If I downgrade to ESP core 2.6.3 and re-run the sketch with #define USE_TICKER enabled then I sill get some odd results, but much less so…

Starting 4979 milleseconds delay...
Delay completed - time taken = 4881 <<<<< ERROR!!

Starting 3819 milleseconds delay...
Delay completed - time taken = 3820

Starting 1635 milleseconds delay...
Delay completed - time taken = 1055 <<<<< ERROR!!

Starting 2919 milleseconds delay...
Delay completed - time taken = 2919

Starting 931 milleseconds delay...
Delay completed - time taken = 932

Starting 2296 milleseconds delay...
Delay completed - time taken = 1025 <<<<< ERROR!!

Pete.

4 Likes

Thank you Blynk_Coeur for your time in coming up with a solution yet again.

However, it does appear that commenting out the #define USE_TICKER line in Settings.h works for me.
Thank you to vshymanskyy and to Peter Knight for your time in identifying this issue.

It now appears that I can use all my legacy code without any major changes. My generator code now works as it should.

So, thank you all.

1 Like

@PeteKnight thanks for a detailed report!

2 Likes

I ran into this recently where blynk1 worked, blynk2 didn’t. Is this a bug? Is this expected to be fixed? I think breaking delay()'s accuracy is a pretty large inconvenience for many users… especially silently failing.

It took me a long time to think “is delay() not accurate?”…

Pete.

On a related theme on using delay of millis or blynktimer. I have a program that is constantly reading a sensor and sending the data up to the server. We are in a remote area and share internet with a lot of people. Our webmaster is complaining about the amount of data I’m using (which is solely the sensor). I don’t need constant sensor info. Maybe once every ten minutes or so. I could use millis or blynktimer but I wonder if my device would still be using data communicating with the cloud. In this case would I be better off using a 50 minute delay?

Your Blynk device needs to be talking to the cloud server constantly for it to remain online.
Putting a blocking delay in the sketch will mean that the device goes offline after 20 seconds or so, and will need to reconnect once the delay ends. That’s not the way to approach the issue.

I’ve previously pointed you to a topic where a Russian guy tweaked the timeout settings to reduce the traffic between the device and the server. If this approach hasn’t solved your problem then I’d suggest adopting a deep sleep approach.

Pete.