Pausing Blynk re-connecting to handle button press event

Hi Blynkers,

Currently I am working on a home-automation project where I would like to automate my lights. For this project I am planning on using Blynk to control these from my phone. Also I am having a physical button to just switch the light ON and OFF, for debouncing this button I am currently using the Bounce2 library. But here comes my question, I would like to make some kind of interrupt that handles the button press while the WEMOS D1 is connecting to Blynk after a connection loss. So I would like to be able to control the light instantly and not having to wait until the connection is complete.
I have been searching on different posts, but I haven’t found one that pauses the re-connecting, and handles the debouncing on an interrupt.

Does any of you have some interresting ideas about this, or solutions to this problem?

Thanks :slight_smile:

Blynk.begin is a totally blocking function. No code will be executed if the device can’t connect, it will simply keep trying to connect.

Blynk.config and Blynk.connect are an alternative. Blynk.connect will still block while it’s attempting to connect, but it fairly quickly times out and I seem to recall that the timeout period can be altered via a parameter.

Pete.

1 Like

You don’t need a full-fledge Debouncing library as it might be not written to use in ISR.
You can just use some simple debouncing way using millis() inside ISR. For example

#define DEBOUNCE_TIME                   200     // the debounce time in msec; increase if the output flickers

volatile unsigned long lastDebounceTime = 0;
volatile bool currentState = LOW;

void ICACHE_RAM_ATTR Falling()
{
  unsigned long currentTime  = millis();
         
  if (currentTime > lastDebounceTime + DEBOUNCE_TIME)
  {
    lastDebounceTime = currentTime;        
    
    //Reverse the state
    currentState = !currentState;
    
    // Do something, such as turn ON/OFF lightPin
    digitalWrite(lightPin, currentState);                                         
  }        
}

void setup()
{
  ....
  pinMode(buttonPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(buttonPin), Falling, FALLING);
  ....
}

The ISR will work no matter you’re blocked by something, such as blocking Blynk.begin(). But as @PeteKnight suggests, you’d better use Blynk.config() and Blynk.connect() to avoid being blocked if you have something important to do in your loop().
The timeout period of Blynk.connect() can be specified either in the call, such as Blynk.connect(TIMEOUT_IN_MS) or by using the following #define. Just place it before first #include of any Blynk library (better the first line of your main code).

#define BLYNK_TIMEOUT_MS     WANTED_TIMEOUT_DIV_3_MS

If Blynk.connect() is called without argument, the timeout will default to 3 times of BLYNK_TIMEOUT_MS (currently 3s or 6s, depending on which device you’re using) as specified in Blynk/BlynkProtocol.h and Blynk/BlynkConfig.h

bool connect(uint32_t timeout = BLYNK_TIMEOUT_MS*3);

You can also try this

1 Like

First of all I would like to thank you for the suggestions. These suggestions have been extremely useful. I included the code that I have made out of this, I think this is what you have implied right?

So far it seems to work correctly, while Blynk is trying to connect, the button is still responding correctly.
I’m not sure if it is allowed to ask a follow up question in a post, but I’m wondering if it is possible to extend this code to also make a disctiction between a short and long button press, or would this be impossible with an interrupt?

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#define DEBOUNCE_TIME 250

volatile unsigned long lastDebounceTime = 0;
volatile bool          currentState     = LOW;
const int              buttonPin        = D1;


// Initialize Blynk
char auth[]           = "";
char ssid[]           = ""; 
char pass[]           = ""; 
IPAddress serverIP    (192,168,0,118);
uint16_t serverPort   = 8080;

BlynkTimer Timer;
unsigned int myServerTimeout      =  3500L;  //  3.5s server connection timeout (SCT)
unsigned int myWiFiTimeout        =  3200L;  //  3.2s WiFi connection timeout   (WCT)
unsigned int blynkInterval        = 25000L;  // 25.0s check server frequency    (CSF)


void ICACHE_RAM_ATTR Falling()
{
  unsigned long currentTime  = millis();
  Serial.println("falling");       
  if (currentTime > lastDebounceTime + DEBOUNCE_TIME)
  {
    lastDebounceTime = currentTime;        
    Serial.println("debounce");
    //Reverse the state
    currentState = !currentState;
    
    // Do something, such as turn ON/OFF lightPin
    digitalWrite(LED_BUILTIN, currentState);                                         
  }        
}


