Blynk connection lost every 5 minutes. WiFi is fine. Reconnect halts program

Hello,
I have been trying to use blynk as a monitoring system on a nodemcu with a simple timer based sensor read. I also wanted redundancy against power outage and network loss. But when i put this code together, the simple timer would fail to execute about 10% of the time. Deeper dive shows that it was because Blynk.connected() was failing pretty regularly. Exactly 300 seconds regularly in fact, where it would then reconnect and continue to execute my program. Further dive showed that if i reset my router, i could get blykn.connected() to pass for up to time X, where X was the length of my DHCP lease, until it started failing every 300 seconds again. Changing my lease from hours to days could put off the problem unless I reset or update the MCU. I started to think it was the wifi, but further testing showed that wifi was constant through all of this. None of my other wifi devices show internet issues, though i haven’t explicitly tested for it.

The code is the simple Check Blynk code that is posted in this forum (based of Costas work) to run and reconnect during network loss. Perhaps my network settings are wrong?
And this wouldn’t even be an issue, except blynk stops my timers from executing as it tries to reconnect, which can take 5-10 seconds every 5 minutes.

I’ve tried to attach an excel graph from the superchart logging my connected time. This timer resets every time blynk connect or WL_connect failed.
My next step is to add a regular ping command to see if it is all of the internet which is failing every few minutes or only the blynk server connection.

Any advice on how to make a strong, persistent connection to the blynk server without resetting my router every day?

Thanks for the help!

#define NAMEandVERSION "OfflineTask_Reconnect_V1.0"
//#define BLYNK_DEBUG        // Optional, this enables more detailed prints


//
const int SDAPIN= D4;//pin 4 is SDA in software
const int SCLPIN= D5; //pin 5 is SCL in software


 unsigned long TimeOfLastWater_Mem=0; 
unsigned long TimeOfLastWater_BLYNK=0; 

/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial
#include "uEEPROMLib.h" //reads the AT24C32 eeprom in the RTC
#define BLYNK_TIMEOUT_MS  500  // must be BEFORE BlynkSimpleEsp8266.h doesn't work !!!
#define BLYNK_HEARTBEAT   17   // must be BEFORE BlynkSimpleEsp8266.h works OK as 17s
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <DHT.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Time.h>
#include <TimeLib.h>
#include <TimeAlarms.h>
// RealTimeClock Library for DS1307 and DS3231 //       see this page for info on using eeprom https://lastminuteengineers.com/ds3231-rtc-arduino-tutorial/#onboard-24c32-eeprom
#include "RTClib.h"   
RTC_DS3231 RTC_EXTERNAL;

//#include <WidgetRTC.h>
//WidgetRTC RTCWidget;  // requires RTC widget in app
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h> 

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "#######################";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "#############";
char pass[] = "############";
unsigned int port = 8080;
char server[] =    "45.55.96.146"; // can use "blynk-cloud.com" or an IP address. ping blynk-cloud.com and paste result
// Set your Static IP address
IPAddress local_IP(192, 168, 1, 176);  //static IP for nodemcu
// Set your Gateway IP address
IPAddress gateway(192, 168, 1, 254); //router address
IPAddress dns_ip ( 192, 168, 1, 182); // pihole address

IPAddress subnet(255, 255, 255, 0); //I dunno, just copied
byte arduino_mac[] = {0xBC,0xDD,0xC2,0x24,0xEB,0xDC};
#define BLYNK_PRINT Serial

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs). Use the pin umber for the bus. 
//OneWire oneWire(DS18BPIN);

WidgetLED led_light(V50);
WidgetLED led_pump(V51);
WidgetLED led_wifi(V53); //This light on app will be active if connection is live
BlynkTimer timer;
BlynkTimer watertimer;
BlynkTimer sensortimer;
int timer_pump_off;      //this is a timer to turn off the pump. It is activated after pump turns on to make sure it turns off
int timer_sensor_read;   //this timer is controllable from the app. It controls the sensor read frequency.


// Define NTP Client to get time. This runs once during setup in full code and then never again. 
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

