ESP32 keeps disconnecting from wifi after sometime ✅

I'm currently working on a project involving the ESP32, creating an automatic plant watering system using Adafruit and the Arduino IDE. The issue I'm encountering is that the ESP32 intermittently disconnects from the router approximately every 20-30 minutes. This disconnection causes the project to pause until I manually reset the ESP32 by pressing the reset button.

Any advice or solutions to ensure the ESP32 maintains a stable connection to the router and continues to send moisture readings to Adafruit without manual intervention would be greatly appreciated.

Here is the code I am using(I will take out the wifi details):

#include <WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

// WiFi parameters
#define WLAN_SSID       "HiddenDetails"
#define WLAN_PASS       "HiddenDetails"

// Adafruit IO
#define AIO_SERVER      "io.adafruit.com"
#define AIO_SERVERPORT  1883
#define AIO_USERNAME    "ElectroMasterOP"
#define AIO_KEY         "aio_OuuD72fe69CKuZ7gvDMObSdTyf65"

WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
Adafruit_MQTT_Publish OutPut_Value = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/OutPut_Value2");

byte moisture;

const int relay = 5;

int sensor_pin = 32;
int output_value;
int led = 18;

void setup() {

  Serial.begin(115200);
  Serial.println(F("Adafruit IO Example"));

  pinMode(led, OUTPUT);
  pinMode(relay, OUTPUT);
  digitalWrite(relay, LOW);
  // Connect to WiFi access point.
  Serial.println(); Serial.println();
  delay(10);
  Serial.print(F("Connecting to "));
  Serial.println(WLAN_SSID);
  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(F("."));
  }
  Serial.println();
  Serial.println(F("WiFi connected"));
  Serial.println(F("IP address: "));
  Serial.println(WiFi.localIP());
  Serial.println("Website: https://io.adafruit.com/ElectroMasterOP/dashboards");
  Serial.print("UserName:");
  Serial.println("HiddenDetails");
  Serial.print("Password:");
  Serial.println(" HiddenDetails");

  // Connect to Adafruit IO
  connect();
}

// Connect to Adafruit IO via MQTT
void connect() {
  Serial.print(F("Connecting to Adafruit IO... "));
  int8_t ret;
  while ((ret = mqtt.connect()) != 0) {
    switch (ret) {
      case 1: Serial.println(F("Wrong protocol")); break;
      case 2: Serial.println(F("ID rejected")); break;
      case 3: Serial.println(F("Server unavail")); break;
      case 4: Serial.println(F("Bad user/pass")); break;
      case 5: Serial.println(F("Not authed")); break;
      case 6: Serial.println(F("Failed to subscribe")); break;
      default: Serial.println(F("Connection failed")); break;
    }

    if (ret >= 0)
      mqtt.disconnect();

    Serial.println(F("Retrying connection..."));
    delay(10000);
  }
  Serial.println(F("Adafruit IO Connected!"));
}

void loop() {

  digitalWrite(relay, LOW);
  output_value = analogRead(sensor_pin);
  output_value = map(output_value, 550, 0, 0, 100);
  
  Serial.print("Moisture : ");
  Serial.print(output_value);
  Serial.println("%");
  delay(50);

  while (output_value <= -100) {
    digitalWrite(led, HIGH);
    output_value = analogRead(sensor_pin);
    output_value = map(output_value, 550, 0, 0, 100);
    Serial.print(output_value);
    digitalWrite(relay, HIGH);
    Serial.println("Current Flowing");
    
    delay(750);
    digitalWrite(relay, LOW);
    Serial.println("Pouring stopped");
    printMoisture(); 
    break;
  }
  printMoisture();
  digitalWrite(led, LOW);
  digitalWrite(relay, LOW);
  Serial.println("Current not Flowing");


  delay(1500);
  digitalWrite(relay, LOW);
  Serial.println("Off Under PrintMoisture");
  //  ESP.restart();

}