void setup() {
  Serial.begin(115200);

  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(buttonPin), Falling, FALLING);

  Serial.println("Initialize Blynk");
  if(WiFi.status() == 6){
    Serial.println("WiFi not connected yet.");
  }
  Timer.setInterval(blynkInterval, checkBlynk);   // check connection to server per blynkInterval
  unsigned long startWiFi = millis();
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    if(millis() > startWiFi + myWiFiTimeout){
      Serial.println("Check the WiFi router. ");
      break;
    }       
  }
  Blynk.config(auth, serverIP, serverPort);
  checkBlynk();
}

void loop() {
  if (Blynk.connected()) {Blynk.run();}
  Timer.run();

}


void checkBlynk() {
  if (WiFi.status() == WL_CONNECTED)  
  {
    unsigned long startConnecting = millis();    
    while(!Blynk.connected()){
      Blynk.connect();  
      if(millis() > startConnecting + myServerTimeout){
        Serial.print("Unable to connect to server. ");
        break;
      }
    }
  }
  if (WiFi.status() != 3) {
    Serial.print("No WiFi. ");
  } 
  Serial.printf("Checking again in %is.\n", blynkInterval / 1000);
}
1 Like

The way to do be able to detect both the button press and release events, and calculate the time between them.
I guess you could use both RISING and FALLING interrupts to detect the press/release events, or when the button is pressed start sampling the button using a digitalRead loop and counting how my reads of one type that you get before the button is released.

Once you know that the ‘pressed’ time has exceeded certain point you can start your alternate course of action.

One theoretical issue is that timers don’t work correctly in an ISR routine (in theory). In practice I’ve never had a problem with this.

Overall, it’s probably much easier to have two buttons :slightly_smiling_face:

Pete.

1 Like

That’s what I implied and it’s encouraging that your code is working as you’d like. Although there is some place you can improve a little bit, yet not important.
You can make a distinction between short and long press using your current code as follows:

// Long press is more than 5s, you can change here
#define LONG_BUTTON_PRESS_TIME_MS    5000L
#define DEBUG_ISR                    0

void ICACHE_RAM_ATTR Rising()
{
  unsigned long currentTime  = millis();
  unsigned long TimeDiff;
  
  //Time from last button press until button released now
  TimeDiff = currentTime - lastDebounceTime;

  if (TimeDiff > DEBOUNCE_TIME)
  {
    //doing something when button is released
    // Any function called inside ISR must be short, and using volatile if global vars
    doButtonRelease();
    
    if (TimeDiff > LONG_BUTTON_PRESS_TIME_MS)
    {
       //Try to avoid Serial.print in ISR, use only for serious debugging
       #if (DEBUG_ISR > 0)
        Serial.printf("TimeDiff = %d ms => long Button Press\n", TimeDiff );
       #endif
       
       // Doing something if button was pressed continuously longer than LONG_BUTTON_PRESS_TIME_MS
       // Any function called inside ISR must be short, and using volatile if global vars
       respondToLongPress(); 
    }
  }

  //Always change to Falling ISR
  lastDebounceTime = currentTime;
  // Prepare ISR, so that we'll know when the button is pressed again
  attachInterrupt(digitalPinToInterrupt(buttonPin), Falling, FALLING);
}
  
void ICACHE_RAM_ATTR Falling()
{
  unsigned long currentTime  = millis();
  //Try to avoid Serial.print in ISR, use only for serious debugging
  #if (DEBUG_ISR > 0)  
  Serial.println("falling");
  #endif
     
  if (currentTime > lastDebounceTime + DEBOUNCE_TIME)
  {
    lastDebounceTime = currentTime; 

    #if (DEBUG_ISR > 0)     
    Serial.println("Button Pressed");
    #endif
    
    //Reverse the state
    currentState = !currentState;
    
    // Do something, such as turn ON/OFF lightPin
    digitalWrite(LED_BUILTIN, currentState); 
    
    // Prepare ISR, so that we'll know when the button is released
    // We'll calculate time difference to know if the button was pressed long enough 
    attachInterrupt(digitalPinToInterrupt(buttonPin), Rising, RISING);                                                
  }        
}


Hope this will be OK for you to apply.

1 Like

