tzapu / WiFiManager

ESP8266 WiFi Connection manager with web captive portal
http://tzapu.com/esp8266-wifi-connection-manager-library-arduino-ide/
MIT License
6.63k stars 1.98k forks source link

ModemSleep Esp8266 and Wifi Manager #1129

Open floatAsNeeded opened 4 years ago

floatAsNeeded commented 4 years ago

Hi all!

I'm not sure whether is an issue, but I'm using the library together with a modem sleep. Basically the code runs for 4.5 minutes in modem sleep and then it connects to the wifi and transmits some data and then the Wifi would go off again. It is working perfectly, but just sometimes, like for example once in a day (Is running 24/7) is doesn't connect to the wifi and it goes in AP mode waiting to be configured. I just want to ask if I'm using the right method. This is my function where it connects and then goes to modem sleep:

void readData()
{
  temp_c = sht1x.readTemperatureC();
  //temp_f = sht1x.readTemperatureF();
  humiditySHT1x = sht1x.readHumidity();
  printResult("Pooling Mode", sht3xd.readTempAndHumidity(SHT3XD_REPEATABILITY_HIGH, SHT3XD_MODE_POLLING, 50));
  readPioggia();
  readVento();
  if ((millis() - previoustemp >= uploadtime) || (dayschange == 1))
  {
    uploadtime = 260000;
    WiFi.forceSleepWake();
    delay(100);
    // Bring up the WiFi connection
    WiFi.mode(WIFI_STA);
    wifiManager.autoConnect("LineaMeteoStazioneS", "LaMeteo2005");

    //delay(2000);
    previoustemp = millis();

    if (dayschange == 0)
    {
      if (minutes < 40)
      {
        if (Firebase.getInt(Weather, "/ChangeTime/StartingMinute"))
        {
          minutes = Weather.intData();
        }
        if (Firebase.getInt(Weather, "/ChangeTime/StartingHour"))
        {
          hours = Weather.intData();
        }
      }

      alternate++;
      Firebase.setFloat(Weather, "/Temperature/Temperaturenow", temperatureSHT3x);
      Firebase.setInt(Weather, "/Humidity", humiditySHT3x);
      Firebase.setFloat(Weather, "/Temperature/TemperatureMax", MaxTemp);
      Firebase.setFloat(Weather, "/Temperature/TemperatureMin", MinTemp);
      Firebase.setFloat(Weather, "/Wind/WindSpeed", WindSpeed);
      Firebase.setInt(Weather, "/Wind/WindDirection", CalDirection);

      if (alternate > 1)
      {
        alternate = 0;
        Firebase.setFloat(Weather, "/SHT1x/Temperature", temp_c);
        Firebase.setInt(Weather, "/SHT1x/Humidity", humiditySHT1x);
      }
      if (gustDetected == 1)
      {
        gustDetected = 0;
        Firebase.setFloat(Weather, "/Wind/Gust24H", Gust);
      }
      if (mmPioggia > 0)
      {
        Firebase.setFloat(Weather, "/Rain/Rain24H", mmPioggia);
      }
      if (rainrate > 0)
      {
        Firebase.setFloat(Weather, "/Rain/RainRate", rainrate);
        Firebase.setFloat(Weather, "/Rain/RainRateMax", rainrateMax);
      }
    }
    if (dayschange == 1)
    {
      dayschange = 0;
      MaxTemp = temperatureSHT3x;
      MinTemp = temperatureSHT3x;
      mmPioggia = 0;
      Gust = 0;
      rainrateMax = 0;
      Firebase.setFloat(Weather, "/Temperature/TemperatureMax", temperatureSHT3x);
      Firebase.setFloat(Weather, "/Temperature/TemperatureMin", temperatureSHT3x);
      Firebase.setFloat(Weather, "/Wind/Gust24H", 0);
      Firebase.setFloat(Weather, "/Rain/Rain24H", 0);
      Firebase.setFloat(Weather, "/Rain/RainRateMax", 0);
    }

    //wificonnected = true;
    WiFi.mode(WIFI_OFF);
    WiFi.forceSleepBegin();
    delay(100);
    //Serial.println("Test");
  }
}

