MQTT with ESP32 gives Timeout Disconnecting

Hello,
I am having a hard time with my ESP32 board the last few days.
I have built a custom soil moisture sensor with an ESP32 board that reads the soil moisture and post it through MQTT to HA. Then sleeps for 1 hour.

The whole project runs on a 18650 / 3000mAH battery using a battery shield V3 which has a 5V output.

As the esp32 has only one VCC I am using a GPIO pin to switch off the sensor too.
The soil moisture sensor was staying ON when esp was in deep sleep.
Something which was not really very good for power consumption and energy saving.

My sketch looks correct, at least to my eyes, but after a few hours of operating I am getting an error which I haven’t be able to solve.

1609060258: New client connected from 192.168.70.161 as plant-esp32 (p2, c1, k60, u'local-user').
1609060348: Client plant-esp32 has exceeded timeout, disconnecting.

I have read lots of forums and tried different versions of my sketch.
I tried different version of PubSubClient library.
I tried to set the MQTT_KEEPALIVE to 60

Unfortunately with no success.
After a couple of sensor readings, ESP fails to publish to HA (has exceed timeout, disconnecting), although it connects to broker.

My sketch looks like this:

#include <WiFi.h>

#define MQTT_KEEPALIVE 60
#include "PubSubClient.h" // Allows us to connect to, and publish to the MQTT broker

#define SensorPin A0

/* definitions for deepsleep */
#define uS_TO_S_FACTOR 1000000        /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 3600            /* Time ESP32 will go to sleep for 2 minutes (in seconds) */

int minsensor = 1200; //drowned in water
int maxsensor = 2800; //dry soil

// WiFi
const char* ssid = "XXXX";
const char* wifi_password = "XXXXX";

// MQTT
// Make sure to update this for your own MQTT Broker!
const char* mqtt_server = "XXXXX";
const char* plant_topic = "plant/moisture";
const char* mqtt_username = "local-user";
const char* mqtt_password = "12345";
const char* clientID = "plant-esp32";

// Initialise the WiFi and MQTT Client objects
WiFiClient wifiClient;
PubSubClient client(mqtt_server, 1883, wifiClient); // 1883 is the listener port for the Broker


void connect_MQTT() {

  Serial.print("Connecting to ");
  Serial.println(ssid);

  // Connect to the WiFi
  WiFi.begin(ssid, wifi_password);

  // Wait until the connection has been confirmed before continuing
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  // Debugging - Output the IP Address of the ESP
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  pinMode(13, OUTPUT);    // sets the digital pin 13 as output
  digitalWrite(13, HIGH); // sets the digital pin 13 on
  delay(1000);  //delay for a second
  Serial.println("PIN 13 is ON");
  
  // original values
  float sensorValue = analogRead(SensorPin);
  Serial.println("Sensor Value is: " + String(sensorValue) );

  //map to percentage
  float percentage = map(sensorValue, maxsensor, minsensor, 0, 100);
  Serial.println("Percentage % is: " + String(percentage) );
  
  // PUBLISH to the MQTT Broker
  client.connect(clientID, mqtt_username, mqtt_password);
  if (client.publish(plant_topic, String(percentage).c_str())) {
    Serial.println("Moisture sent!");
    //Serial.println(plant_topic);
  }

  // If the message failed to send, we will try again, as the connection may have broken.
  else

  {
    Serial.println("Moisture failed to send. Reconnecting to MQTT Broker and trying again");
    client.connect(clientID, mqtt_username, mqtt_password);
    delay(100); // This delay ensures that client.publish doesn't clash with the client.connect call
    client.publish(plant_topic, String(percentage).c_str());
    Serial.println("Moisture sent on recconect!");
  }

  digitalWrite(13, LOW);  // sets the digital pin 13 off
  Serial.println("PIN 13 is OFF");
  
  Serial.setTimeout(2000);
  Serial.println("Preparing ESP32 to sleep for " + String(TIME_TO_SLEEP) + " Seconds");
  Serial.println("Sleeping...");
  ESP.deepSleep(TIME_TO_SLEEP * uS_TO_S_FACTOR);


}


void setup() {

  Serial.begin(115200);
  connect_MQTT();

}

void loop() {

  if (WiFi.status() != WL_CONNECTED) {
    WiFi.begin(ssid, wifi_password);
  }
  
  else 
  {
    client.loop();
  }

}

Any help / advise would be much appreciate and put me back to bed :slight_smile:
thanks in advance
Makis

Try setting your WiFi delay to 1000 or 1500. I had similar problems and when I increased the time for connection it became rock solid with no drops. Since I changed (set mine to 1500), it’s been running for 1.5 years without a hiccup.

thank you for your reply.
Will test it. Meanwhile would you please share your sketch ?

Sure, see below. This is one of 16 esp32’s I have online for sensors and relays around my house and yard.