Again thanks for the reply, this example is really clear for me and well organized! Good to know that Serial.print must be avoided in interrupts, I wasn’t aware of that.
Just to be sure, I adapted one line to distinct between short and long press, I made the following out of it:

    if (TimeDiff > LONG_BUTTON_PRESS_TIME_MS)
    {
       #if (DEBUG_ISR > 0)
        Serial.printf("Long Press" );
       #endif
       // Code for long press

    } else {
      #if (DEBUG_ISR > 0)
        Serial.println("Short Press"); 
       #endif
       // Code for short press

    }

It seems to work correctly, so I would like to thank you for your very useful help! Also @PeteKnight thanks for the useful suggestions and insights! :slight_smile:

I have been playing a bit with the code and found out that the long press only gets activated after the button is released. I was wondering if it is possible to make the code such that the long press gets activated after a certain time of holding the button, without releasing it yet? Or is this impossible as this cannot be identified by an interrupt?

Pete.

1 Like

You certainly can follow Pete suggestion to poll the button.
But because you already have the ISR code providing you a lot of info to process, it’s better to use a timer outside ISR to check and make decision.
As Pete said, it’s not advisable to use Timer in ISR. This is correct because (Blynk)Timer functions are not written to be used in ISR. Those Timers initiated in ISR can run, but not 100% reliable as variables in (Blynk)Timers are purposely not declared volatile.

You can write a code similar to this for long press gets activated after a certain time of holding the button, without releasing it

//Add more vars for new timer to process
volatile bool buttonPressed  = false;
unsigned int buttonInterval       = 1000L;  // 1.0s check button state
bool alreadyTriggered = false;

void ICACHE_RAM_ATTR Rising()
{
  unsigned long currentTime  = millis();
  unsigned long TimeDiff;
  
  //Time from last button press until button released now
  TimeDiff = currentTime - lastDebounceTime;

  if (TimeDiff > DEBOUNCE_TIME)
  {
    //doing something when button is released
    // Any function called inside ISR must be short, and using volatile if global vars
    doButtonRelease();
    //Flag button released
    buttonPressed = false;
    
    if (TimeDiff > LONG_BUTTON_PRESS_TIME_MS)
    {
      ...
    }
    else
    {
      // Code for short press
    }
  }

  //Always change to Falling ISR
  lastDebounceTime = currentTime;
  // Prepare ISR, so that we'll know when the button is pressed again
  attachInterrupt(digitalPinToInterrupt(buttonPin), Falling, FALLING);
}
  
void ICACHE_RAM_ATTR Falling()
{
  unsigned long currentTime  = millis();
  //Try to avoid Serial.print in ISR, use only for serious debugging
  #if (DEBUG_ISR > 0)  
  Serial.println("falling");
  #endif
     
  if (currentTime > lastDebounceTime + DEBOUNCE_TIME)
  {
    lastDebounceTime = currentTime;
    //Flag button pressed
    buttonPressed = true;
    ...                                                
  }        
}

void checkButton()
{
  if (!alreadyTriggered && buttonPressed && (millis() - lastDebounceTime > LONG_BUTTON_PRESS_TIME_MS))
  {
    alreadyTriggered = true;
    Serial.println("Button pressed longer than " + String(LONG_BUTTON_PRESS_TIME_MS/1000) + "s");
    //Doing something here without waiting for button released
    yourFunction();
  }
  else if (!buttonPressed)
  {
    // Reset flag when button released to avoid triggered repeatedly
    alreadyTriggered = false;
  }
}

void setup() {

  ....
  checkBlynk();
  
  Timer.setInterval(blynkInterval, checkBlynk);   // check connection to server per blynkInterval
  // New timer to detect long press before button released
  Timer.setInterval(buttonInterval, checkButton);  
  }


1 Like

Dear @khoih and @PeteKnight the code works perfectly now, I have implemented every suggestion and I’m very happy with it! Thank you both :slight_smile:

Here the complete code for anybody that likes to reproduce it:

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#define DEBOUNCE_TIME               50L
#define LONG_BUTTON_PRESS_TIME_MS   1000L
#define DEBUG_ISR                   0

volatile unsigned long  lastDebounceTime  = 0;
volatile bool           buttonPressed     = false;
bool                    alreadyTriggered  = false;


const int buttonPin = D1;


// Initialize Blynk
char authD1[]         = "";
char ssid[]           = ""; 
char pass[]           = ""; 
IPAddress serverIP    (192,168,0,118);
uint16_t serverPort   = 8080;


