datacute / DoubleResetDetector

Library to detect a double reset, using ESP8266 RTC User Memory
MIT License
87 stars 16 forks source link

Adding Double Reset Detector As An example To WiFi Manager #1

Open kentaylor opened 8 years ago

kentaylor commented 8 years ago

Using a double reset to go into WiFi configuration mode which was mentioned at https://github.com/tzapu/WiFiManager/issues/160#issuecomment-241237648 is a great concept. This has the advantage that human intervention is required to initiate WiFi configuration but avoids the requirement of an extra button to initiate WiFi configuration.

I can see two issues though:-

  1. If the power supply is flaky it can be detected as a double reset and go into configuration mode.
  2. The device freezes for the double reset detection interval which in the example is 10 seconds.

If this was done with RTC memory rather than SPIFFS the record of a reset disappears in the case of a power outage but remains when the reset button is pushed. This would eliminate issue 1.

Perhaps issue 2 wouldn't be too bad if the double reset time was short, say half a second, or maybe the reset flag could be cleared with a timer and callback so it is non blocking.

I'd like to add an example using using a double reset to go into WiFi configuration mode to the version of WiFiManager at https://github.com/kentaylor/WiFiManager, ideally with your help.

datacute commented 8 years ago

Thanks.

Yes, a flaky power supply could trigger a double reset detection. I hadn't been aware of the characteristics of the ESPS8266's RTC memory. Thanks for the idea, I like it.

The device doesn't freeze. Calling drd.loop() in your main loop simply checks whether it's time to remove the flag (SPIFFS file) indicating that the device has recently booted. That's a non-blocking if statement, not a while loop.