float printMoisture() {
  if (!mqtt.ping(3)) {
    // Reconnect to Adafruit IO
    if (!mqtt.connected())
      connect();
  }
  Serial.print("Output Value: ");
  Serial.println(output_value);
  moisture = output_value + 700;

  if (!OutPut_Value.publish(output_value + 700)) {
    Serial.println(F("Failed"));
  }
  else {
    Serial.println(F("Sent!"));
  }
  
  delay(2000);
  digitalWrite(relay, LOW);


}

Disconnects will happen and should be coded for..
I would move the Wifi and mqtt connect out of setup and into the loop..
A system state machine should be added that would not only keep track of the above but can also handle the watering..
Your loop logic right now is confusing, looks like you only want to water for 750ms when sensor say too as you break quickly out of the loop..

But yes, disconnects can happen and if all your connection code resides in setup you must reset in order to reconnect..

Look how I was crafting this loop here..

good luck.. ~q

This tutorial shows how to use wifi events on an ESP32 to do a reconnect

Putting: WiFi.setSleep(false);
in setup after you have connected to the wifi is worth a try

Thank you. Your assistance was extremely helpful and resolved many issues.

2 Likes

I got another issue. During one of my tests, the wifi disconnected. I am getting this error from the serial monitor:

.[322305][D][WiFiGeneric.cpp:1035] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[322305][W][WiFiGeneric.cpp:1057] _eventCallback(): Reason: 202 - AUTH_FAIL
.[322812][D][WiFiGeneric.cpp:1035] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[322812][W][WiFiGeneric.cpp:1057] _eventCallback(): Reason: 202 - AUTH_FAIL
.[323319][D][WiFiGeneric.cpp:1035] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[323319][W][WiFiGeneric.cpp:1057] _eventCallback(): Reason: 202 - AUTH_FAIL
.[323826][D][WiFiGeneric.cpp:1035] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[323826][W][WiFiGeneric.cpp:1057] _eventCallback(): Reason: 202 - AUTH_FAIL
.[324333][D][WiFiGeneric.cpp:1035] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[324333][W][WiFiGeneric.cpp:1057] _eventCallback(): Reason: 202 - AUTH_FAIL
.[324840][D][WiFiGeneric.cpp:1035] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[324840][W][WiFiGeneric.cpp:1057] _eventCallback(): Reason: 202 - AUTH_FAIL
.[325347][D][WiFiGeneric.cpp:1035] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[325347][W][WiFiGeneric.cpp:1057] _eventCallback(): Reason: 202 - AUTH_FAIL
.[325854][D][WiFiGeneric.cpp:1035] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[325854][W][WiFiGeneric.cpp:1057] _eventCallback(): Reason: 202 - AUTH_FAIL
.[326361][D][WiFiGeneric.cpp:1035] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[326361][W][WiFiGeneric.cpp:1057] _eventCallback(): Reason: 202 - AUTH_FAIL
.[326868][D][WiFiGeneric.cpp:1035] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[326868][W][WiFiGeneric.cpp:1057] _eventCallback(): Reason: 202 - AUTH_FAIL

Here is my code:

#include <WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

// WiFi parameters
#define WLAN_SSID       "Sensitive info " 
#define WLAN_PASS       "Sensitive info" 

// Adafruit IO
#define AIO_SERVER      "io.adafruit.com" 
#define AIO_SERVERPORT  1883
#define AIO_USERNAME    "ElectroMasterOP"
#define AIO_KEY         "aio_OuuD72fe69CKuZ7gvDMObSdTyf65"

WiFiClient client;
//Connects to output_value2 feed
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
Adafruit_MQTT_Publish OutPut_Value = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/OutPut_Value2");

byte moisture;

//Creates variables for watering function.
const int relay = 5;
const int sensor_pin = 32;
const int led = 18;
int output_value;