BlynkTimer Timer;
unsigned int myServerTimeout      =  3500L;  //  3.5s server connection timeout (SCT)
unsigned int myWiFiTimeout        =  3200L;  //  3.2s WiFi connection timeout   (WCT)
unsigned int blynkInterval        = 25000L;  // 25.0s check server frequency    (CSF)
unsigned int buttonInterval       =   200L;  //  0.2s check button state


void ICACHE_RAM_ATTR Falling();
void ICACHE_RAM_ATTR Rising();


void setup() {
  Serial.begin(115200);
  
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(buttonPin), Falling, FALLING);


  Serial.println("Initialize Blynk");
  if(WiFi.status() == 6){
    Serial.println("WiFi not connected yet.");
  }
  Timer.setInterval(blynkInterval, checkBlynk);
  unsigned long startWiFi = millis();
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    if(millis() > startWiFi + myWiFiTimeout){
      Serial.println("Check the WiFi router. ");
      break;
    }       
  }
  Blynk.config(authD1, serverIP, serverPort);
  Serial.println("This is HomeControl-TEST"); 
  checkBlynk();


  // New timer to detect long press before button released
  Timer.setInterval(buttonInterval, checkButton);  
}

void loop() {
  if (Blynk.connected()) {Blynk.run();}
  ArduinoOTA.handle();
  Timer.run();
}

void checkBlynk() {
  if (WiFi.status() == WL_CONNECTED)  
  {
    unsigned long startConnecting = millis();    
    while(!Blynk.connected()){
      Blynk.connect();  
      if(millis() > startConnecting + myServerTimeout){
        Serial.print("Unable to connect to server. ");
        break;
      }
    }
  }
  if (WiFi.status() != 3) {
    Serial.print("No WiFi. ");
  } 
  Serial.printf("Checking again in %is.\n", blynkInterval / 1000);
}

void Rising()
{
  unsigned long currentTime  = millis();
  unsigned long TimeDiff;
  
  // Time from last button press until button released now
  TimeDiff = currentTime - lastDebounceTime;

  if (TimeDiff > DEBOUNCE_TIME)
  {
    // Doing something when button is released
    // Any function called inside ISR must be short, and using volatile if global vars
    // ...
    
    // Flag button released
    buttonPressed = false;
       
    
    if (TimeDiff > LONG_BUTTON_PRESS_TIME_MS)
    {
      // Try to avoid Serial.print in ISR, use only for serious debugging
      #if (DEBUG_ISR > 0)
        Serial.printf("Long Button Press (with release)");
      #endif
      
      // Long Press (first need to be released)
       
    } else {
      #if (DEBUG_ISR > 0)
        Serial.println("Short Button Press");
      #endif

      // Short Press
      
    }
  }

  // Always change to Falling ISR
  lastDebounceTime = currentTime;
  // Prepare ISR, so that we'll know when the button is pressed again
  attachInterrupt(digitalPinToInterrupt(buttonPin), Falling, FALLING);
}

void Falling()
{
  unsigned long currentTime  = millis();
     
  if (currentTime > lastDebounceTime + DEBOUNCE_TIME)
  {
    lastDebounceTime = currentTime;
    
    // Flag button pressed
    buttonPressed = true;
    
    // Prepare ISR, so that we'll know when the button is released
    // We'll calculate time difference to know if the button was pressed long enough 
    attachInterrupt(digitalPinToInterrupt(buttonPin), Rising, RISING);                                                
  }     
}

void checkButton()
{
  if (!alreadyTriggered && buttonPressed && (millis() - lastDebounceTime > LONG_BUTTON_PRESS_TIME_MS))
  {
    alreadyTriggered = true;
    #if (DEBUG_ISR > 0)
      Serial.println("Long Button Press");
    #endif
    
    // Doing something here without waiting for button released (long press)
    // yourFunction();
  
  }
  else if (!buttonPressed)
  {
    // Reset flag when button released to avoid triggered repeatedly
    alreadyTriggered = false;
  }
}

I’ve been using this code now for several days, however, the Long button press (so without release) gets triggered sometimes randomly. Initially, I thought by increasing the debounce time this problem would be solved. But this was not the case. What I also found strange is that the short button press does not get triggered randomly, so it is not a debounce problem right?

I’m using the code as posted in last post. Is there a way to fix this problem?

Guido