unsigned long networkconnecttime= 0; // store the time blynk was connected. Reset each time blynk.connected fails
unsigned long wificonnecttime= 0; // store the time wifi was connected. Reset each time wifi check fails
unsigned int myEthernetTimeout =   20000;  //  5.0s Ethernet Connection Timeout (ECT)
unsigned long blynkInterval     =  120;  // 120.0s Check Server Frequency      (CSF)
unsigned long startConnecting = millis();
bool isFirstConnect=1;
const int MAXRETRY=3;
int eepromLocation=0; //save the location of the eeprom record. should find this at start of each program at Setup. 

bool networkon = 0;
bool online = 0;
///////////////////////////////////////////


//////////////////////////////////////
void CheckConnection(){    // check every 11s if connected to Blynk server
  if(!Blynk.connected())
  {
 //   online = 0;
    yield();
    if (WiFi.status() != WL_CONNECTED)
    {
      wificonnecttime=millis();
      Serial.println("Not connected to Wifi! Connect...");
      //Blynk.connectWiFi(ssid, pass); // used with Blynk.connect() in place of Blynk.begin(auth, ssid, pass, server, port);
     WiFi.setSleepMode(WIFI_NONE_SLEEP);//WIFI_MODEM_SLEEP may work better
      WiFi.config(local_IP, dns_ip, gateway, subnet);
      //WiFi.config(local_ip, gateway_ip, subnet_mask);
      WiFi.begin(ssid, pass);
      delay(400); //give it some time to connect
      if (WiFi.status() != WL_CONNECTED)
      {
        Serial.println("Cannot connect to WIFI!");
        Serial.print("\tReconnection failed. Trying again later. "); 
          
   
       online = 0;
      }
      else
      {
        Serial.println("Connected to wifi!");
      }
    }
    
    if ( WiFi.status() == WL_CONNECTED && !Blynk.connected() )
    {
      networkconnecttime=millis(); 
      Serial.println("Not connected to Blynk Server! Connecting..."); 
      Blynk.connect();  // // It has 3 attempts of the defined BLYNK_TIMEOUT_MS to connect to the server, otherwise it goes to the next line 
      if(!Blynk.connected()){
        Serial.println("Connection failed!");
        Serial.print("\tReconnection failed. Trying again later. "); 
        online = 0;
      }
      else
      {
        online = 1;
      }
    }
  }
  else{
    Serial.println("Connected to Blynk server!"); 
   
    //online = 1;   
    Blynk.virtualWrite(V22, millis() / 1000 /60);
  Blynk.virtualWrite(V23, (millis()-networkconnecttime) / 1000); //find out how much time has passed since the last internet outtage
  Blynk.virtualWrite(V24, (millis()-wificonnecttime) / 1000); //find out how much time has passed since the last internet outtage
  }
    
}




////////////////////////////////////////////////////
//              Setup                            //
///////////////////////////////////////////////////
void setup()
{
  // Debug console

  #ifndef ESP8266 //part of rtc library?
  while (!Serial); // for Leonardo/Micro/Zero 
#endif
    Serial.println("Welcome to Setup!");

  Serial.begin(115200);

 Wire.begin(SDAPIN, SCLPIN);  //Wire.begin(SDA,SCL) allows us to change the pins the clock uses


 
  RTC_EXTERNAL.begin();      // Synchronize with widget (server) time on connection
//  setSyncProvider(syncProvider);   // the function to get the time from the RTC
  if(timeStatus() != timeSet)
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");  

    
 Blynk.begin(auth, ssid, pass);
  // You can also specify server:
  //Blynk.begin(auth, ssid, pass, "blynk-cloud.com", 80);
  //Blynk.begin(auth, ssid, pass, IPAddress(192,168,1,100), 8080);


timer.setInterval(15000L, CheckConnection);   // check connection to server per blynkInterval


Serial.println("Setup Complete. \n"); 
}




////////////////////////////////////////////////
              //LOOP//
////////////////////////////////////////////////////
void loop()
{
  timer.run();
  // only attempt Blynk-related functions when connected to Blynk
  if (Blynk.connected())
  {
    Blynk.run();
  }
}

This should be a graph showing how blynk.connect time cycles every 5 min during continuous wifi connection.

I can’t figure-out what you are trying to do with your network settings.
You define all these network settings…

