Device disconnects from cloud after 4 but before 5 minutes

I have an ESP32 (Chip is ESP32-D0WDQ6 (revision 1), Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None, Crystal is 40MHz) connecting to Blynk cloud over WiFi. Here is my sketch.

// Template ID, Device Name and Auth Token are provided by the Blynk.Cloud
// See the Device Info tab, or Template settings
#define BLYNK_TEMPLATE_ID "REMOVED"
#define BLYNK_DEVICE_NAME "REMOVED"
#define BLYNK_AUTH_TOKEN "REMOVED"

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

#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <DHTesp.h>

char auth[] = BLYNK_AUTH_TOKEN;
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "REMOVED";
char pass[] = "REMOVED";

BlynkTimer readAndSendTimer;

ComfortState externalDHT11ComfortState;
ComfortState externalDHT22ComfortState;
ComfortState internalTopDHT11ComfortState;
ComfortState internalTopDHT22ComfortState;
ComfortState internalMiddleDHT11ComfortState;
ComfortState internalMiddleDHT22ComfortState;
ComfortState internalBottomDHT11ComfortState;
ComfortState internalBottomDHT22ComfortState;

/** Initialize DHTs */
DHTesp externalDHT11;
DHTesp externalDHT22;
DHTesp internalTopDHT11;
DHTesp internalTopDHT22;
DHTesp internalMiddleDHT11;
DHTesp internalMiddleDHT22;
DHTesp internalBottomDHT11;
DHTesp internalBottomDHT22;

/** Define signal connection pins */
int externalDHT11SignalPin = 12;
int externalDHT22SignalPin = 13;
int internalTopDHT11SignalPin = 15;
int internalTopDHT22SignalPin = 2;
int internalMiddleDHT11SignalPin = 4;
int internalMiddleDHT22SignalPin = 16;
int internalBottomDHT11SignalPin = 17;
int internalBottomDHT22SignalPin = 5;
int heaterRelaySignalPin = 14;
int humidifierRelaySignalPin = 27;
int topFanRelaySignalPin = 26;
int waterLevelSignalPin = 25;

