Help on keep device connected to Blynk. No clear reason for device be offline

Hello every body,
I hope you are all doing well.
Could you help me on solving a problem?

I am testing Blynk on a ESP32-S3 connected to 8 Temperature sensors (DS18B20) to measure 8 aquariums. Five are linked to Blink for software test (v1-v5), and I am prone to install more devices with many sensors as soon as I get the sketch running well with Blynk.

Temperatures are collected every second and the average of 60 seconds are send to Blink, i. e., Blink receives five values every minute. The sketch works perfect locally, showing data on screen and logging in a SD card. Nevertheless, Blynk is very important for remote monitoring.

==> The connection with Blynk occurs perfectly at the start and I can follow values on App or Console, but after a while…minutes or even hours… the device becomes offline, although it continues to collect, show and log data. It also “tries” to send data to Blynk. The reset of the uC solves the issue, but graphs on Blynk app miss the data.

Based on code found in this community I set up a function to monitor the connection and reestablish in case of (Blynk. connected() == false). I use a Blynktimer to check every 20 seconds. ==> NO SUCCESS.
I also change the Heartbeat to 20 seconds. NO SUCCESS
So, I put
#define BLYNK_DEBUG_ALL
… to follow the communication between Device<->Blynk and share here to help on diagnosis.

I hope to find a solution. Thanks in advance!

Traits of the project:
I use FreeRTOS. Blynk.run() and timer.run() are placed within a task pinned to Core1 as follows:

void BlynkLoop (void * pvParameters) {
  (void) pvParameters;
  Serial.println("Blynk-Loop Task Started");
    
  for(;;) {
    if (Blynk.connected()) Blynk.run();
    timer.run();
    vTaskDelay(1); //feed the watchdog
  }
}

There is a function that sends data to Blynk after 60 measuremens:

 void SendDataToBlynk(){
  debugln("\n  ->  Start Sending Data to Blynk "); //Serial.println
  uint64_t TimeStamp = ((uint64_t)now.unixtime()+10800)*1000;  //Time Stamp (milliseconds + 3hours)
  
  Blynk.beginGroup(TimeStamp);  
  Blynk.virtualWrite(V1, (double)(TempAverage[0]));
  Blynk.virtualWrite(V2, (double)(TempAverage[1]));
  Blynk.virtualWrite(V3, (double)(TempAverage[2]));
  Blynk.virtualWrite(V4, (double)(TempAverage[3]));
  Blynk.virtualWrite(V5, (double)(TempAverage[4]));
  Blynk.endGroup();

  debugln("  -| End Sending Data to Blynk \n");
}

To monitor the connections a Blynk timer was initiated at setup():

  connection_timer_ID = timer.setInterval(20000L, Blynk_CheckConnection);

Which calls the the Function void Blynk_CheckConnection () as follows:

void Blynk_CheckConnection(){
  if (!(Blynk.connected())) {
    if(WiFi.status() != WL_CONNECTED) {
      debugln(" WiFi connection was lost!");
      WiFi_Disconnect();
      WiFi_ConnectAsClient();
      Blynk.connect();
    } else {
      debugln(" Blynk server connection was lost");
      Blynk.connect();
    }
  }

Here is the Serial.print output when connection is ok. One can see the one second value followed 60 second average. I cut part of the printout for simplicity. It is possible to see the device pinging to server, which stops when it appears offline. Blynk.connected() is always true, even when the device is offline.

[3767] Connected to WiFi
[3767] IP: 192.168.1.34
[3767] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v1.3.2 on ESP32-S3

 #StandWithUkraine    https://bit.ly/swua


[3768] Connecting to blynk.cloud:80
[4037] <[1D|00|01|00|20]**********
[4182] >[00|00|01|00|C8]
[4183] Ready (ping: 144ms).
[4183] Free RAM: 280608
[4183] Waiting:50
[4234] <[11|00|02|00]}mcu[00]0.0.0[00]fw-type[00]TMPL20ZbxYhJ7[00]build[00]May[20|20]7[20]2024[20]21:40:06[00]blynk[00]1.3.2[00]h-beat[00]20[00]buff-in[00]1024[00]dev[00]ESP32-S3[00]tmpl[00]TMPL20ZbxYhJ7

 Blynk Connected!

