Library 0.5.0 Anti-flooding methods seem to affect void loop() and timer consistency

I just wanted to bring this little 'fix" up again as I finally tracked it down as the culprit to one of my large code testbed projects randomly dropping into a repetitive round of rebooting.

It seems that this fix, when it encounters a large influx of Blynk commands… somehow hijacks the void loop() to the point that, instead of thousands of cycles per second, it is only processing as many as needed to process the Blynk commands… Once I made up a check routine to monitor whatever was going on, I was able to see it drop to less than 10 cycles a second… sometimes seeming to stall out completely for a few seconds.

Needless to say that can cause other running code to have issues… in my case it was my WDT timing out after 8 seconds of no void loop() processing it’s reset… and it would then cycle through boot/reboot a handful of times before whatever Blynk backlog was cleared and settled down :stuck_out_tongue:

I have moved this to an Issues and Errors topic as I have also discovered that occasional timers are no longer… on time…

Due to past issue with my many utilised vPins in one of my larger projects, I had discovered issues with Blynk.syncAll() causing buffer overflows. My “solution” at the time was a hack that incorporated individual vPin syncs with a small timed delay… worked great, ran all 127 vPins in about 8 seconds, if i recall, and did not interfere with anything else.

But now it feels like this anti-flooding issue, by its apparent nature of slowing down the void loop(), is negatively affecting timers as well (probably since the timer call is in the loop). Thus many of my previously precision timed routines sometimes get radically slowed down.

In some of my devices I utilize a simple LED toggle to monitor the loop… and often that LED is actually OFF for a second or two? Adding in a simple counter to my void loop() oftens averages less than 50 cycles per second… <50? even on a 16MHz Arduino with a large sketch, that is ridiculously slow.

I have seen this happen on Arduino, ESP8266 and even ESP32 with differing sketches… but only after finally submitting to the 0.5.0 library update. It just took me awhile to determine the apparent cause.

Any insight of how to keep the anti-flooding without violating the necessity of a fast cycling void loop()?

maybe the authors can introduce a programmable anti-flooding / flooding switch to be chosen by the programmer?

1 Like

Maybe @vshymanskyy could give some details of how “flood prevention” was implemented in 0.5.0 so the Community could assess the pros and cons together with the impact it might have on their specific projects.

Flood prevention will certainly help newbies but that might be to the overall detriment of the Blynk project. Therefore I welcome the suggestion made by @krzyspx regarding a “switch”.

1 Like

Thank for your report. There is already a switch. But i do not recommend using it (will hurt), so won’t provide details right now :wink:
I think I know what’s causing the problem , but to verify I really need a simple reproducible example of this issue. I’m currently unable to work on this, but i’ll check this out ASAP.

3 Likes

This is a reduced version of my Virtual LED Matrix sketch, running on a Wemos D1 Mini @ 80MHz CPU… primarily set to push out a few Blynk commands as fast as possible.

It’s main function timer (LEDTimer) is running some minor internal calculations and then pushes out two Blynk commands and a digital pin toggle ever timed loop. A 2nd timer (CLKtimer) displays the LEDTimer loop and void loop() counts every second.

In a “normal” setting, I can see this void loop() issue occurs with the main function timer at around 250ms… giving the timed write loop a cycle of about 5/s and the void loop() at around 10000-12000/s.

Screenshot_2018-01-18-14-51-23

But I have noticed that with a large enough #define BLYNK_MSG_LIMIT 400, on my Local Server, I can drop the main function timer to around 8-10ms before noting the void loop() issue, wherein it ranges from around 9000-13000/s to whatever the anti-flooding rate is… usually sub 150/s

Screenshot_2018-01-18-14-39-26
Screenshot_2018-01-18-14-37-58

Here is the Flood Test Project files.

image

//#define BLYNK_PRINT Serial
//#define BLYNK_MAX_READBYTES 4096
//#define BLYNK_MSG_LIMIT 400  // Uncomment this for faster througput
//#define BLYNK_HEARTBEAT 60
#define BLYNK_NO_BUILTIN  // Disable built-in analog & digital pin operations
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>  // For OTA
#include <WiFiUdp.h>  // For OTA
#include <ArduinoOTA.h>  // For OTA
#include <BlynkSimpleEsp8266.h>
char auth[] = "xxxxxxxxxx";
char ssid[] = "xxxxxxxxxx";
char pass[] = "xxxxxxxxxx";
String HEXstring;
int randLED, randIntensity, LEDTimer, CLKtimer;
int rrr, ggg, bbb;
int LEDCLK = 0;
int CLK = 0;
BlynkTimer timer;


void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  //Serial.begin(115200);
  Blynk.begin(auth, ssid, pass, "xxx.xxx.xxx.xxx", 8442);
  LEDTimer = timer.setInterval(250L, RGBMatrix);  // Change this for overall speed of LED flashing
  CLKtimer = timer.setInterval(1000L, CLKcheck);
  ArduinoOTA.setHostname("Flood Test");  // For OTA
  ArduinoOTA.begin();  // For OTA
}


void CLKcheck() {
  Blynk.virtualWrite(4, CLK);
  Blynk.virtualWrite(5, LEDCLK);
  CLK = 0;
  LEDCLK = 0;
}