but then you don’t use them when you initially connect to the network and Blynk:

The Blynk.begin command will establish the Wi-Fi network (using DHCP) then the connection to the Blynk cloud server. If the device disconnects then you’re attempting to force it to rte-connect to your Wi-Fi with a totally different set of network credentials.

BTW, you don’t need to do this:

a single blynk timer object (lets call it BlynkTimer timer) can support upto 16 separate timers.

I also wouldn’t do all the NTP stuff, I’d use the Blynk RTC widget, which works very well when the device is offline.

Pete.

Besides what @PeteKnight said, the real issue here is this code in the loop preventing the auto-reconnection to Blynk

if (Blynk.connected())
  {
    Blynk.run();
  }

Use the standard loop() to enable auto-reconnecting

Blynk.run();
timer.run();

Why?
Blynk.run() has some internal functions to manage the reconnection when WiFi and/or Blynk is lost.

Using the original code, if you have some issue with WiFi/Blynk, then Blynk.connected() is false, and Blynk.run() is disabled.

I now see you have timer to CheckConnection. It’s better, but have to wait some time (15s).

You can check and try

where you can specify Multi WiFi / Servers and better auto-reconnect

Thanks for the response,
If i remove the IsConnected check and internet is truly down for extended periods, won’t Blynk.run() get stuck in a reconnect loop where none of the offline functions will execute? And this still doesn’t address the issue as to why Blynk.Connected() is returning 0 every 5 minutes.

In my first design without Blynk, i have an RTC which keeps all the timer activities independent of black and brownout conditions. I’ve been trying to preserve that functionality as i migrated to Blynk.

This issue lies somewhere in your code and/or your network/router/Internet. Only you can narrow down, starting from the simplest Blynk code, then adding more and more, with lots of debugging msgs.
You have to completely understand why/where and solve it before moving forward.

1 Like

Hey Peter,
I broke out the timers because some problems i think i found in the library. If you check Number.enabled before you declare a timer object, you get 0xFFFF (x16) instead of 0. This caused a bunch of issues where enabling and disabling a single timer caused other timers in the instance to also fail. By separating out the timers to their own instance, i could prevent a lot of this crosstalk.
I removed the blynk RTC during troubleshooting. I wanted to align clocks at the start o the skech, but the blynk RTC set up its own setsyncprovider when called and thought that this sync was responsible for the periodic disconnects as it kept trying to update the internal RTC. The NTP i can fire off once during setup to align my RTC and then disable once Blynk starts running.

I made some adjustments to the network credentials and removed blynk.begin for blynk.config and wifi.config. The end result is unchanged, and i still get connection loss. Wifi does fail to connect on first pass though, but seems to work at the next checkconnection().

void setup()
{
  // Debug console

  #ifndef ESP8266 //part of rtc library?
  while (!Serial); // for Leonardo/Micro/Zero 
#endif
    Serial.println("Welcome to Setup!");

  Serial.begin(115200);


Serial.print(ESP.getFullVersion());
WiFi.hostname(NAMEandVERSION);
WiFi.mode(WIFI_STA);
WiFi.setSleepMode(WIFI_NONE_SLEEP);//WIFI_MODEM_SLEEP may work better

WiFi.config(local_IP, dns_ip, gateway, subnet);
WiFi.begin(ssid, pass); //start wifi, then connect
  Serial.print("localIP: ");
  Serial.println(WiFi.localIP());


Blynk.config(auth, server, port); 
 CheckConnection();// It needs to run first to initiate the connection.Same function works for checking the connection!

 
    
timer.setInterval(15000L, CheckConnection);   // check connection to server per blynkInterval
Serial.println("Setup Complete. \n"); 
}


////////////////////////////////////////////////
              //LOOP//
////////////////////////////////////////////////////
void loop()
{
  timer.run();
  // only attempt Blynk-related functions when connected to Blynk
  if (Blynk.connected())
  {
    Blynk.run();
  }
}