Blynk Loop Task Started
[6403] >[00|00|02|00|C8]
01 - 29.81  29.69  29.62  30.00  29.50  29.62  29.38  29.69
02 - 29.81  29.69  29.62  30.00  29.50  29.62  29.38  29.69
03 - 29.81  29.69  29.62  30.00  29.50  29.62  29.38  29.69
04 - 29.81  29.69  29.62  30.00  29.50  29.62  29.38  29.69
05 - 29.81  29.69  29.62  30.00  29.50  29.62  29.38  29.69 
06 - 29.81  29.69  29.62  30.00  29.50  29.62  29.38  29.69
07 - 29.81  29.69  29.62  30.00  29.50  29.62  29.38  29.69
...
17 - 29.81  29.69  29.62  30.00  29.50  29.62  29.38  29.69
18 - 29.81  29.69  29.62  30.00  29.50  29.62  29.38  29.69
[24239] <[06|00|03|00|00]
[24414] >[00|00|03|00|C8]
19 - 29.81  29.69  29.62  30.00  29.50  29.62  29.38  29.69
20 - 29.81  29.69  29.62  30.00  29.50  29.62  29.38  29.69
Blink connected
21 - 29.81  29.69  29.62  30.00  29.50  29.62  29.38  29.69
...

58 - 29.81  29.69  29.62  30.00  29.56  29.69  29.38  29.69
[64246] <[06|00|05|00|00]
[64455] >[00|00|05|00|C8]
59 - 29.81  29.69  29.62  30.00  29.50  29.69  29.38  29.69
60 - 29.81  29.69  29.62  30.00  29.50  29.69  29.38  29.69

Avg  29.81 29.69 29.62 30.00 29.51 29.64 29.37 29.69  (°C) 2024-05-08T12:29:19
 
  -> Start Sending Data to Blynk
[66058] <[15|00|06|00|0F]t[00]1715182159000
[66060] <[14|00|07|00|0F]vw[00]1[00]29.8125000
[66062] Waiting:49
[66112] <[14|00|08|00|0F]vw[00]2[00]29.6875000
[66113] Waiting:50
[66164] <[14|00|09|00|0F]vw[00]3[00]29.6250000
[66165] Waiting:50
[66216] <[14|00|0A|00|0F]vw[00]4[00]30.0000000
[66217] Waiting:50
[66268] <[14|00|0B|00|0F]vw[00]5[00]29.5062504
[66269] <[15|00|0C|00|01]e
  -| End Sending Data to Blynk 

Blink connected
01 - 29.81  29.69  29.62  30.00  29.50  29.69  29.38  29.69
...

Here is the Serial.print output when devide is offline.

57 - 29.75  29.62  29.56  29.94  29.44  29.56  29.31  29.62 
58 - 29.75  29.62  29.56  29.94  29.44  29.56  29.31  29.62 
59 - 29.75  29.62  29.56  29.94  29.44  29.56  29.31  29.62  
60 - 29.75  29.62  29.56  29.94  29.44  29.56  29.31  29.62

Avg  29.74 29.62 29.54 29.94 29.44 29.56 29.31 29.62  (°C) 2024-05-08T12:20:54

  ->Start Sending Data to Blynk 
[12903088] Cmd skipped:20
[12903088] Cmd skipped:20
[12903088] Cmd skipped:20
[12903088] Cmd skipped:20
[12903089] Cmd skipped:20
  -| End Sending Data to Blynk 