// Read and VirtualWrite all values to Blynk Virtual Pins
void readAndSendSensorData() {

  //Serial.println("Attempting sensing from external DHT11.");
  float externalDHT11Humidity = externalDHT11.getHumidity();
  Blynk.virtualWrite(V0, externalDHT11Humidity);
  Blynk.run();
  float externalDHT11Temperature = externalDHT11.getTemperature();
  Blynk.virtualWrite(V1, externalDHT11Temperature);
  Blynk.run();
  //Serial.println("External DHT11: Data sent to Blynk:");
  //Serial.println("Humidity (%)\tTemperature");
  //Serial.print(externalDHT11Humidity, 1);
  //Serial.print("\t\t");
  //Serial.print(externalDHT11Temperature, 1);
  //Serial.println("");

  //Serial.println("Attempting sensing from external DHT22.");
  float externalDHT22Humidity = externalDHT22.getHumidity();
  Blynk.virtualWrite(V2, externalDHT22Humidity);
  Blynk.run();
  float externalDHT22Temperature = externalDHT22.getTemperature();
  Blynk.virtualWrite(V3, externalDHT22Temperature);
  Blynk.run();
  float externalDHT22DewPoint = externalDHT22.computeDewPoint(externalDHT22Humidity, externalDHT22Temperature, false);
  Blynk.virtualWrite(V4, externalDHT22DewPoint);
  Blynk.run();
  float externalDHT22AbsoluteHumidity = externalDHT22.computeAbsoluteHumidity(externalDHT22Temperature, externalDHT22Humidity, false);
  Blynk.virtualWrite(V5, externalDHT22AbsoluteHumidity * 1000); // Blynk has milligrams/cubic meter as a listed unit
  Blynk.run();
  int externalDHT22HumanPerception = externalDHT22.computePerception(externalDHT22Temperature, externalDHT22Humidity, false);
  String externalDHT22HumanPerceptionText = getHumanPerceptionText(externalDHT22HumanPerception);
  Blynk.virtualWrite(V6, externalDHT22HumanPerceptionText);
  Blynk.run();
  float externalDHT22ComfortRatio = externalDHT22.getComfortRatio(externalDHT22ComfortState, externalDHT22Temperature, externalDHT22Humidity, false);
  String externalDHT22ComfortStatusText = getComfortStatusText(externalDHT22ComfortState);
  Blynk.virtualWrite(V7, externalDHT22ComfortStatusText);
  Blynk.run();
  //Serial.println("External DHT22: Data sent to Blynk:");
  //Serial.println("Humidity (%)\tTemperature (C)\tDew Point (C)\tAbsolute Humidity (g/cu. m)\tHuman Perception Status\t\tComfort Status");
  //Serial.print(externalDHT22Humidity, 1);
  //Serial.print("\t\t");
  //Serial.print(externalDHT22Temperature, 1);
  //Serial.print("\t\t");
  //Serial.print(externalDHT22DewPoint, 1);
  //Serial.print("\t\t");
  //Serial.print(externalDHT22AbsoluteHumidity, 1);
  //Serial.print("\t\t\t\t" + externalDHT22HumanPerceptionText);
  //Serial.println("\t\t\t" + externalDHT22ComfortStatusText);
  //Serial.println("");

  //Serial.println("Attempting sensing from internal top DHT11.");
  float internalTopDHT11Humidity = internalTopDHT11.getHumidity();
  Blynk.virtualWrite(V8, internalTopDHT11Humidity);
  Blynk.run();
  float internalTopDHT11Temperature = internalTopDHT11.getTemperature();
  Blynk.virtualWrite(V9, internalTopDHT11Temperature);
  Blynk.run();
  //Serial.println("Internal top DHT11: Data sent to Blynk:");
  //Serial.println("Humidity (%)\tTemperature (C)");
  //Serial.print(internalTopDHT11Humidity, 1);
  //Serial.print("\t\t");
  //Serial.print(internalTopDHT11Temperature, 1);
  //Serial.println("");

  //Serial.println("Attempting sensing from internal top DHT22.");
  float internalTopDHT22Humidity = internalTopDHT22.getHumidity();
  Blynk.virtualWrite(V10, internalTopDHT22Humidity);
  Blynk.run();
  float internalTopDHT22Temperature = internalTopDHT22.getTemperature();
  Blynk.virtualWrite(V11, internalTopDHT22Temperature);
  Blynk.run();
  float internalTopDHT22DewPoint = internalTopDHT22.computeDewPoint(internalTopDHT22Humidity, internalTopDHT22Temperature, false);
  Blynk.virtualWrite(V12, internalTopDHT22DewPoint);
  Blynk.run();
  float internalTopDHT22AbsoluteHumidity = internalTopDHT22.computeAbsoluteHumidity(internalTopDHT22Temperature, internalTopDHT22Humidity, false);
  Blynk.virtualWrite(V13, internalTopDHT22AbsoluteHumidity * 1000); // Blynk has milligrams/cubic meter as a listed unit
  Blynk.run();
  int internalTopDHT22HumanPerception = internalTopDHT22.computePerception(internalTopDHT22Temperature, internalTopDHT22Humidity, false);
  String internalTopDHT22HumanPerceptionText = getHumanPerceptionText(internalTopDHT22HumanPerception);
  Blynk.virtualWrite(V14, internalTopDHT22HumanPerceptionText);
  Blynk.run();
  float internalTopDHT22ComfortRatio = internalTopDHT22.getComfortRatio(internalTopDHT22ComfortState, internalTopDHT22Temperature, internalTopDHT22Humidity, false);
  String internalTopDHT22ComfortStatusText = getComfortStatusText(internalTopDHT22ComfortState);
  Blynk.virtualWrite(V15, internalTopDHT22ComfortStatusText);
  Blynk.run();
  //Serial.println("Internal top DHT22: Data sent to Blynk:");
  //Serial.println("Humidity (%)\tTemperature (C)\tDew Point (C)\tAbsolute Humidity (g./cu. m)\tHuman Perception Status\t\tComfort Status");
  //Serial.print(internalTopDHT22Humidity, 1);
  //Serial.print("\t\t");
  //Serial.print(internalTopDHT22Temperature, 1);
  //Serial.print("\t\t");
  //Serial.print(internalTopDHT22DewPoint, 1);
  //Serial.print("\t\t");
  //Serial.print(internalTopDHT22AbsoluteHumidity, 1);
  //Serial.print("\t\t\t\t" + internalTopDHT22HumanPerceptionText);
  //Serial.println("\t\t\t" + internalTopDHT22ComfortStatusText);
  //Serial.println("");

  //Serial.println("Attempting sensing from internal middle DHT11.");
  float internalMiddleDHT11Humidity = internalMiddleDHT11.getHumidity();
  Blynk.virtualWrite(V16, internalMiddleDHT11Humidity);
  Blynk.run();
  float internalMiddleDHT11Temperature = internalMiddleDHT11.getTemperature();
  Blynk.virtualWrite(V17, internalMiddleDHT11Temperature);
  Blynk.run();
  //Serial.println("Internal middle DHT11: Data sent to Blynk:");
  //Serial.println("Humidity (%)\tTemperature (C)");
  //Serial.print(internalMiddleDHT11Humidity, 1);
  //Serial.print("\t\t");
  //Serial.print(internalMiddleDHT11Temperature, 1);
  //Serial.println("");

  //Serial.println("Attempting sensing from internal middle DHT22.");
  float internalMiddleDHT22Humidity = internalMiddleDHT22.getHumidity();
  Blynk.virtualWrite(V18, internalMiddleDHT22Humidity);
  Blynk.run();
  float internalMiddleDHT22Temperature = internalMiddleDHT22.getTemperature();
  Blynk.virtualWrite(V19, internalMiddleDHT22Temperature);
  Blynk.run();
  //Serial.println("Internal middle DHT22: Data sent to Blynk:");
  //Serial.println("Humidity (%)\tTemperature (C)");
  //Serial.print(internalMiddleDHT22Humidity, 1);
  //Serial.print("\t\t");
  //Serial.print(internalMiddleDHT22Temperature, 1);
  //Serial.println("");

  //Serial.println("Attempting sensing from internal bottom DHT11.");
  float internalBottomDHT11Humidity = internalBottomDHT11.getHumidity();
  Blynk.virtualWrite(V20, internalBottomDHT11Humidity);
  Blynk.run();
  float internalBottomDHT11Temperature = internalBottomDHT11.getTemperature();
  Blynk.virtualWrite(V21, internalBottomDHT11Temperature);
  Blynk.run();
  //Serial.println("Internal bottom DHT11: Data sent to Blynk:");
  //Serial.println("Humidity (%)\tTemperature (C)");
  //Serial.print(internalBottomDHT11Humidity, 1);
  //Serial.print("\t\t");
  //Serial.print(internalBottomDHT11Temperature, 1);
  //Serial.println("");

  //Serial.println("Attempting sensing from internal bottom DHT22.");
  float internalBottomDHT22Humidity = internalBottomDHT22.getHumidity();
  Blynk.virtualWrite(V22, internalBottomDHT22Humidity);
  Blynk.run();
  float internalBottomDHT22Temperature = internalBottomDHT22.getTemperature();
  Blynk.virtualWrite(V23, internalBottomDHT22Temperature);
  Blynk.run();
  //Serial.println("Internal bottom DHT22: Data sent to Blynk:");
  //Serial.println("Humidity (%)\tTemperature (C)");
  //Serial.print(internalBottomDHT22Humidity, 1);
  //Serial.print("\t\t");
  //Serial.print(internalBottomDHT22Temperature, 1);
  //Serial.println("");

  // Read the analog value from the water level sensor in the humidifier container
  int waterLevel = analogRead(waterLevelSignalPin);
  Blynk.virtualWrite(V24, waterLevel);
  Blynk.run();
  //Serial.print("Water level in the humidifier container is:");
  //Serial.print(waterLevel, 1);
  //Serial.println("");

  /**
    Control heater based on internal top DHT22. This relay is wired Normally 
    Open (Normally open pin starts sending current on HIGH, and vice versa)
  */
  if (internalTopDHT22Temperature < 28) {
    digitalWrite(heaterRelaySignalPin, HIGH);
    Blynk.virtualWrite(V25, HIGH);
    Blynk.run();
  } else {
    digitalWrite(heaterRelaySignalPin, LOW);
    Blynk.virtualWrite(V25, LOW);
    Blynk.run();
  }

  /** 
    Control humidifier based on internal top DHT22. This relay is wired Normally 
    Open (Normally open pin starts sending current on HIGH, and vice versa)
  */
  if (internalTopDHT22Humidity < 70) {
    digitalWrite(humidifierRelaySignalPin, HIGH);
    Blynk.virtualWrite(V26, HIGH);
    Blynk.run();
  } else {
    digitalWrite(humidifierRelaySignalPin, LOW);
    Blynk.virtualWrite(V26, LOW);
    Blynk.run();
  }

  /**
    Control top fan based on internal top DHT22. This relay is wired Normally 
    Open (Normally open pin starts sending current on HIGH, and vice versa)
  */
  if (internalTopDHT22Humidity > 70 || internalTopDHT22Temperature > 28) {
    digitalWrite(topFanRelaySignalPin, HIGH);
    Blynk.virtualWrite(V27, HIGH);
    Blynk.run();
  } else {
    digitalWrite(topFanRelaySignalPin, LOW);
    Blynk.virtualWrite(V27, LOW);
    Blynk.run();
  }

  /**
    Read and send the WiFi's Received Signal Strength Indicator (RSSI) of the WiFi connection - an integer
  */
  int wifiSignalStrength = WiFi.RSSI();
  //Serial.print("WiFi signal strength (RSSI): ");
  //Serial.println(wifiSignalStrength);
  Blynk.virtualWrite(V28, wifiSignalStrength);
}

