[SOLVED] ESP32 with sensors stops working after X hours

Hi everyone,

So I have this basic setup as I wrote in the title.

I have this connecting via WiFi to my network and communicating via MQTT with my OpenHab2 installation where I have a lot more devices.

All works well with no conflicts, but something on my code here is not correct because after a couple of days, exactly at midnight it stops communicating and I have to restart the device. This makes no sense.

Can someone please help me here looking at my code?

#include <WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"
#define DHTPIN 13
#define DHTTYPE DHT11

int period = 200000; //Corre a cada 2 minutos
unsigned long time_now = 0;
int sensor_pin = A0;
int s;
char mensagem[100];
   
char* ssid = "BLA";
const char* password =  "BLA";
const char* mqttServer = "1.2.3.4";
const int mqttPort = 1883;
const char* mqttUser = "DVES_USER";
const char* mqttPassword = "****";
WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHTPIN, DHTTYPE);
    
void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Iniciando conexao com a rede WiFi...");
  }
  Serial.println("Conectado na rede WiFi!");

  dht.begin();
}
  
void loop() {
  if(millis() - time_now > period){
    time_now = millis();
    
    float h = dht.readHumidity();
    float t = dht.readTemperature();
    s = analogRead(sensor_pin);
        
    //Faz a conexao com o broker MQTT
    reconectabroker();
    sprintf(mensagem, "{\"Temperatura\":\"%d\",\"Humidade\":\"%d\",\"Solo\":\"%d\"}", (int)t, (int)h, (int)s);
    Serial.println(mensagem);
        
    //Envia a mensagem ao broker
    client.publish("Sensor_Temp_Hum_Solo", mensagem);
  }
}

void reconectabroker() {
  //Conexao ao broker MQTT
  client.setServer(mqttServer, mqttPort);
  while (!client.connected()) {
    Serial.println("Conectando ao broker MQTT...");
    if (client.connect("ESP32Client", mqttUser, mqttPassword )) {
      Serial.println("Conectado ao broker!");
    } else {
      Serial.print("Falha na conexao ao broker - Estado: ");
      Serial.print(client.state());
      delay(2000);
    }
  }
}

Thanks a lot in advance!

SOLUTION:

After a lot of trial and error, the problem that originated this topic was my old router from my previous ISP... >:(

Well, anyway, thanks to the kind help of people in this forum and also a lot of search that I've made, here's my perfectly working code going now more than 2 weeks always on and communicating without interuptions:

//Program: ESP32 Wifi module with sensors communicating via MQTT
//Author: Pedro Lima (MAIDOT)

#include <WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"
#define DHTPIN 13
#define DHTTYPE DHT11

unsigned long period = 120000; //Runs each 2 minutes
unsigned long time_now = 0;
int sensor_soil_pin = A0;
int soil;
int soil_a;
const int sensor_rain_pin = 15;
int rain;
int rain_a;
char msg[100];
char* ssid = "HIDDEN";
const char* password =  "HIDDEN";
const char* mqttServer = "192.168.1.100";
const int mqttPort = 1883;
const char* mqttUser = "DVES_USER";
const char* mqttPassword = "****";

IPAddress local_IP(192, 168, 2, 201);
IPAddress gateway(192, 168, 2, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);
IPAddress secondaryDNS(8, 8, 4, 4);
WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHTPIN, DHTTYPE);
    
void setup() {
  Serial.begin(115200);

  WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
  WiFi.setAutoReconnect(true);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Starting WiFi connection to the network...");
  }
  Serial.println("Connected to WiFi network!");
  if(WiFi.getSleep() == true) {
    WiFi.setSleep(false);
    Serial.println("WiFi Sleep is now deactivated.");
  }

  dht.begin();
}
  