//Creates statefunction and its cases.
enum State {
  INIT,
  CONNECT_WIFI,
  CONNECT_MQTT,
  READ_SENSOR,
  WATER_PLANT,
  PUBLISH_DATA
};

//Starts the statefunction up.
State currentState = INIT;

void setup() {
  Serial.begin(115200); //Connects to serial monitor
  Serial.println(F("Adafruit IO Example"));

  pinMode(led, OUTPUT);
  pinMode(relay, OUTPUT);
  digitalWrite(relay, LOW);
}

void loop() {
  switch (currentState) {
    case INIT:
      Serial.println(F("Initializing...")); //Initialization
      currentState = CONNECT_WIFI; //Next step start-off
      break;//Goes to next step

    case CONNECT_WIFI:
      //Connects to wifi using the parameters
      Serial.print(F("Connecting to WiFi: "));
      Serial.println(WLAN_SSID);
      WiFi.begin(WLAN_SSID, WLAN_PASS);
      //Checks for issues then reconnects if so.
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(F("."));
        WiFi.begin(WLAN_SSID, WLAN_PASS);
      }
      Serial.println();

      //Prints local IP/allows user to know its ready to go on.
      Serial.println(F("WiFi connected"));
      Serial.print(F("IP address: "));
      Serial.println(WiFi.localIP());
      currentState = CONNECT_MQTT;//Next step start-off
      break;//Allowing to go to next step

    case CONNECT_MQTT:
      Serial.print(F("Connecting to Adafruit IO... "));
      //Connects to adafruit using AIO_KEY put in at the top.
      if (mqtt.connect() == 0) {
        Serial.println(F("Adafruit IO Connected!"));
        currentState = READ_SENSOR;//Next step start-off
      } else {
        //Retrying because there were errors
        Serial.println(F("Connection failed, retrying..."));
        delay(10000);
      }
      break;//Allowing to go to next step

    case READ_SENSOR:
      digitalWrite(relay, LOW);//Turns relay/pump off
      output_value = analogRead(sensor_pin);
      output_value = map(output_value, 550, 0, 0, 100);//Checks moisture
      Serial.print("Moisture : ");//Printing value
      Serial.print(output_value);
      Serial.println("%");
      delay(50);

      if (output_value <= -100) {
        currentState = WATER_PLANT;//Next step start-off(forking off No.1)
      } else {
        currentState = PUBLISH_DATA;//Next step start-off(forking off No.2)
      }
      break;//Allowing to go to next step

      
    case WATER_PLANT:
      //No.1
      digitalWrite(led, HIGH);
      digitalWrite(relay, HIGH);//Pump on/Water pouring
      Serial.println("Current Flowing");
      delay(1250);//Water pours for 1250ms
      digitalWrite(relay, LOW);//Pump off.
      Serial.println("Pouring stopped");
      digitalWrite(led, LOW);
      currentState = PUBLISH_DATA;//Next step start-off(No.2)
      break;//Allowing to go to next step

    case PUBLISH_DATA:
      //No.2
      //Connect to adafruit.
      if (!mqtt.ping(3)) {
        // Reconnect to Adafruit IO
        if (!mqtt.connected()) {
          currentState = CONNECT_MQTT;
          break;
        }
      }
      //Print on serial monitor and puts output_value+700 in the output_value2 feed to be plotted into a graph
      Serial.print("Output Value: ");
      Serial.println(output_value);
      moisture = output_value + 700;
      if (!OutPut_Value.publish(output_value + 700)) {
        //Fails data send/retrys
        Serial.println(F("Failed to send data"));
      } else {
        Serial.println(F("Data sent!"));
        Serial.println("--------------------------");
      }
      delay(2000);
      
      currentState = READ_SENSOR;//Loops again from reading sensor
      break;//Allowing to go to start of loop.
  }
}

probably right there..
you do another WiFi begin every 500 milliseconds..
thinking the WiFi begin should be removed??

good luck.. ~q

Thank you, that did help a lot.

1 Like