Persistent Disconnection Issues with Blynk Server on DOIT ESP32 DEVKIT V1

Hello everyone, I’m working on an automated greenhouse project using a DOIT ESP32 DEVKIT V1 connected to the Blynk server. My setup involves reporting sensor data and actuator statuses, with the system set to automatically adjust environmental conditions based on sensor input. However, I’m encountering recurring disconnections from the Blynk server, which compromise the system’s reliability.

Here are the details:

  • Hardware: DOIT ESP32 DEVKIT V1 + ESP32 DEVKIT development board
  • Communication type: WiFi, via university’s IoT network
  • Datastreams: 10 total (5 for sensor data, 5 for actuator status)
  • Power for ESP32: Type-C cable with USB adapter plugged into a power socket

Problem:
The system initially operates as expected, transmitting data to the Blynk server without issues for a few hours. Disconnection periods vary, lasting from 30 seconds to 17 minutes. However, after roughly 6-7 hours, it fails to reconnect, resulting in complete operational failure. I’ve attempted to maintain a clean void loop() and adjusted timer intervals to 2000L and 5000L for data transmission. Notably, reducing the datastreams to 5 (sensor data only) allowed for longer operation times (over 10 hours) but did not eliminate disconnection issues.

Attempts to Resolve:

  • Ensured void loop() remains clean
  • Adjusted data-sending intervals (2000L and 5000L)
  • Tested with reduced number of datastreams

Could anyone provide insights or suggestions on how to maintain a stable connection to the Blynk server? Any advice or similar experiences shared would be immensely appreciated. Thank you in advance for your help!

#define BLYNK_TEMPLATE_ID "TMPL5QnD7wJfZ"
#define BLYNK_TEMPLATE_NAME "IoT Smart Agriculture System"
#define BLYNK_AUTH_TOKEN "xxx"

// WiFi credentials
char ssid[] = "XXXXX-IoT"; // WiFi Name
char pass[] = "Oio602npoEKo"; // WiFi Password
char auth[] = "xxxxx";

#include <Ticker.h>
#include <WiFi.h>
#include <DallasTemperature.h>
#include <BlynkSimpleEsp32.h>
#include <Wire.h> 
#include <BH1750.h>
#include <DHT.h>                      //For air moisture and temperature sensor
#include <OneWire.h>                  //For Soil moisture sensor

// GPIO pins for ESP32 
#define DHTPIN 15                  // For DHT11
#define DHTTYPE DHT11              // DHT 11 Air temperature and moisture sensor
#define SOUND_SPEED 0.034          // SR04 Ultrasonic sensor
#define CM_TO_INCH 0.393701        // SR04 Ultrasonic sensor
#define MOIST_PIN 34
#define ONE_WIRE_BUS 4
#define WATER_PUMP_PIN 25
#define HEAT_MAT_PIN 26
#define LED_PIN 27 

// Virtual pins for blynk 
#define VPIN_AIR_HUMIDITY V0
#define VPIN_AIR_TEMPERATURE V1
#define VPIN_SOIL_MOISTURE V2
#define VPIN_SOIL_TEMPERATURE V3
#define VPIN_WATER_TANK_LEVEL V4
#define VPIN_LIGHT_SENSOR V5
#define VPIN_CONNECTION V6
#define VPIN_WATER_PUMP_STATUS V7
#define VPIN_HEAT_MAT_STATUS V8
#define VPIN_LED_GROW_LIGHT_STATUS V9


unsigned long lastWaterPumpActivation = 0;
const unsigned long waterPumpCooldown = 1800000; // 30 minutes in milliseconds

//For SR04 Ultrasonic sensor
const int trigPin = 5; 
const int echoPin = 18;
long duration;
float distanceCm;
float distanceInch;

DHT dht(DHTPIN, DHTTYPE);
BlynkTimer timer;
BH1750 lightMeter;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress sensor1 = { 0x28, 0x38, 0x7D, 0x81, 0xE3, 0xE1, 0x3C, 0xA };
DeviceAddress sensor2 = { 0x28, 0x57, 0xFC, 0x81, 0xE3, 0xE1, 0x3C, 0xEB };

float measureDistance(){
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  // Calculate the distance
  distanceCm = duration * SOUND_SPEED/2;
  return distanceCm;
}

float measureSoilTemp(){
  sensors.requestTemperatures();
  float tempC1 = sensors.getTempC(sensor1);
  float tempC2 = sensors.getTempC(sensor2);
  float avgTempC = (tempC1 + tempC2) / 2;
  return avgTempC;
}

float measureMoist(){
  int moist = analogRead(MOIST_PIN);
  // Invert the calculation logic: (4000 - moist) represents the inverse reading
  float moistPercent = ((float)(4000 - moist) / (4000 - 2000)) * 100;
  moistPercent = constrain(moistPercent, 0, 100); // Ensure the percentage is between 0 and 100 

  Serial.print("Soil Moisture Reading: ");
  Serial.print(moist);
  Serial.print(" - Moisture %: ");
  Serial.println(moistPercent);
  return moistPercent;
  //return moist;
}