I guess the pin voltage could be floating slightly. Try adding a 10k resistor to pull the value up or down (depending on how you’ve wired it).
If the push button connects between D1 and GND then connect your resistor between D1 and 3.3v.
If it’s the other way then between D1 and GND.

Pete.

1 Like

With Pete’s experience, his advice is the best approach in this situation.
To deal with this erratic / random behaviour, I’m afraid only you can debug and find out the real problem. It’s possibly a hardware issue such as power, noise, board, switch, etc.

I think there are something you can try:

  1. Follow Pete’s advice by pulling up or down using resistor depending your hardware.
  2. Check / replace your power supply. Put more capacitors (tantalum and electrolytic) to stabilise the power and noise.
  3. Move buttonPin from D1 to another pin. If you use Wemos D1, pin D1 is also TX. If you use some kind of communication using TX/RX (such as USB debug port, setting / using debug port in Arduino IDE, etc.), there is a possibility of interference.
  4. Replace the Switch, as well as the board.
  5. Put more debugging messages at strategic points to help identify where the problem is.
  6. Increase buttonInterval. You don’t need to scan the button every 0.2s.

I briefly scan your posted code, and it seems OK. Let us know the debugging result.

Good luck.

1 Like

I have added some 10k resistors for the connected buttons. I’m currently having my button connected between the D1 and GND and added the risistor between D1 and 3.3v. I left the code unchanged, or did I had to change INPUT_PULLUP to INPUT?

Unfortunately, I still have the random triggering of the long press button, however, I still find this strange as the short press does not get triggered randomly. I’ve been running this code now for a couple of days, where the long press gets triggered almost every 1.5 hour, whereas, the short press never have been triggered randomly?

I will also go over the code one more time, and try playing with debug messages.

Guido

No need to use the internal pull-ups when using physical resistors.

Don’t get too hung-up about the short/long press thing. I think you’ll find that its only doing the long press event because of the logic of how the code ios written and the fact that the change is a drift in one direction, rather than a spike.

Have you tried reversing the switch polarity and the corresponding interrupt logic?

Pete.

Hi,
I think this is my fault to place the attachInterrupt in the wrong place while copying. Sorry. I also add some digitalRead(buttonPin) check to be sure it’s not spurious signal.

Try this now.

void ICACHE_RAM_ATTR Rising()
{
  unsigned long currentTime  = millis();
  unsigned long TimeDiff;

  #if (DEBUG_ISR > 0)  
  Serial.println("rising");
  #endif  
  
  // Time from last button press until button released now
  TimeDiff = currentTime - lastDebounceTime;

  if ( digitalRead(buttonPin) && (TimeDiff > DEBOUNCE_TIME) )
  {
    #if (DEBUG_ISR > 0)     
    Serial.println("Button Released");
    #endif
    // Doing something when button is released
    // Any function called inside ISR must be short, and using volatile if global vars
    // ...
    
    // Flag button released
    buttonPressed = false;
          
    if (TimeDiff > LONG_BUTTON_PRESS_TIME_MS)
    {
      // Try to avoid Serial.print in ISR, use only for serious debugging
      #if (DEBUG_ISR > 0)
        Serial.printf("TimeDiff = %d ms => long Button Press (with release)\n", TimeDiff );
       #endif      
      // Long Press (first need to be released)
       
    } else {
      #if (DEBUG_ISR > 0)
        Serial.println("Short Button Press");
      #endif

      // Short Press
      
    }
   // Must be here inside the if, not outside !!!
    // Always change to Falling ISR
    lastDebounceTime = currentTime;
    // Prepare ISR, so that we'll know when the button is pressed again
    attachInterrupt(digitalPinToInterrupt(buttonPin), Falling, FALLING);    
  }
}

void  Falling()
//void ICACHE_RAM_ATTR Falling()
{
  unsigned long currentTime  = millis();

  //Try to avoid Serial.print in ISR, use only for serious debugging
  #if (DEBUG_ISR > 0)  
  Serial.println("falling");
  #endif  
     
  if ( !digitalRead(buttonPin) && (currentTime > lastDebounceTime + DEBOUNCE_TIME))
  {
    lastDebounceTime = currentTime;

     #if (DEBUG_ISR > 0)     
    Serial.println("Button Pressed");
    #endif   

    // Flag button pressed
    buttonPressed = true;
       
    // Prepare ISR, so that we'll know when the button is released
    // We'll calculate time difference to know if the button was pressed long enough 
    attachInterrupt(digitalPinToInterrupt(buttonPin), Rising, RISING);                                                
  }     
}