void loop() {
  if ( WiFi.status() ==  WL_CONNECTED ){ //Connected to WiFi
    if(millis() - time_now > period){ //Using ESP timer "esp_timer_get_time()" did not went well
      time_now = millis();
      //Serial.print("ESP time right now: ");
      //Serial.println(time_now);
      
      float h = dht.readHumidity();
      float t = dht.readTemperature();
      soil_a = analogRead(sensor_soil_pin);
      rain_a = analogRead(sensor_rain_pin);
      soil = map(soil_a, 0, 4095, 100, 0);
      rain = map(rain_a, 0, 4095, 100, 0);
      
      //Establishes a connection to MQTT broker
      reconectabroker();
      sprintf(msg, "{\"Temperature\":\"%d\",\"Humidity\":\"%d\",\"Soil\":\"%d\",\"Rain\":\"%d\"}", (int)t, (int)h, (int)soil, (int)rain);
      Serial.println(msg);
          
      //Send message to MQTT broker
      client.publish("Sensors_THSR_Exterior", msg);
      Serial.println("Message successfully sent to MQTT broker...");
    }
  }else{ //WiFi not connected, try to reconnect
    WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
    WiFi.begin();
    int UpCount = 0;
    int WLcount = 0;
    Serial.println("Trying to reconnect to WiFi network...");
    while (WiFi.status() != WL_CONNECTED && WLcount < 200 ){
      delay( 100 );
      Serial.printf(".");
      if (UpCount >= 60){
        UpCount = 0;
        Serial.printf("\n");
      }
      ++UpCount;
      ++WLcount;
    }
    if(WiFi.status() != WL_CONNECTED){
      Serial.println("Impossible reconnecting to WiFi, rebooting device!");
      ESP.restart();
    }
  }
}

void reconectabroker() {
  //Connection to MQTT broker
  client.setServer(mqttServer, mqttPort);
  while (!client.connected()) {
    Serial.println("Connecting to MQTT broker...");
    if (client.connect("ESP32Client", mqttUser, mqttPassword )) {
      Serial.println("Connected to MQTT broker!");
    } else {
      Serial.print("Fail while connecting to MQTT broker - Status: ");
      Serial.print(client.state());
      delay(2000);
    }
  }
}

This

int period = 200000; //Corre a cada 2 minutos

will not fit into an 'int'
All variables used with millis() should be of type unsigned long.

Not sure if that is your problem with the 'stops working' but definitely not delaying like you think

If you are going thru a router, check its settings. Some times they renew leases on IP address that might cause an issue.

There is no RTC so there is nothing to tie you to midnight. You should look elsewhere. Perhaps it is a router as zoomkat said.

Also, don't forget the mills() timer rolls over after about 50 days.

blh64:
This

int period = 200000; //Corre a cada 2 minutos

will not fit into an 'int'
All variables used with millis() should be of type unsigned long.

Not sure if that is your problem with the 'stops working' but definitely not delaying like you think

Well, it actually runs each 2 minutes, so it means that it's correctly reading that variable. Anyway, I've changed as per your suggestion.

Thanks!

zoomkat:
If you are going thru a router, check its settings. Some times they renew leases on IP address that might cause an issue.

ToddL1962:
There is no RTC so there is nothing to tie you to midnight. You should look elsewhere. Perhaps it is a router as zoomkat said.

Also, don't forget the mills() timer rolls over after about 50 days.

Thank you both!

My router is a Xiaomi Mi Wifi and it has a Lease time of 720 minutes (12 hours) so it makes no sense since this goes on working for +/- 2 days, but it always stops at midnight.

Anyhow, I changed my code to this now as per your suggestions guys. It's connected and communicating so let's hope the fixed IP solved the issue. :slight_smile:

#include <WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"
#define DHTPIN 13
#define DHTTYPE DHT11

unsigned long period = 200000; //Corre a cada 2 minutos
unsigned long time_now = 0;
int sensor_pin = A0;
int s;
char mensagem[100];
char* ssid = "BLA";
const char* password =  "BLA";
const char* mqttServer = "192.168.2.190";
const int mqttPort = 1883;
const char* mqttUser = "DVES_USER";
const char* mqttPassword = "****";

IPAddress local_IP(192, 168, 2, 201);
IPAddress gateway(192, 168, 2, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);
IPAddress secondaryDNS(8, 8, 4, 4);
WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHTPIN, DHTTYPE);
    
void setup() {
  Serial.begin(115200);

  WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
  
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("A iniciar conexão com à rede WiFi...");
  }
  Serial.println("Conectado à rede WiFi!");

  dht.begin();
}

The code missing here is the same as in my first post.