01 - 29.75  29.62  29.56  29.94  29.44  29.56  29.31  29.62  
02 - 29.75  29.62  29.56  29.94  29.44  29.56  29.31  29.62  
03 - 29.75  29.62  29.56  29.94  29.44  29.56  29.31  29.62  
Blink connected                                                                         <=== SHOWS CONNECTED BESIDES DEVICE OFFLINE 
04 - 29.75  29.62  29.56  29.94  29.50  29.5

Question - do you have any other devices that are using the same Blynk auth token as this one?

Observations…

  1. You haven’t shared your code, apart from a meaningless snippet, so its difficult to comment.
  2. Having BLYNK_DEBUG turned on doesn’t help - in fact it makes this harder to follow.
  3. Reducing the heartbeat to 20 seconds will probably make things worse, but it depends on how you’ve written your code.
  4. Blynk.connected() is probably being misused in your sketch.

Pete.

Hi Pete,

Thanks for the answer!

No. This is the first one and the only one at moment. So there is no conflict with other device
The sketch is getting big and under construction, I will not send everything but the setup and the important functions, Setup() calls other functions inside to initialise the peripherals: Sensors, TFT, DS3231RTC, SD card, Buttons, and the FreeRTOS Tasks. Initialisations and function declarations are in separate “.h” files. I am sending here the part related to Blynk.

Basically, the 1 Hz square wave pin from the DS3231 is used to sync the measurements with precision and independent of the core activity through an interruption attached to a pin. The OneSecondTimer_ISR() notifies the Task xReadTempSensors (at Core1). After reading the 8 sensors, this tasks commands the sensors to integrate the next measurement and notifies the Task xAverage to run and store the values in a array [8][60]. At the 60th measurement, the average of each sensor is calculated. This part has the highest priority in order to have a good precision between measurement and time stamp. I could even monitor it on the oscilloscope. It takes a bit 108 ms to measure and store the data: 1/10th of the time of core1 is taken every second. xAverage frees xLogData, in which data log and sent to Blynk, to run every 60th seconds and xDrawScreen, xPrintTemperatures every second.

This functions works fine and synchronised independent of Blynk. I “insert” Blynk after that.
I tried to put on loop() but i experienced crashes. I followed the strategy of @CampHamp and placed the Blynk.run() to be pooled in a task BlynkLoop() pinned to Core0 with minimal delay.

It will be good to understand more deeply what Blink.run() does. I could see it pinging to the server when ok and not doing it when offline. So, in my sketch, it seems stopping pinging. I do not know why. Could it be its interaction with FreeRTOS, getting interrupted by other tasks? I could not understand why Blynk.connected() returns “true” when the device is already long offline. What could cause that? Blynk.connected() is within a function attached to a Blynktimer (as in the firs post) and also hear shown in setup() code. The timer calls the function, it runs and returns the value of Blynk.connected().

Below you will find the Setup() code which creates the the FreeRTOS functions responsible for the program flow. Also the tasks responsible for data read, average, log, and Serial print.
the function SendDataToBlynk() is called within the Task xLogData(), just after appending the data to logfile.

My best regards,
Heitor


//FreeRTOS
#if CONFIG_FREERTOS_UNICORE // Check how many cores the uC has
    static const BaseType_t app_cpu = 0;
#else
    static const BaseType_t app_cpu = 1;
#endif

// Debug settings 
#define DEBUG 1 // 0 for remove debuglines
#if DEBUG == 1
    #define debug(x) Serial.print(x)
    #define debug2(x,y) Serial.print(x,y)
    #define debugln(x) Serial.println(x)
#else 
    #define debug(x)
    #define debug2(x,y)
    #define debugln(x)
#endif

// Blynk 
#define BLYNK_DEBUG_ALL
#define BLYNK_PRINT Serial

#define BLYNK_TEMPLATE_NAME "TempLogger"
#define BLYNK_TEMPLATE_ID   "T*****"
#define CONFIG_DEVICE_PREFIX "Blynk"
#define BLYNK_AUTH_TOKEN "*****"
#define BLYNK_CONNECT_TIMEOUT 5000 // 5 seconds