void setup() {

  // Debug console
  //Serial.begin(115200);
  //Serial.println("Setup started.");

  WiFi.mode(WIFI_STA);
  //Serial.println("WiFi capability set to STATION mode.");

  Blynk.begin(auth, ssid, pass);
  //Serial.println("Authorised to send data to Blynk.");

  // Set up pin modes
  pinMode(externalDHT11SignalPin, INPUT);
  pinMode(externalDHT22SignalPin, INPUT);
  pinMode(internalTopDHT11SignalPin, INPUT);
  pinMode(internalTopDHT22SignalPin, INPUT);
  pinMode(internalMiddleDHT11SignalPin, INPUT);
  pinMode(internalMiddleDHT22SignalPin, INPUT);
  pinMode(internalBottomDHT11SignalPin, INPUT);
  pinMode(internalBottomDHT22SignalPin, INPUT);
  pinMode(heaterRelaySignalPin, OUTPUT);
  pinMode(humidifierRelaySignalPin, OUTPUT);
  pinMode(topFanRelaySignalPin, OUTPUT);
  pinMode(waterLevelSignalPin, INPUT);

  // Set up DHTs
  externalDHT11.setup(externalDHT11SignalPin, DHTesp::DHT11);
  externalDHT22.setup(externalDHT22SignalPin, DHTesp::DHT22);
  internalTopDHT11.setup(internalTopDHT11SignalPin, DHTesp::DHT11);
  internalTopDHT22.setup(internalTopDHT22SignalPin, DHTesp::DHT22);
  internalMiddleDHT11.setup(internalMiddleDHT11SignalPin, DHTesp::DHT11);
  internalMiddleDHT22.setup(internalMiddleDHT22SignalPin, DHTesp::DHT22);
  internalBottomDHT11.setup(internalBottomDHT11SignalPin, DHTesp::DHT11);
  internalBottomDHT22.setup(internalBottomDHT22SignalPin, DHTesp::DHT22);
  //Serial.println("All DHT11 & DHT22 set up.");

  // Setup 10 seconds interval for the readAndSensorData function
  readAndSendTimer.setInterval(30000L, readAndSendSensorData);
}