Ok so less than 24h and last communication was, again, yesterday at midnight.

I noticed that device is not connected to WiFi so I wonder. How can I "loop something" to reconnect to WiFi each time it disconnects?

blh64:
All variables used with millis() should be of type unsigned long.

In some cases using an unsigned long (uint32_t) for timing is a wast of memory. For button debouncing and timing periods < ~65.5 seconds an unsigned int (uint16_t) will suffice :slight_smile:

Ok, after a little search, I've found out that more people have this problem and I've implemented a solution to reconnect whenever WiFi desconnects and if the reconnection is not sucessfull after a while, it simply reboots the ESP device.

So here's my new full code which is now working but I don't know yet for how long:

#include <WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"
#define DHTPIN 13
#define DHTTYPE DHT11

unsigned long period = 200000; //Corre a cada 2 minutos
unsigned long time_now = 0;
int sensor_pin = A0;
int s;
char mensagem[100];
char* ssid = "BLA";
const char* password =  "BLA";
const char* mqttServer = "192.168.2.190";
const int mqttPort = 1883;
const char* mqttUser = "DVES_USER";
const char* mqttPassword = "****";

IPAddress local_IP(192, 168, 2, 201);
IPAddress gateway(192, 168, 2, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);
IPAddress secondaryDNS(8, 8, 4, 4);
WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHTPIN, DHTTYPE);
    
void setup() {
  Serial.begin(115200);
  
  //Verifica a presença de shield - vou ignorar propositadamente, erro provavelmente seria da energia
  /*if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield não presente!");
    while(true);
  }*/

  WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
  
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("A iniciar conexão com à rede WiFi...");
  }
  Serial.println("Conectado à rede WiFi!");

  dht.begin();
}
  
void loop() {
  if ( WiFi.status() ==  WL_CONNECTED ){ //Conectado ao WiFi
    if(millis() - time_now > period){
      time_now = millis();
      
      float h = dht.readHumidity();
      float t = dht.readTemperature();
      s = analogRead(sensor_pin);
          
      //Faz a conexão com o broker MQTT
      reconectabroker();
      sprintf(mensagem, "{\"Temperatura\":\"%d\",\"Humidade\":\"%d\",\"Solo\":\"%d\"}", (int)t, (int)h, (int)s);
      Serial.println(mensagem);
          
      //Envia a mensagem ao broker
      client.publish("Sensor_Temp_Hum_Solo", mensagem);
      //Serial.println("Mensagem enviada com sucesso...");
    }
  }else{//Desconectado do WiFi, volta a tentar
    WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
    WiFi.begin();
    int UpCount = 0;
    int WLcount = 0;
    Serial.println("A tentar reconectar à rede WiFi...");
    while (WiFi.status() != WL_CONNECTED && WLcount < 200 ){
      delay( 100 );
      Serial.printf(".");
      if (UpCount >= 60){
        UpCount = 0;
        Serial.printf("\n");
      }
      ++UpCount;
      ++WLcount;
    }
    if(WiFi.status() != WL_CONNECTED){
      Serial.println("Impossível reconectar à rede WiFi, a reiniciar dispositivo!");
      ESP.restart();
    }
  }
}

void reconectabroker() {
  //Conexao ao broker MQTT
  client.setServer(mqttServer, mqttPort);
  while (!client.connected()) {
    Serial.println("Conectando ao broker MQTT...");
    if (client.connect("ESP32Client", mqttUser, mqttPassword )) {
      Serial.println("Conectado ao broker!");
    } else {
      Serial.print("Falha na conexao ao broker - Estado: ");
      Serial.print(client.state());
      delay(2000);
    }
  }
}

Will update this post and mark it as solved if within the next couple of days it stays ON. :slight_smile:

This block of code may cause the WiFi connection to time out and disconnect - especially if the 2 seconds delay in it is invoked:

while (!client.connected()) {
...
}

You should try to avoid to wait for the client to connect and not use delay at all.

Danois90:
This block of code may cause the WiFi connection to time out and disconnect - especially if the 2 seconds delay in it is invoked:

I suppose you are refering to this line of code but correct me if I'm wrong:

while (WiFi.status() != WL_CONNECTED && WLcount < 200 ){

If so, then you may haven't noticed that it's inside the "else" that will fall into only in case it loses connection to WiFi.

So far after more than 5 hours straight, it's working without any problems.

Let's see how long it handles.

I will keep this updated until I reach a conclusion to help future visitors.

Update: Weird thing here!

Yesterday it stoped again. Not at midnight this time, it was around 00:40.

Now, today when I unpluged the device and pluged it into my PC, so that I can track on serial monitor what happens until it stops working, it actually didn't started. Meaning, it didn't connected to WiFi.

This has never happened in the past since when I unpluged and pluged back again, it always connected.

I had to press the reset button on the ESP32 (labeled EN) and then it started working properly.

Right now is working correctly but I will keep serial monitor open until it stops working again to try and see where/when it stops.

In "setup()" before "WiFi.begin()" try to add "WiFi.setSleepMode(WIFI_NONE_SLEEP)" and see if it changes anything.

Danois90:
In "setup()" before "WiFi.begin()" try to add "WiFi.setSleepMode(WIFI_NONE_SLEEP)" and see if it changes anything.

Thank you for your input, but when I verify code it gives me this error: 'class WiFiClass' has no member named 'setSleepMode'

With an ESP32 one can use esp_timer_get_time(); instead of millis(). esp_timer_get_time(); returns micriseconds and will roll over in a bir more then 127 years.:

void fDo_AudioReadFreq( void *pvParameters )
{
  int64_t EndTime = esp_timer_get_time();
  int64_t StartTime = esp_timer_get_time(); //gets time in uSeconds like Arduino Micros
  for (;;)
  {
    xEventGroupWaitBits (eg, evtDo_AudioReadFreq, pdTRUE, pdTRUE, portMAX_DELAY);
    EndTime = esp_timer_get_time() - StartTime;
    // log_i( "TimeSpentOnTasks: %d", EndTime );
    Audio.ReadFreq(FreqVal);
    for (int i = 0; i < 7; i++)
    {
      FreqVal[i] = constrain( FreqVal[i], NOISE, A_D_ConversionBits );
      FreqVal[i] = map( FreqVal[i], NOISE, A_D_ConversionBits, 0, 255 );
      // log_i( "Freq %d Value: %d", i, FreqVal[i]);//used for debugging and Freq choosing
    }
    xQueueSend( xQ_LED_Info, ( void * ) &FreqVal, xTicksToWait0 );
    StartTime = esp_timer_get_time();
  }
  vTaskDelete( NULL );
} // fDo_ AudioReadFreq( void *pvParameters )
////

Well regarding the timer that's a good advice, although my problem it's not connected with it (at least that's what I suspect) but I've implemented your suggestion.

Now, regarding "WiFi.setSleepMode(WIFI_NONE_SLEEP)" I tried to implement but I get this error message:

WiFi_to_MQTT:41:21: error: 'WIFI_NONE_SLEEP' was not declared in this scope

Multiple libraries were found for «WiFi.h»
User: C:\Users\user\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\WiFi
Not user: C:\Program Files (x86)\Arduino\libraries\WiFi
exit status 1
'class WiFiClass' has no member named 'setSleepMode'

Well, it actually runs each 2 minutes, so it means that it's correctly reading that variable. Anyway, I've changed as per your suggestion.

int period = 200000; //Corre a cada 2 minutos

Well, 200,000 would not be 2 minutes anyway... 2 minutes is 2601000 = 120000.

You would actually end up with 200000 % (2^16) = 3392 in that variable - 3.392 seconds.
If it still takes 2 minutes, it is because there is some other delay somewhere.

What did you change it to? Is it still an int type?

Seems like "WiFi.setSleepMode()" is not avaiable on ESP32. After your WiFi has been established, try to check if "WiFi.getSleep()" is true. If it is then try to disable it with "WiFi.setSleep(false)". You could also try to enable automatic reconnect with "WiFi.setAutoReconnect(true)".

@aarg you are right, this was just me not thinking that a minute has 60 seconds. :'D

@Danois90 thanks a ton for your kind help. I think that thanks to you, I got it working! :smiley: Now let's hope it handles well.

So far so good! Let's see for how long it handles.

Here goes the entire code as it is right now. I have there connected a DHT11 (temperature and humidity sensor), soil humidity sensor and rain sensor.

It communicates via MQTT to my OpenHab server, then I store it in MySQL and work that in pretty graphs, also automating irrigation, blinds, etc. :slight_smile:

//Programa: Modulo ESP32 Wifi com MQTT e sensores (temperatura, humidade, solo e chuva)
//Autor: Pedro Lima

#include <WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"
#define DHTPIN 13
#define DHTTYPE DHT11

unsigned long period = 120000000; //Corre a cada 2 minutos
unsigned long time_now = 0;
int sensor_solo_pin = A0;
int solo;
const int sensor_chuva_pin = 15;
int chuva;
char mensagem[100];
char* ssid = "BLA";
const char* password =  "BLA";
const char* mqttServer = "192.168.2.190";
const int mqttPort = 1883;
const char* mqttUser = "DVES_USER";
const char* mqttPassword = "****";

IPAddress local_IP(192, 168, 2, 201);
IPAddress gateway(192, 168, 2, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);
IPAddress secondaryDNS(8, 8, 4, 4);
WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHTPIN, DHTTYPE);
    
void setup() {
  Serial.begin(115200);
  
  //Verifica a presença de shield - vou ignorar propositadamente, erro provavelmente seria da energia
  /*if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield não presente!");
    while(true);
  }*/

  WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
  WiFi.setAutoReconnect(true);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("A iniciar conexão com à rede WiFi...");
  }
  Serial.println("Conectado à rede WiFi!");
  if(WiFi.getSleep() == true) {
    WiFi.setSleep(false);
  }

  dht.begin();
}
  