//////////////////////////////////////
void CheckConnection(){    // check every 11s if connected to Blynk server
 
  if(!Blynk.connected())
  {
 //   online = 0;
    yield();
    if (WiFi.status() != WL_CONNECTED)
    {
      wificonnecttime=millis();
      Serial.println("Not connected to Wifi! Connect...");
      //Blynk.connectWiFi(ssid, pass); // used with Blynk.connect() in place of Blynk.begin(auth, ssid, pass, server, port);
     WiFi.setSleepMode(WIFI_NONE_SLEEP);//WIFI_MODEM_SLEEP may work better
      WiFi.config(local_IP, dns_ip, gateway, subnet);
      //WiFi.config(local_ip, gateway_ip, subnet_mask);
      WiFi.begin(ssid, pass);
      delay(400); //give it some time to connect
      if (WiFi.status() != WL_CONNECTED)
      {
        Serial.println("Cannot connect to WIFI!");
        Serial.print("\tReconnection failed. Trying again later. "); 
          
   
       online = 0;
      }
      else
      {
        Serial.println("Connected to wifi!");
      }
    }
    
    if ( WiFi.status() == WL_CONNECTED && !Blynk.connected() )
    {
      Serial.println("WiFi on, but not connected to Blynk Server! Connecting..."); 
      networkconnecttime=millis(); 
    Serial.print("Pinging ip ");
  Serial.println("www.google.com");

  if(Ping.ping("www.google.com")) {
    Serial.println("Ping Google Successfully!");
    pingsuccess+=1; 
  } else {
    Serial.println("Ping Error :(");
    pingsuccess=0; 
  }
      Blynk.connect();  // // It has 3 attempts of the defined BLYNK_TIMEOUT_MS to connect to the server, otherwise it goes to the next line 
      if(!Blynk.connected()){
        Serial.println("Connection failed!");
        Serial.print("\tReconnection failed. Trying again later. "); 
        online = 0;
      }
      else
      {
        online = 1;
      }
    }
  }
  else{
    Serial.println("Connected to Blynk server!"); 

 

   
    //online = 1;   
    Blynk.virtualWrite(V22, millis() / 1000 /60);
  Blynk.virtualWrite(V23, (millis()-networkconnecttime) / 1000); //find out how much time has passed since the last internet outtage
  Blynk.virtualWrite(V24, (millis()-wificonnecttime) / 1000); //find out how much time has passed since the last internet outtage
  Blynk.virtualWrite(V25, pingsuccess); 
  }
    
}

I added a ping test to google that runs every time blynkcheck runs. So far, whenever blynk connect fails, i can still ping google, so i’m not losing my full internet connection, just the connection to Blynk. Is there a way to see if i’m overloading the server and getting rejected?

My serial out looks as follows. At the bottom you can see where a re-connection started after blynk failed to connect. Google is pinged successfully right before.

SDK:2.2.2-dev(38a443e)/Core:2.6.3=20603000/lwIP:STABLE-2_1_2_RELEASE/glue:1.2-16-ge23a07e/BearSSL:89454aflocalIP: 192.168.1.176
23:22:35.593 -> [159] 
23:22:35.593 ->     ___  __          __
23:22:35.593 ->    / _ )/ /_ _____  / /__
23:22:35.593 ->   / _  / / // / _ \/  '_/
23:22:35.593 ->  /____/_/\_, /_//_/_/\_\
23:22:35.593 ->         /___/ v0.6.1 on NodeMCU
23:22:35.635 -> 
23:22:35.635 -> Not connected to Wifi! Connect...
23:22:36.072 -> Cannot connect to WIFI!
23:22:36.072 -> 	Reconnection failed. Trying again later. Setup Complete. 
23:22:36.106 -> 
23:22:51.067 -> WiFi on, but not connected to Blynk Server! Connecting...
23:22:51.100 -> Pinging ip www.google.com
23:22:55.237 -> Ping Google Successfully!
23:22:55.237 -> [19815] Connecting to 45.55.96.146:8080
23:22:55.408 -> [19983] Ready (ping: 84ms).
23:23:06.083 -> Connected to Blynk server!
23:23:21.096 -> Connected to Blynk server!
23:23:36.083 -> Connected to Blynk server!
23:23:51.066 -> Connected to Blynk server!
23:24:06.083 -> Connected to Blynk server!
23:24:21.087 -> Connected to Blynk server!
23:24:36.090 -> Connected to Blynk server!
23:24:51.094 -> Connected to Blynk server!
23:25:06.086 -> Connected to Blynk server!
23:25:21.091 -> Connected to Blynk server!
23:25:36.070 -> Connected to Blynk server!
23:25:51.068 -> Connected to Blynk server!
23:26:06.076 -> Connected to Blynk server!
23:26:21.093 -> Connected to Blynk server!
23:26:36.100 -> Connected to Blynk server!
23:26:51.092 -> Connected to Blynk server!
23:27:06.086 -> Connected to Blynk server!
23:27:21.071 -> Connected to Blynk server!
23:27:36.075 -> Connected to Blynk server!
23:27:51.086 -> Connected to Blynk server!
23:28:06.099 -> WiFi on, but not connected to Blynk Server! Connecting...
23:28:06.099 -> Pinging ip www.google.com
23:28:10.196 -> Ping Google Successfully!
23:28:10.196 -> [334768] Connecting to 45.55.96.146:8080
23:28:10.366 -> [334937] Ready (ping: 83ms).
23:28:21.092 -> Connected to Blynk server!
23:28:36.077 -> Connected to Blynk server!