I do plan on uploading a couple of repositories of my code that use my double reset detector, and your modified version of the WiFiManager. I did have to alter WiFiManager more though, since there was no way to change your mind once you entered configuration mode. The change I made was to set configuration changes to not be persistent while clearing the connection details. (I'm also thinking of changing the default configuration action to be "save and reset" - since I'm always switching channels, resulting in losing my connection, and I'm not too concerned with getting feedback to my browser regarding the configuration change.)

kentaylor commented 8 years ago

Thanks for the freezing explanation.

I don't understand "there was no way to change your mind once you entered configuration mode". URL http://192.168.4.1/close goes out of configuration mode and can be called prior to changing configuration parameters.

If you would fork kentaylor/wifimanager and implement your changes in a way that is easy to incorporate into the existing version that would be great. Perhaps you could have a branch that has minimal changes and another with changes that are harder to integrate into the existing version.

Human initiated configuration without a dedicated button is useful. I'd like to add that as an example.

datacute commented 8 years ago

I've pushed one of my repositories that uses WifiManager and DoubleResetDetector, to https://github.com/datacute/OLED_MQTT

My comment was about an older version, before you removed the call to WiFi.disconnect(true) in startConfigPortal. I had spent an evening with no internet access, trying to get double reset detection behaviour I liked, but couldn't enter config mode without it losing my connections settings. When I got home and saw the code that is run within WiFi.disconnect, I discovered I could get the behaviour I liked with this:

WiFi.persistent(false);
WiFi.disconnect(true);
WiFi.persistent(true);
kentaylor commented 8 years ago

I see you are using a screen. I am too with this sketch https://github.com/kentaylor/esp8266-weather-station/blob/master/examples/WeatherDHT22ThreeScreensWiFiManager/WeatherDHT22ThreeScreensWiFiManager.ino . An idea I'm trying there is a single multi function button. Long press, short press and double press are 3 different states. I've been do some user testing with this app and found users find WiFi configuration much easier with screen feedback.

So you must be still using an old WiFiManager library version. You can see why setting wifi.persistent false keeps the WiFi data at https://github.com/esp8266/Arduino/blob/bbaed29b7e55f15d61eeedbf4d91e0473672222d/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp#L255 .

You should try the latest version. I've added a feature set explanation at https://github.com/kentaylor/WiFiManager/blob/master/README.md . One thing which should fix a lot of user confusion is setting the device URL to http://wifi.urremote.com regardless of the URL you call it with. Then when users go to this address on the wrong WiFi network they get advice on what they are doing wrong rather than just a failure.

I remain keen to incorporate double reset configuration portal launching using the RTC clock.

jgarridc commented 7 years ago

Hi good afternoon, sorry about my english..... Well I am usign tzapu wifimanager libray and its fantastic, but I need to make a pshisical reset in my nodemcu when I want, and I found de doble reset, and its fantastic too. But the problem I have is the next:

When I use the double reset library I have a problem with this code line:

if (isnan(temp) || isnan(humi)){ Serial.println("Fallo en lectura de temperatura y humedad"); return;} But with tzapu library its works fine.

This is all the sketch I use:

`#include

include

include

include

include

include

include //librería conexión a thingspeak

include //librería esp8266

define DHTTYPE DHT22

include

LiquidCrystal_I2C lcd(0x27, 16, 2);

const char serverThingspeak = "api.thingspeak.com"; const char WiFi_hostname = "xxxxxxxxxxx6"; unsigned long myChannelNumber = xxxxxxxxxxxx; const char * myWriteAPIKey = "xxxxxxxxxxxxxxxxx"; const int releCaldera = 16; const int DHTpin = D4; float histeresis = 1; static unsigned long last_loop; unsigned long int anteriorRefreshDatos = 0; float temp= 0; float humi= 0; float tempDeseada = 00; int calderaHabilitada; int estadoRele = 0; int contconexion = 0;

DHT dht(DHTpin, DHTTYPE);

WiFiClient client; WiFiServer server(80);

void setup() {

Serial.begin(115200);
Serial.println();
dht.begin();
delay(10);

      lcd.clear();
      lcd.begin(16,2);
      lcd.init();
      lcd.backlight();

    WiFiManager wifiManager;

pinMode(releCaldera, OUTPUT);
digitalWrite(releCaldera, LOW);

    IPAddress _ip = IPAddress(192, 168, 1, 10);
    IPAddress _gw = IPAddress(192, 168, 1, 1);
    IPAddress _sn = IPAddress(255, 255, 255, 0);

  wifiManager.setSTAStaticIPConfig(_ip, _gw, _sn);

if (!wifiManager.autoConnect()) { Serial.println("failed to connect, we should reset as see if it connects"); delay(3000); ESP.reset(); delay(5000); }

//if you get here you have connected to the WiFi Serial.println("connected...yeey :)");

Serial.println("local ip"); Serial.println(WiFi.localIP());

// Start the server

ThingSpeak.begin(client); Serial.println("Cliente thingspeak iniciado"); server.begin(); Serial.println("Server iniciado"); delay(10000); }

void refreshDatos(){

if (millis() > anteriorRefreshDatos + 20000){ anteriorRefreshDatos = millis();

float temp = dht.readTemperature(); float humi = dht.readHumidity();

if (isnan(temp) || isnan(humi)){ Serial.println("Fallo en lectura de temperatura y humedad"); return;}

if (calderaHabilitada = 1){
if (temp + histeresis >= tempDeseada && temp > 0)  digitalWrite(releCaldera, LOW);
else if (temp < tempDeseada && temp > 0) digitalWrite(releCaldera, HIGH);
else digitalWrite(releCaldera, LOW); 
     }              

  Serial.println();
  Serial.println("Leyendo datos....");
  Serial.println();
  Serial.printf("RSSI: %d dB\n", WiFi.RSSI());

  Serial.print("Temperatura deseada: ");
  Serial.println(tempDeseada); 
  Serial.print("Temperatura: ");
  Serial.println(temp);
  Serial.print("Humedad: ");
  Serial.println(humi);

        lcd.setCursor(0,0);
        lcd.print("Temp: ");
        lcd.print(temp);
        lcd.print(" ");
        lcd.print((char)223);
        lcd.print("C");
        lcd.setCursor(0,1);
        lcd.print("Hum:  ");
        lcd.print(humi);
        lcd.print(" %");

  int estadoRele = digitalRead(releCaldera);
  if (estadoRele == LOW)
    {
    Serial.print("Estado relé caldera: ");  
    Serial.println("LOW");

        lcd.setCursor(15,0);
        lcd.print(" ");

    } else {
    Serial.print("Estado relé caldera: ");  
    Serial.println("HIGH");

        lcd.setCursor(15,0);
        lcd.print("C");

     }      

          ThingSpeak.setField(1, temp);
          ThingSpeak.setField(2, humi); 
          ThingSpeak.setField(3, estadoRele);
          ThingSpeak.setField(4, tempDeseada);
          ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
          delay(15000);
          Serial.println("Enviando datos...");
          Serial.println();

            }
           }

void loop() {

refreshDatos();

// Check if a client has connected WiFiClient client = server.available(); if (!client) { return;
}

// Read the first line of the request String req = client.readStringUntil('\r'); Serial.println(req); client.flush();

int val;

  if (req.indexOf("/tempDeseada40") != -1){
  tempDeseada = 40;
  val = 1;
  } else if (req.indexOf("/tempDeseada22") != -1){
  tempDeseada = 22;
  val = 1;
  } else if (req.indexOf("/tempDeseada23") != -1){
  tempDeseada = 23;
  val = 1;
  } else if (req.indexOf("/tempDeseada24") != -1){
  tempDeseada = 24;
  val = 1;
  } else if (req.indexOf("/tempDeseada25") != -1){
  tempDeseada = 25;
  val = 1;
  } else if (req.indexOf("/tempDeseada26") != -1){
  tempDeseada = 26;
  val = 1;
  } else if (req.indexOf("/tempDeseada00") != -1){
  tempDeseada = 00;
  val = 0;
  } else {
  Serial.println("peticion invalida");
  client.stop();
  return;  

}

// Set GPIO2 according to the request calderaHabilitada = val; client.flush();

// Prepare the response String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n\r\nGPIO is now "; s += (val)?"high":"low"; s += "\n";

// Send the response to the client client.print(s); delay(1); client.stop(); Serial.println("Client disonnected"); }`

guysoft commented 5 years ago

Hey, Wrote a working project that does this.

Here is the source (which might need clearing up because it hackathon code): https://github.com/guysoft/Mqtt_Wifi_manager

Here is a video for demo and proof: https://www.youtube.com/watch?v=zjSd5B13HYE

guysoft commented 5 years ago