#include <BlynkSimpleEsp32.h> // does not work if putted before #defines
BlynkTimer timer;
int connection_timer_ID;

//Blynk functions
void Blynk_CheckConnection();
void SendDataToBlynk();

/* ----------------------------------------------
//  TASKs FUNCTIONS and  associated setup
//  ----------------------------------------------*/

// TEMPORARY! just to monitor Task Stack Size Use. remove after code completion
// use: UBaseType_t= uxTaskGetStackHighWaterMark(TaskHandle_t myTaskhandler);
UBaseType_t  FreeSensorRead, FreeAverage, FreeScreen, FreeSerial, FreeLog; 

// TASKS
void BlynkLoop (void * pvParameters);

TaskHandle_t ReadTempSensors_h;
void xReadTempSensors(void *pvParameters);

TaskHandle_t xAverage_h;
void xAverage (void *pvParameters);
bool hasAverage = false;
const int hasMeasured_BIT = BIT0;

TaskHandle_t xDrawScreen_h;
void xDrawScreen(void *pvParameters);
const int DrawScreen_BIT = BIT1;
bool DrawAll = false;

TaskHandle_t xPrintTemperatures_h;
const int PrintTemperatures_BIT = BIT2;
void xPrintTemperatures(void *pvParameters);

TaskHandle_t LogData_h;
void xLogData (void *pvParameters);
const int LogData_BIT = BIT3;

// Handle of event group used to sinchronize tasks
EventGroupHandle_t egTheEvents_h; 

/* ----------------------------------------------
//    TASKs FUNCTIONS and  associated setup END
// ----------------------------------------------*/

void setup() {
  Serial.begin(115200);
  delay(2000);
  
  Blynk.begin(BLYNK_AUTH_TOKEN, client_ssid, client_password);
  while (!Blynk.connected());
  if (!Blynk.connected()) debugln ("\n Blynk NOT connected");
  else debugln("\n Blynk Connected!");

 //PINS
  pinMode(LCD_POWER_ON, OUTPUT); // Battery boot and LCD ON
  digitalWrite(LCD_POWER_ON, HIGH);

  //Butoons
  pinMode(BUTTON_1, INPUT_PULLUP);
  pinMode(BUTTON_2, INPUT_PULLUP);
  
  //ADC Battery Voltage
  pinMode(BAT_VOLT, INPUT); //ADC at GPIO_NUM_4 -> ADC_CHANNEL_3
  adc1_config_width(ADC_WIDTH_BIT_12);
  adc1_config_channel_atten(ADC1_CHANNEL_3, ADC_ATTEN_11db);
  esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_11db, ADC_WIDTH_BIT_12, 1100, &adc_chars);

  SplashSerialScreen(); // ESP32 infos
  setup_DS3231_RTC(); //Real Time Clock and 1Hz square wave generator
  
  // Connect to Wifi and set the time.
  //WiFi_ConnectAsClient();
  //Adjust_RTC_byNPT();
  //WiFi_Disconnect();
 
  //PSRAM init
  if(psramInit()) debugln(" PSRAM - ok");  
  else debugln("\nPSRAM NOT ok");
        
  // Screen
  tftSetup();
  TFTdimming(dimmValue);

  //SD-Card
  Setup_SD_FS ();
  Create_Log_File();

  //Dallas Sensors DS18B20
  setupTemperatureSensors(); 

  //RTOS tasks
  egTheEvents_h = xEventGroupCreate();
  xTaskCreatePinnedToCore(BlynkLoop, "blynk", 100000, NULL, 1, NULL, 0);
  xTaskCreatePinnedToCore(xReadTempSensors, "ReadTempSensors", 5*512, NULL, 5, &ReadTempSensors_h, 1); // Use address of handle = &handles
  xTaskCreate(xAverage, "Avergage Sensors", 2*512, NULL, 6, &xAverage_h );
  xTaskCreate(xDrawScreen, "DrawScreen", 6*512, NULL, 2, &xDrawScreen_h); 
  xTaskCreate(xPrintTemperatures, "PrintTemperatures", 10*512, NULL, 1, &xPrintTemperatures_h);
  xTaskCreate(xLogData, "LogData", 5*1024, NULL, 4, &LogData_h);  
  
  // Interrupts for DS3231 at GPIO_NUM_44
  attachInterrupt(GPIO_NUM_44,  OneSecondTimer_ISR, FALLING); // External Hardware timer:
  onRecord = true;

  // Blink timer to check server connectionn periodically
  connection_timer_ID = timer.setInterval(20000L, Blynk_CheckConnection);

  // Button handling using OnButton Library
  Button1.attachClick(Button1_Click);
  Button2.attachClick(Button2_Click);
  Button2.attachLongPressStop(Button2_LongClick);
} 