That’s not a problem with the library, it’s a problem with how you are using the library.
When you create a timer instance it is assigned a timer ID. This is a zero-based allocation process, which will normally result in the first timer being assigned the ID of 0, the second the ID of 1 etc. up to ID 15 for BlynkTimer.
However, when you delete and create/recreate timers on the fly within your program flow it can be difficult to predict which ID will be assigned to a specific timer instance. Therefore, the library has the facility to return an integer value when a timer is created, which can be used to reference the timer instance when you want to disable/enable/delete it in future.

BlynkTimer timer;

int connection_timer_ID;
int water_timer_ID;
int sensor_timer_ID;

connection_timer_ID = timer.setInterval(15000L, CheckConnection);
water_timer_ID = timer.setInterval(xxx, xxx);
int sensor_timer_ID = timer.setInterval(yyy, yyy);

Asking BlynkTimer “hey, is timer ID 15 enabled” before you’ve declared a timer that has been allocated timer ID 15 isn’t really a sensible approach.

As far as your main issue is concerned, I think you’re going the wrong way with this. You’re adding-in more and more complexity, at times without appearing to be using optimal code for things like establishing your Wi-Fi connection and checking if Blynk is connected.
I’d go the other way and strip this down to the simplest code structure possible to try to get to the bottom of your issue.

Pete.

Ok, i simplified the program and removed all the workarounds i had added. Perhaps it is a wrong port or server?
I set up an internet monitor to log whenever network is down for >1s. It shows some disconnectivity, but at a different frequency than the 5min blynk experiences. Even now its been at least 20min with no issues, so i’m still weary to believe it is my ISP. It also shows that the ping to the blynk server, 45.55.96.146 is 4-200x longer than the ping to google through the course of the day.

#define BLYNK_DEBUG        // Optional, this enables more detailed prints




/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial

#define BLYNK_TIMEOUT_MS  500  // must be BEFORE BlynkSimpleEsp8266.h doesn't work !!!
#define BLYNK_HEARTBEAT   17   // must be BEFORE BlynkSimpleEsp8266.h works OK as 17s
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>


// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "###";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "Operation PRISM";
char pass[] = "###";
unsigned int port = 8080;
char server[] =    "45.55.96.146"; // can use "blynk-cloud.com" or an IP address. ping blynk-cloud.com and paste result
// Set your Static IP address

#define BLYNK_PRINT Serial

BlynkTimer timer;


// Define NTP Client to get time

unsigned long networkconnecttime= 0; // store the time blynk was connected. Reset each time blynk.connected fails
unsigned long wificonnecttime= 0; // store the time wifi was connected. Reset each time wifi check fails

bool networkon = 0;
bool online = 0;
 
///////////////////////////////////////////