In the setup I just simply this for connection:

 WiFi.mode(WIFI_STA);
 wifiManager.autoConnect("LineaMeteoStazioneS", "LaMeteo2005");

Of course I already have in the code the following:

#include <ESP8266WiFi.h>
#include <WiFiManager.h>         // https://github.com/tzapu/WiFiManager
#include <DNSServer.h>            //Local DNS Server used for redirecting all requests to the configuration portal
#include <ESP8266WebServer.h> 
WiFiManager wifiManager;

Do you think I can improve somehow this?

I'm using a Wemos D1 mini pro and external antenna.

Thank you in advance!

tablatronix commented 4 years ago

In this case I would avoid using autoconnect and manually start up cp when needed to avoid this.

You can also make sure you are setting a portal timeout so it doesn't sit there.

floatAsNeeded commented 4 years ago

Hi! Thank you for your answer!

You mean to put in the code already the Wifi information like password and name? For the purpose of my project, I really need to use Autoconnect because I want to set up the wifi connection not by software in case I want to use different networks in different locations of the world also.

I'm using at the moment this code, as you suggested to put a portal timeout

I'm running in the setup this

 WiFi.mode(WIFI_STA);
    //wifiManager.setConfigPortalBlocking(false);
    wifiManager.setConfigPortalTimeout(120);

    res = wifiManager.autoConnect("LineaMeteoStazioneS", "LaMeteo2005");

    if (!res) {
      Serial.println("Failed to connect");
      ESP.deepSleep(60 * 1000000, WAKE_RF_DEFAULT);
    }

and in the loop this

WiFi.forceSleepWake();
    delay(100);
    WiFi.mode(WIFI_STA);

    WiFi.begin();
    while (WiFi.status() != WL_CONNECTED) {
      delay(250);
      Serial.print(".");
    }

Basically, if it fails to connect it goes to sleep for 1 minute and then would try again and again until it connects. In this case just if for real you need to set up the network it won't connect, but it should avoid the fact to get stuck in case of just missed connection. I'm then running in the loop just simple Wifi.begin

What do you think about this? And also if you could explain that CP startup. Thanks! :)

tablatronix commented 4 years ago

Well you can maybe add a timer and if you cannot reconnect after 3 retries, then start configportal. Or run your own check and and use button press etc

floatAsNeeded commented 4 years ago

Yes, I also added a timer, but just in the loop, because in the setup there is already the portal timeout.

So basically I'm putting the loop :

 WiFi.forceSleepWake();
    delay(100);
    WiFi.mode(WIFI_STA);
    WiFi.begin();
    unsigned long timeout = millis();
    while (WiFi.status() != WL_CONNECTED) {
      delay(250);
      Serial.print(".");
      if (millis() - timeout > 30000)
      {
        Serial.println("Going to sleep for 1 minute and try again from setup..");
        ESP.deepSleep(60 * 1000000, WAKE_RF_DEFAULT);
      }
    }

In case it takes more than 30 seconds to establish a connection it goes to sleep, just for saving power purpose and then try again from setup.

WiFi.mode(WIFI_STA);
  wifiManager.setConfigPortalTimeout(120);

  res = wifiManager.autoConnect("LineaMeteoStazioneS", "LaMeteo2005");

  if (!res) {
    Serial.println("Failed to connect");
    ESP.deepSleep(60 * 1000000, WAKE_RF_DEFAULT);
  }

In setup, if it fails it still will try until everything is not set as it should. I think unless for real the network is not available anymore, it should work this way!

tablatronix commented 4 years ago

yeah you can do it like that, I mean you do not necessarily need to reboot, but that works ok also if its a hardware issue.

floatAsNeeded commented 4 years ago

Yeah, I prefer to do it like that also for what you mention and also I want to take every chance to save a bit power, otherwise, it would be continuously using at least 75mA, until connection is not established. At least sleeping for 1 minute can provide me a bit of saving of energy. In my project, I'm using a solar panel and a battery so I need to do that :D Thanks for the help