void loop() { //spooling the buttons
  Button1.tick();
  Button2.tick();
}

void BlynkLoop (void * pvParameters) {
  (void) pvParameters;
  Serial.println("Blynk Loop Task Started");
    
  for(;;) {
    if (Blynk.connected()) Blynk.run();
    timer.run();
    vTaskDelay(1); //feed the watchdog
  }
}

void Blynk_CheckConnection(){
  if (!(Blynk.connected())) {
    if(WiFi.status() != WL_CONNECTED) {
      debugln(" WiFi connection was lost!");
      WiFi_Disconnect();
      WiFi_ConnectAsClient();
      Blynk.connect();
    } else {
      debugln(" Blynk server connection was lost");
      Blynk.connect();
    }
  }
  else debugln("Blink connected");
}
void IRAM_ATTR OneSecondTimer_ISR() { // ISR 
  BaseType_t task_woken = pdFALSE;
  // notify the task xReadTempSensors via ReadTempSensors_h hadle
  vTaskNotifyGiveFromISR(ReadTempSensors_h, &task_woken ); 
} 

void xReadTempSensors(void *pvParameters) {
  (void) pvParameters;
  EventBits_t myEventBits;
  for (;;) {
    //Stack size monitoring - DELETE when READY
    FreeSensorRead = uxTaskGetStackHighWaterMark(ReadTempSensors_h);
    
    //Unblock at falling edge DS3231 sqw wave and reset the notification (<4us)
    ulTaskGenericNotifyTake(tskDEFAULT_INDEX_TO_NOTIFY, pdTRUE, portMAX_DELAY);

    //read all sensors
    for (uint8_t i = 0; i < sensorsNumber; i++){ 
      sTemp[i] = sensors.getTempC(sensor[i]);
    }
    now = rtc.now(); //DS3231 time
    SampleN = count;
    count++;
    if (count > 59) count = 0;
    
    // ADC battery voltage is HW and SW corrected (ESP32-S3) (<2uS)
    BattVolt = 0.19 + (float)esp_adc_cal_raw_to_voltage(adc1_get_raw(ADC1_CHANNEL_3), &adc_chars) * 0.002;

    xEventGroupSetBits(egTheEvents_h, hasMeasured_BIT); // Release for xAverge Task
    sensors.requestTemperatures();
  }
}