I’ve implemented this code and also added the digitalRead(buttonPin) to the checkButton() just as an extra check and now everything seems to work as expected!

Thanks for all the help @PeteKnight and @khoih

Guido

1 Like

Hello !
@khoih @PeteKnight @guidotillema
i was going through the forum and found this interesting thread !!
After following the exact steps as you guys have mentioned above i still find that the button stops responding when connecting to the server !!

Scene 1
Device turns on
No Router available (button responds no lag)

Scene 2
Device turns on
router available but no internet

Now after the device is connected to wifi router it fails to connect to the server as there is no internet connection available the device keep trying to connect at set intervals… during this time the code as blocked !!
This is the code i am using

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#define DEBOUNCE_TIME               25
#define LONG_BUTTON_PRESS_TIME_MS   10
#define DEBUG_ISR                   0
#define VPIN1 V1
volatile unsigned long  lastDebounceTime  = 0;
volatile bool           buttonPressed     = false;
bool                    alreadyTriggered  = false;

void lightOn1();
void lightOff1();

boolean LampState1 = 0;
boolean SwitchReset1 = true;

const int RelayPin1 = D2;
const int buttonPin = D1;


// Initialize Blynk
char authD1[]         = "";
char ssid[]           = ""; 
char pass[]           = ""; 
IPAddress serverIP    (00,000,000,000);
uint16_t serverPort   = 8080;


BlynkTimer Timer;
unsigned int myServerTimeout      =  3500L;  //  3.5s server connection timeout (SCT)
unsigned int myWiFiTimeout        =  3200L;  //  3.2s WiFi connection timeout   (WCT)
unsigned int blynkInterval        = 25000L;  // 25.0s check server frequency    (CSF)
unsigned int buttonInterval       =   100L;  //  0.1s check button state


void ICACHE_RAM_ATTR Falling();
void ICACHE_RAM_ATTR Rising();



void setup() {
  Serial.begin(115200);
    pinMode(RelayPin1, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(buttonPin), Falling, FALLING);


  Serial.println("Initialize Blynk");
  if(WiFi.status() == 6){
    Serial.println("WiFi not connected yet.");
  }
  Timer.setInterval(blynkInterval, checkBlynk);
  unsigned long startWiFi = millis();
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    if(millis() > startWiFi + myWiFiTimeout){
      Serial.println("Check the WiFi router. ");
      break;
    }       
  }
  Blynk.config(authD1, serverIP, 8080);
  Serial.println("This is HomeControl-TEST"); 
  checkBlynk();
  Timer.setInterval(buttonInterval, checkButton);  
}

void checkBlynk() {
  if (WiFi.status() == WL_CONNECTED)  
  {
    unsigned long startConnecting = millis();    
    while(!Blynk.connected()){
      Blynk.connect();  
      if(millis() > startConnecting + myServerTimeout){
        Serial.print("Unable to connect to server. ");
        break;
      }
    }
  }
  if (WiFi.status() != 3) {
    Serial.print("No WiFi. ");
  } 
  Serial.printf("Checking again in %is.\n", blynkInterval / 1000);
}

void Rising()
{
  unsigned long currentTime  = millis();
  unsigned long TimeDiff;
  #if (DEBUG_ISR > 0)  
  Serial.println("rising");
  #endif  
  TimeDiff = currentTime - lastDebounceTime;
  if ( digitalRead(buttonPin) && (TimeDiff > DEBOUNCE_TIME) )
  {
    #if (DEBUG_ISR > 0)     
    Serial.println("Button Released");
    #endif
    buttonPressed = false;
          
    if (TimeDiff > LONG_BUTTON_PRESS_TIME_MS)
    {
     #if (DEBUG_ISR > 0)
        Serial.printf("TimeDiff = %d ms => long Button Press (with release)\n", TimeDiff );
       #endif      
      
    } else {
      #if (DEBUG_ISR > 0)
        Serial.println("Short Button Press");
      #endif
    }
    lastDebounceTime = currentTime;
    attachInterrupt(digitalPinToInterrupt(buttonPin), Falling, FALLING);    
  }
}