//////////////////////////////////////
void CheckConnection(){    // check every 11s if connected to Blynk server
 
  if(!Blynk.connected())
  {
 //   online = 0;
    yield();
       
    if ( WiFi.status() == WL_CONNECTED && !Blynk.connected() )
    {

      Blynk.connect();  // // It has 3 attempts of the defined BLYNK_TIMEOUT_MS to connect to the server, otherwise it goes to the next line 
      if(!Blynk.connected()){
        Serial.println("Connection failed!");
        Serial.print("\tReconnection failed. Trying again later. "); 
        online = 0;
      }
     }
  }
  

else{
    Serial.println("Connected to Blynk server!"); 
 
    Blynk.virtualWrite(V22, millis() / 1000 /60);
  Blynk.virtualWrite(V23, (millis()-networkconnecttime) / 1000); //find out how much time has passed since the last internet outtage
   }
    
}




////////////////////////////////////////////////////
//              Setup                            //
///////////////////////////////////////////////////
void setup()
{
  // Debug console

  #ifndef ESP8266 //part of rtc library?
  while (!Serial); // for Leonardo/Micro/Zero 
#endif
    Serial.println("Welcome to Setup!");

  Serial.begin(115200);

Serial.print(ESP.getFullVersion());
 CheckConnection();// It needs to run first to initiate the connection.Same function works for checking the connection!
  
 Blynk.begin(auth, ssid, pass);
 
timer.setInterval(15000L, CheckConnection);   // check connection to server per blynkInterval

}

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

The serial out is below, surrounding a disconnect and reconnect. Does this show anything is useful?
09:05:11.343 -> Connected to Blynk server! //all is well
09:05:11.378 -> [50420232] <[14|00]`[00|09]vw[00]22[00]840
09:05:11.413 -> [50420300] <[14|00]a[00|0B]vw[00]23[00]50420
09:05:11.483 -> [50420367] <[14|00]b[00|0A]vw[00]24[00]2130
09:05:11.553 -> [50420434] <[14|00]c[00|07]vw[00]25[00]0
09:05:21.709 -> [50430594] Connecting to blynk-cloud.com:80 // <==Failure occurs here. disconnected, attempting reconnect, 5min after last disconnect
09:05:21.813 -> [50430681] <[1D|00|01|00] ################# //my token removed
09:05:21.917 -> [50430780] >[00|00|01|00|C8]
09:05:21.917 -> [50430780] Ready (ping: 98ms).
09:05:21.917 -> [50430780] Free RAM: 48936
09:05:21.960 -> [50430847] <[11|00|02|00]Hver[00]0.6.1[00]h-beat[00]17[00]buff-in[00]1024[00]dev[00]NodeMCU[00]build[00]Mar 20 2020 19:04:25[00]
09:05:22.053 -> [50430935] >[00|00|02|00|C8]
09:05:26.370 -> Connected to Blynk server! //Reconnected once more
09:05:26.370 -> [50435232] <[14|00|03|00|09]vw[00]22[00]840
09:05:26.438 -> [50435300] <[14|00|04|00|0B]vw[00]23[00]50435
09:05:26.508 -> [50435367] <[14|00|05|00|0A]vw[00]24[00]2145
09:05:26.575 -> [50435434] <[14|00|06|00|07]vw[00]25[00]0
09:05:39.060 -> [50447936] <[06|00|07|00|00]
09:05:39.165 -> [50448023] >[00|00|07|00|C8]

Are you sure that this debug output was created with this code?
It appears to be reporting virtual writes to pins V24 and V25 that aren’t in your code.

Pete.

This message does not mean that the device has re-connected to the Blynk server, it’s a message that you’ve coded into your CheckConnection() function and will alway be printed when Blynk.connected() = true.

void CheckConnection(){    // check every 11s if connected to Blynk server
 
  if(!Blynk.connected())
  {
     // do some stuff if disconnected... 
  }
  else
  {
    Serial.println("Connected to Blynk server!"); 
    Blynk.virtualWrite(V22, millis() / 1000 /60);
    Blynk.virtualWrite(V23, (millis()-networkconnecttime) / 1000); //find out how much time has passed since the last internet outage
  }

This message should really say “Blynk is still connected, carry on as normal”

Also, you have two #define BLYNK_PRINT Serial lines in your code, and this line in your void setup is untrue:

CheckConnection();// It needs to run first to initiate the connection.Same function works for checking the connection!

when using Blynk.begin (as this sketch does) the connection will be made automatically when Blynk.begin executes.

Pete.