float measureWaterTankLevel() {
  float distance = measureDistance(); // Use the existing measureDistance function to get the current distance.
  float fullTankDistance = 2.5; // Distance when the tank is full.
  float emptyTankDistance = 17.0; // Distance when the tank is empty.
  // Calculate the percentage full. This will invert the measurement since a smaller distance means more water.
  float tankLevelPercent = (1.0 - ((distance - fullTankDistance) / (emptyTankDistance - fullTankDistance))) * 100;

  // Ensure the percentage is between 0 and 100
  tankLevelPercent = constrain(tankLevelPercent, 0, 100);
  Serial.print("Water Tank Level Reading: ");
  Serial.print(distance);
  Serial.print(" cm - Level %: ");
  Serial.println(tankLevelPercent);
  return tankLevelPercent;
}

void sendSensorData() {
  float h = dht.readHumidity(); //Measure air moisture value in %
  float t = dht.readTemperature(); //Measure temperature valur in degrees Celsius
  float lux = lightMeter.readLightLevel();
  float waterTankLevel = measureWaterTankLevel();
  float moistPercent = measureMoist();
  float temp = measureSoilTemp();

  Blynk.virtualWrite(VPIN_AIR_TEMPERATURE, t);
  Blynk.virtualWrite(VPIN_AIR_HUMIDITY, h);
  Blynk.virtualWrite(VPIN_SOIL_MOISTURE, moistPercent);
  Blynk.virtualWrite(VPIN_WATER_TANK_LEVEL, waterTankLevel);
  Blynk.virtualWrite(VPIN_LIGHT_SENSOR, lux);
  Blynk.virtualWrite(VPIN_SOIL_TEMPERATURE, temp);
  Blynk.virtualWrite(VPIN_CONNECTION, Blynk.connected() ? 1 : 0);
}


void controlActuators() {
  unsigned long currentMillis = millis();
  float waterTankLevel = measureWaterTankLevel();
  float soilMoisturePercent = measureMoist();
  float soilTemperature = measureSoilTemp();
  float lightLevel = lightMeter.readLightLevel();

  if (waterTankLevel < 10 && soilMoisturePercent < 40 && millis() - lastWaterPumpActivation > waterPumpCooldown) {
    digitalWrite(WATER_PUMP_PIN, LOW); // Turn on the pump
    Blynk.virtualWrite(VPIN_WATER_PUMP_STATUS, 1);
    Serial.println("Pump activated.");
    delay(2000); // Keep the pump on for 2 seconds
    digitalWrite(WATER_PUMP_PIN, HIGH); // Turn off the pump
    Serial.println("Pump deactivated.");
    Blynk.virtualWrite(VPIN_WATER_PUMP_STATUS, 0);
    lastWaterPumpActivation = millis(); // Update the last activation time
  }
  // Heat mat logic
  if (soilTemperature < 18) {
    digitalWrite(HEAT_MAT_PIN, LOW);
    Blynk.virtualWrite(VPIN_HEAT_MAT_STATUS, 1);
  } else if (soilTemperature > 16) {
    digitalWrite(HEAT_MAT_PIN, HIGH);
    Blynk.virtualWrite(VPIN_HEAT_MAT_STATUS, 0);
  }

  // LED grow light logic
  if (lightLevel < 150) {
    digitalWrite(LED_PIN, LOW);
    Blynk.virtualWrite(VPIN_LED_GROW_LIGHT_STATUS, 1);
  } else if (lightLevel > 100) {
    digitalWrite(LED_PIN, HIGH);
    Blynk.virtualWrite(VPIN_LED_GROW_LIGHT_STATUS, 0);
  }
}

void setup() {
  Serial.begin(115200);
  dht.begin();
  Wire.begin();
  lightMeter.begin();
  sensors.begin();
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin, INPUT); // Sets the echoPin as an Input

  // Set up the actuator pin
  pinMode(WATER_PUMP_PIN, OUTPUT);
  pinMode(HEAT_MAT_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);

  // Ensure actuators are off initially
  digitalWrite(WATER_PUMP_PIN, HIGH);
  digitalWrite(HEAT_MAT_PIN, HIGH);
  digitalWrite(LED_PIN, HIGH);


  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, pass);
  Blynk.config(auth);

  Serial.println("WiFi connected");  
  Blynk.begin(BLYNK_AUTH_TOKEN , ssid, pass);
  timer.setInterval(2000L, sendSensorData);
  timer.setInterval(5000L, controlActuators);
}

void loop() {
  Blynk.run();
  timer.run();

}

Here is a screenshot from the Blynk app that logs my device’s timeline for yesterday night. Thank you so much.

It’s a bit weird that you are managing your WiFi connection yourself (although the code for this seems incomplete, and using Blynk.config(), but then using Blynk.begin().
What’s the thinking behind this?

Pete.

Thanks for your quick response, Pete.

To be honest, I am really new to IoT, and I wrote this code by referencing to others’ work, so it may not be correct. If that can be the reason for my problem, then can you tell me thr correct way to connect to WiFi? Thanks!

Are you looking for the device to perform some f7nctiins (such as running the pump) even if WiFi or the internet is down?

Pete.

No, my main concern is how to let my system stay connected to the server to report data for a long time like a week.

Do you know what might cause the connection problem shown in the screenshot? Is that because I have too many data sending at the same time? Or it is because of the delay function.

Thanks!

Start by removing g these two lines of code…

I’d also remove this too, as it makes no sense…

You should add this line near the top of your sketch…

#define BLYNK_PRINT Serial

and connect a laptop to your board and see what the serial m9nitor tells you when a disconnection occurs.

It might also be worth having a chat with your IT department to see if they have any firewall rules set-up that might be contributing to this.

Pete.

Thanks! I will try it.