void loop() {
  Blynk.run();
  readAndSendTimer.run();
}

/**
  Comfort Status Text
  0 -> OK
  1 -> Too Hot
  2 -> Too cold
  4 -> Too dry
  5 -> Hot and dry
  6 -> Cold and dry
  8 -> Too humid
  9 -> Hot and humid
  10 -> Cold and humid
**/
String getComfortStatusText(int reportedComfortState) {

  String comfortStatusText;

  switch (reportedComfortState) {

    case Comfort_OK:
      comfortStatusText = "OK";
      break;
    case Comfort_TooHot:
      comfortStatusText = "Too Hot";
      break;
    case Comfort_TooCold:
      comfortStatusText = "Too Cold";
      break;
    case Comfort_TooDry:
      comfortStatusText = "Too Dry";
      break;
    case Comfort_TooHumid:
      comfortStatusText = "Too Humid";
      break;
    case Comfort_HotAndHumid:
      comfortStatusText = "Hot and Humid";
      break;
    case Comfort_HotAndDry:
      comfortStatusText = "Hot and Dry";
      break;
    case Comfort_ColdAndHumid:
      comfortStatusText = "Cold and Humid";
      break;
    case Comfort_ColdAndDry:
      comfortStatusText = "Cold and Dry";
      break;
    default:
      comfortStatusText = "Unknown";
      break;
  };

  return comfortStatusText;
}