void  Falling()
{
  unsigned long currentTime  = millis();
  #if (DEBUG_ISR > 0)  
  Serial.println("falling");
  #endif  
     
  if ( !digitalRead(buttonPin) && (currentTime > lastDebounceTime + DEBOUNCE_TIME))
  {
    lastDebounceTime = currentTime;

     #if (DEBUG_ISR > 0)     
    Serial.println("Button Pressed");
    #endif   
    buttonPressed = true;
    attachInterrupt(digitalPinToInterrupt(buttonPin), Rising, RISING);                                                
  }     
}

void loop() {
  if (Blynk.connected()) {
    Blynk.run();
    }
  Timer.run();
}


void checkButton()
{
  if (!alreadyTriggered && buttonPressed && (millis() - lastDebounceTime > LONG_BUTTON_PRESS_TIME_MS))
  {
    alreadyTriggered = true;
    #if (DEBUG_ISR > 0)
      Serial.println("Long Button Press");
    #endif
    
    // Doing something here without waiting for button released (long press)
   ButtonCheck1();
  
  }
  else if (!buttonPressed)
  {
    // Reset flag when button released to avoid triggered repeatedly
    alreadyTriggered = false;
    ButtonCheck1();
  }
}

void ButtonCheck1() {
  boolean SwitchState1 = (digitalRead(buttonPin));
  if (!SwitchState1 && SwitchReset1 == true) {
if (LampState1) {
  lightOff1();
} else {
  lightOn1();
}
SwitchReset1 = false;
delay(50);
  }
  else if (SwitchState1) {
SwitchReset1 = true;
  }
}

void ToggleRelay1() {
  LampState1 = !LampState1;
  if (LampState1) {
   lightOn1();
  }
  else lightOff1();
}

void lightOn1() {
digitalWrite(RelayPin1, LOW);
LampState1 = 1;
Blynk.virtualWrite(VPIN1, HIGH); 
}

void lightOff1() {
digitalWrite(RelayPin1, HIGH);
LampState1 = 0;
Blynk.virtualWrite(VPIN1, LOW); 
}

BLYNK_WRITE(VPIN1) {
  int SwitchStatus1 = param.asInt();
if (SwitchStatus1 == 2){
ToggleRelay1();
  }
  else if (SwitchStatus1){
lightOn1();
  }
  else lightOff1();
}

The whole purpose was to eliminate the blockage of the code during reconnection !! But the problem still exists !! MAY BE I AM GOING WRONG SOMEWHERE !!

Is there any thing missing in the code or is this the way it is supposed to work ??

EDITING TO ADD SERIAL MONITOR OUTPUT

WiFi not connected yet.
Check the WiFi router. 
[3558] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v0.6.0 on NodeMCU

This is HomeControl-TEST
No WiFi. Checking again in 25s.            *Button works without any lag [No router found]*
No WiFi. Checking again in 25s.            *Button works without any lag [No router found]*
[50057] Connecting to 40.200.200.000  *Button stops working [router available, No internet]*
[55058] Connecting to 40.200.20.000    *Button stops working [router available, No internet]*
Unable to connect to server. Checking again in 25s. *Button works without any lag*
[75057] Connecting to 40.200.200.00
[75896] Ready (ping: 208ms).
Checking again in 25s.                            *Starts to work normally !!!!!!!*

That’s the way Blynk library was written to block everything while connecting to WiFi (unless you use ISR directly) . You can see the code in function void connectWiFi(const char* ssid, const char* pass) of BlynkSimpleEsp8266.h

while (WiFi.status() != WL_CONNECTED) {
            BlynkDelay(500);
        }

At that time, nothing else can execute but ISR. And you’re relying on function checkButton(), which in turn relies on Software Timer to run. But nothing can run then !!!
The solution, if absolutely necessary, is

  1. to use Falling/Rising ISR and call your lean/mean function directly
  2. to use ESP8266TimerInterrupt ( https://github.com/khoih-prog/ESP8266TimerInterrupt ) to call checkButton() and your lean/mean function directly
  3. modify the BlynkSimpleEsp8266.h code like the following to reduce blocking time to max 10s
int i = 0;
while ( (i++ < 40) && (WiFi.status() != WL_CONNECTED) )
{
  delay(250);
}

The other reason is the way Blynk.connect() was written in BlynkProtocol.h can block up to 9s while connecting to Blynk server:

while ((state != CONNECTED) && (BlynkMillis() - started < timeout))
{
   run();
}