void loop() {
  if ( WiFi.status() ==  WL_CONNECTED ){ //Conectado ao WiFi
    if(esp_timer_get_time() - time_now > period){ //Usado tempo do hardware ESP ao invés de millis()
      time_now = esp_timer_get_time();
      
      float h = dht.readHumidity();
      float t = dht.readTemperature();
      solo = analogRead(sensor_solo_pin);
      chuva = analogRead(sensor_chuva_pin);
          
      //Faz a conexão com o broker MQTT
      reconectabroker();
      sprintf(mensagem, "{\"Temperatura\":\"%d\",\"Humidade\":\"%d\",\"Solo\":\"%d\",\"Chuva\":\"%d\"}", (int)t, (int)h, (int)solo, (int)chuva);
      Serial.println(mensagem);
          
      //Envia a mensagem ao broker
      client.publish("Sensor_Temp_Hum_Solo", mensagem);
      //Serial.println("Mensagem enviada com sucesso...");
    }
  }else{//Desconectado do WiFi, volta a tentar
    WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
    WiFi.begin();
    int UpCount = 0;
    int WLcount = 0;
    Serial.println("A tentar reconectar à rede WiFi...");
    while (WiFi.status() != WL_CONNECTED && WLcount < 200 ){
      delay( 100 );
      Serial.printf(".");
      if (UpCount >= 60){
        UpCount = 0;
        Serial.printf("\n");
      }
      ++UpCount;
      ++WLcount;
    }
    if(WiFi.status() != WL_CONNECTED){
      Serial.println("Impossível reconectar à rede WiFi, a reiniciar dispositivo!");
      ESP.restart();
    }
  }
}

void reconectabroker() {
  //Conexao ao broker MQTT
  client.setServer(mqttServer, mqttPort);
  while (!client.connected()) {
    Serial.println("Conectando ao broker MQTT...");
    if (client.connect("ESP32Client", mqttUser, mqttPassword )) {
      Serial.println("Conectado ao broker!");
    } else {
      Serial.print("Falha na conexão ao broker - Estado: ");
      Serial.print(client.state());
      delay(2000);
    }
  }
}

Well... I guess I'm out of luck! Still, after some hours, it disconnected from WiFi, AGAIN! :frowning:

What can be wrong here after all?

What does your debug output say when you lose connection?

Also, is there something else happening on your network (periodic backup?) that causes contention?

Do you have wireless phones that interfere with your wifi?

Has the ESP32 actually crashed or is it trying to reconnect but never can?