void RGBMatrix() {
  randLED = random(4);
  randIntensity = random(64, 256);
  rrr = random(256);
  ggg = random(256);
  bbb = random(256);
  String strRED = String(rrr, HEX);  // Convert RED DEC to HEX.
  if (rrr < 16) {
    strRED = String("0" + strRED);  // Buffer with 0 if required.
  }  // END if
  String strGRN = String(ggg, HEX);  // Convert GREEN DEC to HEX.
  if (ggg < 16)  {
    strGRN = String("0" + strGRN);  // Buffer with 0 if required.
  }  // END if
  String strBLU = String(bbb, HEX);  // Convert BLUE DEC to HEX.
  if (bbb < 16)  {
    strBLU = String("0" + strBLU);  // Buffer with 0 if required.
  }  // END if
  String HEXstring = String("#" + strRED + strGRN + strBLU);  // Combine HEX fragments.
  Blynk.setProperty(randLED, "color", HEXstring);  // Set random LED HEX colour
  Blynk.virtualWrite(randLED, randIntensity);  // Set random LED intensity
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); // Flash LED_BUILTIN
  LEDCLK++;
}


void loop()
{
  CLK++;
  Blynk.run();
  timer.run();
  ArduinoOTA.handle();
}
3 Likes

This issue is actually more notable (as in project instability) with more fleshed out (aka actually doing something) sketches that are running many timed loops and pushing more overall Blynk commands, but at a slower overall rate… eventually causing the project to disconnect within a few minutes (and this is with using all sorts of "go faster" enhancements :wink: )

//#define BLYNK_PRINT Serial
#define BLYNK_MAX_READBYTES 4096
#define BLYNK_MSG_LIMIT 1024
#define BLYNK_HEARTBEAT 60
#define BLYNK_NO_BUILTIN  // Disable built-in analog & digital pin operations

Note the void loop() counter at the upper right of screen. This is on a testbench project that, while huge, has been fairly stable for almost a year of well, testbench use :wink:

This is running on an Arduino MEGA, so at 16MHz it is a bit slow, but normally I would see a void loop() counter of 100-200/s

1 Like

Hi @Gunner then you for putting the effort identifying and articulating the issue. I have been getting the same resets on my project that I recompiled to v0.5.0 - know at least we have some idea what could be creating them.

I’m with @costas on this - the community’s needs to be provided with more details on the logic behind v0.5.0 so we can assess impacts to our projects, and a switch as mentioned previously might be a good idea as a way to help community members with the transition.

@mars - the library is open source and you can check out the relevant changes… what prevents you from doing that? :wink:

@Gunner the issue may be… did you know that (AFAIK) SimpleTimer “buffers” amount of times it need to run the function? For example, if your timer function runs longer that the run interval, you’re in some kind of trouble - it will try running your function multiple times to reach the expected amount of runs, which it can’t ever achieve - the function itself takes longer… I hope I’m clear here. It would be good to validate that, I might be wrong.

I have fiddled with all my timers to give each one enough time to complete it’s task… although that has gotten harder when the void loop() itself stalls out :wink: reminiscent of that dreaded delay() command.

But I have seen the scenario you are referring too… it does tend to result in multiple “copies”
of a function running, one in the midst of another, spaced out only by the set time, until it overloads the system or someone stops mashing the button like they were playing Lunar Lander :stuck_out_tongue:

Like on a button controlled sequence, wherein I don’t have a check flag, and the button is pressed a 2nd time before the 1st sequence has ended… e.g. press a button and it flashes an LED once a second for 5 seconds… press it again mid-way and you have the LED flashing twice a second until the initial 5 seconds is over then back to once a second for the remaining time… press it 3-4 times and the LED starts strobing and things get interesting :stuck_out_tongue:

1 Like

BTW, I can take the timer out of the equation altogether and just run a Blynk command function directly from the void loop() and it will still result in the drastic slowdown of the loop in order to avoid flooding… so not entirely timer related.

I had a feeling you were going to say that :wink:

Agree I could and should but given this may be of interest to many in the community (my assumption) it would be much more efficient for the creator (yourself) to provide an explanation or at least point us to the logic within their code so its less of a “needle in the hay stack” activity for us mere mortals to digest. :wink:

@Gunner This slowdown is completely expected…

@mars I have a much better idea. How about a webinar on blynk library internals? More details later!

3 Likes

very much like that idea :+1:

To clarify… so, my OP is…

  1. A non issue? :face_with_raised_eyebrow:

  2. A valid point, but slowdown was expected… just deal with it :sunglasses:

  3. A grievous miscalculation of nanny control and there will be a Local Server #define option to disable such for those who can actually balance their Blynk commands and background code :stuck_out_tongue_winking_eye:

@Gunner 2, I think.
basically, maybe we should modify blynktimer so it runs a missed event only once, aka “best effort”…

But the issue doesn’t appear to be timer related…

Now I know this is a Apples to Coconuts comparison :wink: … but “removing” Blynk and running the same sketch with only lots of Serial.println() outputs instead… my void loop() on my MEGA is around 12000-14000 per second, while processing 200 LED calculation loops & Serial .println() a second (timer at 5ms).

With Blynk, the MEGA tops out at 5 loops (void loop() and LED process each) per second with the same timer setting.

Count them… 5 lps!! :face_with_raised_eyebrow:

If I raise the timer to 500ms, well, then I get a whopping, and variable, range from 1 - 54 void loop() per second :stuck_out_tongue: but only a lousy 2 lps for the LEDs (thats a total of 4 Blynk commands per second EDIT, OK, 6 counting the displays showing the loop counts :slight_smile: ).

Now, can you really state that Blynk takes that much overhead from even a measly Arduino?

I guess I need to drop back a library version to be sure, but I think the issue is with whatever “protections” have been added… Stable, even with noobs… perhaps (EDIT, not really as it still disconnects briefly, way too often) … and way too slow for any real background processing needs.

Is your configuration: a MEGA + ESP8266 as a shield?

For that last test yes… was the quickest I could slap together at the time…

I am working on an identical Wemos one now… but based on other projects I have been fighting with, there is still a phenomenal drop in overall CPU performance.