/**
  Human Perception Text
  0 -> Dry
  1 -> Very comfortable
  2 -> Comfortable
  3 -> Ok
  4 -> Uncomfortable
  5 -> Quite uncomfortable
  6 -> Very uncomfortable
  7 -> Severe uncomfortable
**/
String getHumanPerceptionText(int reportedHumanPerceptionValue) {

  String humanPerceptionText;

  switch (reportedHumanPerceptionValue) {

    case 0:
      humanPerceptionText = "Dry";
      break;
    case 1:
      humanPerceptionText = "Very comfy";
      break;
    case 2:
      humanPerceptionText = "Comfy";
      break;
    case 3:
      humanPerceptionText = "OK";
      break;
    case 4:
      humanPerceptionText = "Uncomfy";
      break;
    case 5:
      humanPerceptionText = "Quite uncomfy";
      break;
    case 6:
      humanPerceptionText = "Very uncomfy";
      break;
    case 7:
      humanPerceptionText = "Severely uncomfy";
      break;
  };

  return humanPerceptionText;
}

I was about to add multiple setTimeouts, putting each virtual write in a separate Timeout, when I saw this thread, and instead used multiple Blynk.run() in accordance to this thread.

Despite everything that I do, the Blynk web dashboard shows the device online, as soon as it boots, and starts sending data to Blynk, but, right around 4 minutes and 30 seconds the device goes offline. Can someone help please? @PeteKnight

UPDATE: After multiple edits and commenting all the Serial prints, the code is above. This is connected for the last 20 minutes now, so looks like the problem has been resolved, but this makes me concerned, since Blynk has a Virtual Write limit of 10 per second. Shall that not be an issue?

Can you point me to the part of that BlynkTimer tutorial that led you to believe that what you’ve done in your sketch is correct?
That way I can re-word the tutorial to ensure that other people don’t misinterpret it again.

Pete.

1 Like

Hi,

Thanks for the response. I’m really sorry that I wanted to quote some other thread.

Can you please let me know the problems that you see?

As previously updated, this code works fine now, and remains connected, so the problem that I opened this thread for has been resolved. Yet it’ll be a great help if you let me know the flaws that you see with the code. As said previously, I wanted to use multiple setTimeouts, but, as recommended by you in response to a similar question, you recommended that one can add some Blynk.run commands in a large virtual write block to give some air to Blynk. Please let me know if I misunderstood something.

Thanks,

Your current sketch performs 29 Blynk virtual writes each time readAndSendSensorData is executed.
It’s difficult to gauge how long this function takes to execute, but I’d guess that it’s somewhere in the region of 1 second. Adding serial print statements would help you to measure this accurately.

You shouldn’t be sending data to the Blynk servers more than toen times per second.

It would be far better split the process of reading the sensors and writing the results to Blynk into more sensible blocks of code, each in its own function and called fia separate interval timers that are staggered.

I’d also change the name of your BlynkTimer object from readAndSendTimer to just timer.
The timer object can be used for upto 16 timer instances, and these are defined by the functions that are called by each instance.

You’ve misunderstood why you would need to add Blynk.run() into functions that are being called, and your function (which will become multiple functions) doesn’t need them.

To split your readAndSendTimer up effectively, you’ll need to be making variables like externalDHT11Humidity global rather than local, and I’d suggest that you go through a process of reading the sensors in batches, then using these readings to calculate the appropriate actions that need to be taken.

I’d also be careful about the pins that you are using for your sensors, as some of the pins you’ve chosen can prevent the board from booting if they are pulled HIGH or LOW at boot time.
I’d also be careful about the lengths of the wires to your sensors, and TBH, I wouldn’t be using the DHT range of sensors at all.

Pete.