void xAverage (void *pvParameters) {
  (void) pvParameters;
  EventBits_t myEventBits;

  for (;;){
    // Wait for 
    myEventBits = xEventGroupWaitBits(egTheEvents_h, hasMeasured_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
    FreeAverage = uxTaskGetStackHighWaterMark(xAverage_h);

    for (uint8_t i = 0 ; i< sensorsNumber; i++){  //7uS
      sTempMinute [i] [SampleN] = sTemp [i];
    }
    
    if (SampleN >= 59) { //15us to calculate average from 8 arrays of 60 floats
      hasAverage = true;
      for (uint8_t i = 0; i < sensorsNumber; i++){
        TempAverage[i] = 0; 
        for (uint8_t j = 0; j < 60 ; j++) {
          TempAverage[i] += sTempMinute[i][j];
        }
        TempAverage[i] /= 60;
      }
      FreeAverage = uxTaskGetStackHighWaterMark(xAverage_h);
      xEventGroupSetBits(egTheEvents_h, LogData_BIT); //Ready to log!

    } 
    else {
      hasAverage = false;
    }
    
    // after passing values to arrays allows Screen and Serial outputs tasks - core independent
    xEventGroupSetBits(egTheEvents_h, DrawScreen_BIT | PrintTemperatures_BIT); //Set eventgroup bits takes 4.2us.
  }
}

void xLogData (void *pvParameters){
  (void) pvParameters;    
  EventBits_t myEventBits;
  char dataBuffer [256];

  for(;;) {
    // Task synchronization
    myEventBits = xEventGroupWaitBits(egTheEvents_h, LogData_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
    FreeLog = uxTaskGetStackHighWaterMark(xPrintTemperatures_h);
    
    // Log Data
    const char * format = "%02u/%02u/%02u %02u:%02u:%02u, %5.2f, %5.2f, %5.2f, %5.2f, %5.2f, %5.2f, %5.2f, %5.2f\r\n";
    sprintf (dataBuffer,  format, now.day(), now.month(), now.year()
                              , now.hour(), now.minute(), now.second() // data stamp
                              , TempAverage [0]
                              , TempAverage [1]
                              , TempAverage [2]
                              , TempAverage [3]
                              , TempAverage [4]
                              , TempAverage [5]
                              , TempAverage [6]
                              , TempAverage [7]
                              );
  //Append the data to file

  appendFile(SD, logFileName, dataBuffer);

// SEND TO BLYNK
  SendDataToBlynk();
  }
}

void SendDataToBlynk(){
  debugln("\n  ->  Start Sending Data to Blynk "); //Serial.println
  uint64_t TimeStamp = ((uint64_t)now.unixtime()+10800)*1000;  //Time Stamp (milliseconds + 3hours)
  
  Blynk.beginGroup(TimeStamp);  
  Blynk.virtualWrite(V1, (double)(TempAverage[0]));
  Blynk.virtualWrite(V2, (double)(TempAverage[1]));
  Blynk.virtualWrite(V3, (double)(TempAverage[2]));
  Blynk.virtualWrite(V4, (double)(TempAverage[3]));
  Blynk.virtualWrite(V5, (double)(TempAverage[4]));
  Blynk.endGroup();

  debugln("  -| End Sending Data to Blynk \n");
}

void xPrintTemperatures(void *pvParameters) {
  (void) pvParameters;    
  EventBits_t myEventBits;
  char buf1[] = "DD/MM/YYYY - hh:mm:ss"; //TimeStamp
    for(;;) {
      myEventBits = xEventGroupWaitBits(egTheEvents_h, PrintTemperatures_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
      FreeSerial = uxTaskGetStackHighWaterMark(LogData_h);

      // print each measurment
      Serial.print("\e[1;33m");
      Serial.printf("%02i - ", SampleN + 1);
      Serial.print("\e[0;37m");
      for(uint8_t i = 0; i < sensorsNumber; i++){
        Serial.printf("%5.2f  ", sTemp[i]); 
      }
     
      //print the average of 60 measurements
      if (hasAverage){
        Serial.println("\e[1;91m");
        Serial.print("Avg  ");
        Serial.print("\e[0;31m");
        for(uint8_t i = 0; i < sensorsNumber; i++){
          Serial.print(TempAverage[i], 2); Serial.print(" ");
        }
        Serial.print(" (\u00B0C) ");
        Serial.print("\e[1;33m");
        Serial.println (now.timestamp());
        Serial.print("\e[0;37m");
        Serial.println("");
      }
    }
}

You’re using Blynk.begin() but then using a variety of strategies and commands that aren’t really compatible with that approach.

Blynk.begin() creates the WiFi connection and attempts to establish and maintain a Blynk connection.

It’s not clear from your code snippets exactly what you’re doing, but if you want to do the WiFi and Blynk connection tests in the way you are attempting then you should stop using Blynk.begin() and instead do the following…

1 manually establish a WiFi connection, using a proper looping routine until you have a connection established.

  1. use Blynk.config(Auth) and Blynk.connect(optional timeout in ms). The default timeout is around 18 seconds if you don’t specify one.

  2. do a Blynk.connected() test in your loop and only execute Blynk.run() if Blynk.connected() is true

  3. use a timed function to firstly check if WiFi is connected, and if it is check if Blynk is connected. Ensure that your Blynk.connect() timeout and connection checking timer are compatible with each other.

Pete.

Thanks Pete,

I will try it.

Changes in code:

  • Blynk connection after WiFi connection (10 sec timeout).
  • Blink.run() back to loop() {};
  • Heartbeat back to 45s
  • new Blynk_CheckConnection() fuction called by Blynktimer every 30seconds.

Connected like before and sending data to Blink server. I will live it overnight to test any interruptions.
I return here tomorrow.


void setup() {

  Serial.begin(115200);
  delay(2000);

    //Blynk.begin(BLYNK_AUTH_TOKEN, client_ssid, client_password);
  WiFi_ConnectAsClient();
  if (WiFi.status() == WL_CONNECTED) {
    Blynk.config(BLYNK_AUTH_TOKEN);
    Blynk.connect();
    while (!Blynk.connected()); // wait for Blynk connection.
    if (!Blynk.connected()){
      debugln ("\n Blynk NOT connected");
    } 
    else {
      debugln("\n Blynk Connected!");
    }
...
// check Blynk connection every 30 seconds. (> WiFi + Blynk timeouts)
// 
connection_timer_ID = timer.setInterval(30000L, Blynk_CheckConnection); // 30 seconds 
....
}
void loop() {  //spooling Blynk, timer and buttons.
  if (Blynk.connected()) {
      Blynk.run();
  }
  timer.run();
  Button1.tick();
  Button2.tick();
}

void Blynk_CheckConnection() { // 10 seconds wifi-Timeout + 18 seconds Blink timeout = 28 seconds. 

  if (WiFi.status() != WL_CONNECTED) { 
    debugln(" No WiFi.");
    WiFi_Disconnect();
    WiFi_ConnectAsClient(); //Chama o pai de Santo de novo.
  } 
  else {
    debugln(" WiFi is OK");
  }

  if (WiFi.status() == WL_CONNECTED){ // sem o Pai de Santo não tem trabalho hoje
    if (!Blynk.connected()){
      debugln (" Blynk is NOT connected");

      Blynk.disconnect(); // mata a pau pra garantir!
      Blynk.config(BLYNK_AUTH_TOKEN); 
      Blynk.connect(); //agora ressucita o sujeito. Saravá!

      while (!Blynk.connected()); // 18 segundos pra espirito volar! Sacode o corpo! Humm! Humm! Humm!
       
      if (!Blynk.connected()){
      debugln ("\n Blynk could NOT be reconnected"); // tá mortinho da Silva. Tem matar frango preto!
      } 
      else {
        debugln("\n Blynk was reconnected!"); // Aleluia Senhor! Deus é Pai!
      }
    }
    else {
      debugln("\n Blynk is still connected!");
    }
  }
}

void WiFi_Disconnect ()
{
  WiFi.disconnect(true); 
  debugln(" WiFi disconnected!\n");
}

void WiFi_ConnectAsClient ()
{
  WiFi.mode  (WIFI_STA);
  WiFi.config (INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
  WiFi.begin (client_ssid, client_password);

  debug (" Connecting to WiFi...  ");
  unsigned long TimeStart = millis ();
  while (WiFi.status() != WL_CONNECTED)
  {
    if (millis () - TimeStart >= WiFi_TimeOut) {
      debugln ("Time Out! WiFi NOT connected!\n");
      WiFi_Disconnect ();
      return;
    } 
  }
  debugln("connected!");
  debugln("+------------------------------+");
  debug("\e[0;33m");
  debug ("  MAC:  "); debugln (WiFi.macAddress());
  debug ("  IP:   "); debugln (WiFi.localIP());
  debug ("  GTW:  "); debugln (WiFi.gatewayIP());
  debug ("  DNS:  "); debugln (WiFi.dnsIP());
  debug ("  RRSI: "); debugln (WiFi.RSSI());
  debug("\e[0;37m");
  debugln("+------------------------------+");
}

Serial.prints

 Connecting to WiFi...  connected!
+------------------------------+
  MAC:  80:65:99:DF:B1:E8
  IP:   10.10.10.56
  GTW:  10.10.10.1
  DNS:  198.54.100.14
  RRSI: -64
+------------------------------+
[3357] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v1.3.2 on ESP32-S3

 #StandWithUkraine    https://bit.ly/swua


[3358] Connecting to blynk.cloud:80
[3656] <[1D|00|01|00|20]******
[3860] >[00|00|01|00|C8]
[3860] Ready (ping: 202ms).
[3860] Free RAM: 280592
[3861] Waiting:49
[3911] <[11|00|02|00]}mcu[00]0.0.0[00]fw-type[00]*****[00]build[00]May[20|20]8[20]2024[20]18:57:19[00]blynk[00]1.3.2[00]h-beat[00]45[00]buff-in[00]1024[00]dev[00]ESP32-S3[00]tmpl[00]TMPL20ZbxYhJ7

 Blynk Connected!
[6150] >[00|00|02|00|C8]
01 - 28.69  28.81  28.94  29.50  29.06  29.06  29.00  29.19
....
....
60 - 28.75  28.88  29.00  29.50  29.12  29.06  29.00  29.12
Avg  28.75 28.87 28.97 29.50 29.09 29.06 29.00 29.13  (°C) 2024-05-08T18:59:45

  -> Start Sending Data to Blynk
[125860] <[15|00|0C|00|0F]t[00]1715205585000
[125862] <[14|00|0D|00|0F]vw[00]1[00]28.7500000
[125863] Waiting:50
[125914] <[14|00|0E|00|0F]vw[00]2[00]28.8708324
[125915] Waiting:50
[125966] <[14|00|0F|00|0F]vw[00]3[00]28.9656258
[125967] Waiting:50
[126018] <[14|00|10|00|0F]vw[00]4[00]29.5000000
[126019] Waiting:50
[126070] <[14|00|11|00|0F]vw[00]5[00]29.0895824
[126071] <[15|00|12|00|01]e
  -| End Sending Data to Blynk 

 WiFi is OK

 Blynk is still connected!
01 - 28.75  28.88  29.00  29.50  29.06  29.06  29.00  29.12
02 - 28.75  28.88  29.00  29.50  29.06  29.06  29.00  29.12
03 - 28.75  28.81  29.00  29.50  29.06  29.06  29.00  29.12
04 - 28.75  28.88  29.00  29.50  29.12  29.06  29.00  29.12
05 - 28.75  28.88  29.00  29.50  29.12  29.06  29.00  29.12  

Really?

Some of your while loops look a bit strange to me.

Pete.

Hi Pete,

May be…

while (!Blynk.connect()){...}

The timeout for WiFi connection is set to 10 seconds. Usually it connects immediately.
Blynk default is 18 seconds summing 28 seconds of maximal time. So, check connection every 30 seconds is ok.

Besides my dirty code, things got much better here. I have continuous data now. A variable to count disconnections. There was only two in more than 12 hrs with successful reconnections.

Let’s move it on!
Thank you for the support!