#include <WiFi.h>
#include <Wire.h>
#include <SPI.h>
#include “PubSubClient.h”
#include <Adafruit_Sensor.h>
#include “Adafruit_BME680.h”

#define CLIENT_ID “s2”

#define BME1_SCK 16
#define BME1_MISO 17
#define BME1_MOSI 18
#define BME1_CS 19

const char* ssid = “xxx”; // Enter SSID here
const char* password = “xxx”; //Enter Password here

IPAddress local_IP(192, 168, 5, 51);
IPAddress gateway(192, 168, 5, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(192, 168, 5, 1);

Adafruit_BME680 bme1(BME1_CS, BME1_MOSI, BME1_MISO, BME1_SCK);

const int numReadings = 6;
int readings[numReadings]; // the readings from the analog input
int readIndex = 0; // the index of the current reading
int total = 0; // the running total
int average = 0; // the average

int lum1 = 34;

int outside_light;

WiFiClient espClient;
PubSubClient mqttClient(espClient);

void setup() {
Serial.begin(115200);
while (!Serial);
Serial.println(F(“S2 Sensors”));
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS)) {
Serial.println(“Static IP Failed to configure”);
}
Serial.println("Connecting to ");
Serial.println(ssid);

while (WiFi.status() != WL_CONNECTED) {
WiFi.disconnect();
WiFi.begin(ssid, password);
delay(1500);

Serial.print(".");
}
Serial.println("");
Serial.println(“WiFi connected…!”);
Serial.print(“Got IP: “); Serial.println(WiFi.localIP());
Serial.println(””);
mqttClient.setClient(espClient);
mqttClient.setServer( “192.168.5.6”, 1883);
Serial.println();
Serial.println(F(“Ready to send data”));
Serial.println();

if (!bme1.begin()) {
Serial.println(“Could not find a valid BME680 sensor, check wiring!”);
while (1);
}

for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;
}

// Set up oversampling and filter initialization
bme1.setTemperatureOversampling(BME680_OS_8X);
bme1.setHumidityOversampling(BME680_OS_2X);
bme1.setPressureOversampling(BME680_OS_4X);

}

void loop() {

// subtract the last reading:
total = total - readings[readIndex];
// read from the sensor:
readings[readIndex] = analogRead(lum1);
// add the reading to the total:
total = total + readings[readIndex];
// advance to the next position in the array:
readIndex = readIndex + 1;

// if we’re at the end of the array…
if (readIndex >= numReadings) {
// …wrap around to the beginning:
readIndex = 0;
}

// calculate the average:
average = total / numReadings;

if (! bme1.performReading()) {
Serial.println(“Failed to perform reading :(”);
return;
}
Serial.print(“Temperature = “);
Serial.print(bme1.temperature * 9/5 + 32);
Serial.println(” °F”);

Serial.print(“Pressure = “);
Serial.print(bme1.pressure / 100.0);
Serial.println(” hPa”);

Serial.print(“Humidity = “);
Serial.print(bme1.humidity);
Serial.println(” %”);

Serial.println("");

Serial.println();
Serial.println();
Serial.println();
Serial.println(average);

Serial.println();

delay(1000);
char msgBuffer[20];
float t1 = bme1.temperature * 9/5 + 32; //outside
float h1 = bme1.readHumidity(); //outside
float p1 = bme1.readPressure() / 100; //outside

outside_light = analogRead(lum1);
if (mqttClient.connect(CLIENT_ID)) {
mqttClient.publish("s2/outside_temperature", dtostrf(t1, 6, 2, msgBuffer));
mqttClient.publish("s2/outside_humidity", dtostrf(h1, 6, 2, msgBuffer));
mqttClient.publish("s2/barametric_pressure", dtostrf(p1, 4, 0, msgBuffer));
mqttClient.publish("s2/outside_light", dtostrf((average / 4), 4, 0, msgBuffer));

}
}

thank you!
However our sketches have major differences.

Most important is that you are not using deep sleep.
Also it seems that your device is always on power and not running on battery like mine.

Anyways, I tried your advice but unfortunately I am having the same behavior on the 2nd run (2nd hour)

1609075239: New client connected from 192.168.70.161 as auto-7826F1EF-1F96-EE7D-DE17-B365786D0422 (p2, c1, k60, u'local-user').
1609075330: Client auto-7826F1EF-1F96-EE7D-DE17-B365786D0422 has exceeded timeout, disconnecting.

It’s hard to believe that no one, on such a huge community, had a problem like mine.
No one really?

None of my esp32’s run on battery. I had too many issues with battery powered devices.

Soon as I went to full powered devices (ESP32’s), and minimized any Zwave Plus devices powered by battery, all of the issues I had went away. I have 4 kwikset zwave plus deadbolts, and 1 motion sensor that are battery powered.

same issue here, did you manage to fix this ?