0
votes

I am building a small sensor based on the ESP8266. For setting up wifi I host a small webserver, where the user can enter the credentials.

In the setup routine I load the credentials and try to connect to wifi. If the connection fails, the esp creates an AP and the user can enter new credentials.

I got some strange behaviour. Because when I remove the credentials, the esp nevertheless connects successfully to the wifi. But the 'serial.print()' don't show any credentials.

Maybe its a problem with the EEPROM or FLASH I have no idea. I could reproduce this behaviour on several ESPs.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>

ESP8266WebServer server(80);

const char *soft_ap_ssid = "Connect Sensor to MCU";
const char *soft_ap_password = "MySensor";

char ssid[32] = "";
char password[32] = "";

bool wifi_status;

void setup()
{
    Serial.begin(115200);
    Serial.println();
    delay(10);

    load_credentials();
    wifi_status = setup_wifi(5);

    if (!wifi_status)
    {
        setup_soft_ap();
        setup_server();
    }
}

void loop()
{
    if (!wifi_status)
    {
        server.handleClient();
    }
    else
    {
        Serial.println("Doing Sensor stuff");
        delay(2000);
        // Remove exsting credentials
        for( int i = 0; i < sizeof(ssid);  i++ ){
            ssid[i] = (char)0;
            password[i] = (char)0;
        }
        save_credentials();
    }
}

/*
############## Gernerische Code ########### TODO LIB
*/
bool setup_wifi(int timeout)
{
    int timeout_ctr = 0;
    Serial.print("Connecting to ");
    Serial.println(ssid);

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

    while ((WiFi.status() != WL_CONNECTED) && (timeout_ctr < timeout))
    {
        delay(500);
        Serial.println("...");
        timeout_ctr++;
    }

    if (WiFi.status())
    {
        Serial.print("IP address: ");
        Serial.println(WiFi.localIP()); //Print the local IP
    }
    else
    {
        Serial.println("Connection to MCU failed, setting up AP.");
    }

    return (WiFi.status() == WL_CONNECTED);
}

void setup_soft_ap()
{
    Serial.println();
    Serial.println("Creating WiFi AP...");

    WiFi.softAP(soft_ap_ssid, soft_ap_password);
    Serial.print("AP \"");
    Serial.print(soft_ap_ssid);
    Serial.println("\" is online.");
    Serial.print("IP address: ");
    Serial.println(WiFi.softAPIP());
    Serial.println();
}

void setup_server()
{
    server.on("/", handle_root);         //Associate the landingpage function to the path
    server.on("/submit", handle_submit); //Associate the handler function to the path
    server.begin();                     //Start the server
    Serial.println("Server listening");
}

void handle_root()
{
    const char *landingpage = "<html><head> <title>ESP8266 Demo</title> <style></style></head><body> <h1>Sensor einrichten</h1> <p> Eingabe der Wifi Daten </p><form action='/submit' method='post'> <input type='text' name='ssid' placeholder='Wifi SSID'> <input type='text' name='pw' placeholder='Wifi Password'> <input type='submit' value='Submit'> </form></body></html>";
    server.send(200, "text/html", landingpage);
}

void handle_submit()
{
    if (server.args() > 0)
    {
        Serial.println("POST:");
        Serial.println(server.arg("ssid"));
        Serial.println(server.arg("pw"));

        server.arg("ssid").toCharArray(ssid, sizeof(ssid) - 1);
        server.arg("pw").toCharArray(password, sizeof(password) - 1);

        Serial.println("credentials:");
        Serial.println(ssid);
        Serial.println(password);
        save_credentials();
    }
    server.sendHeader("Location", String("/"), true);
    server.send(302, "text/plain", "");
}

void load_credentials()
{
    EEPROM.begin(512);
    EEPROM.get(0, ssid);
    EEPROM.get(0 + sizeof(ssid), password);
    char ok[2 + 1];
    EEPROM.get(0 + sizeof(ssid) + sizeof(password), ok);
    EEPROM.end();
    if (String(ok) != String("OK"))
    {
        ssid[0] = 0;
        password[0] = 0;
    }
    Serial.println("Recovered credentials:");
    Serial.println(ssid);
    Serial.println(password);
}

/** Store WLAN credentials to EEPROM */
void save_credentials()
{
    EEPROM.begin(512);
    EEPROM.put(0, ssid);
    EEPROM.put(0 + sizeof(ssid), password);
    char ok[2 + 1] = "OK";
    EEPROM.put(0 + sizeof(ssid) + sizeof(password), ok);
    EEPROM.commit();
    EEPROM.end();
}
1

1 Answers

1
votes

By default, the ESP8266 Arduino SDK saves its wifi configuration in flash memory.

This is documented but not called out clearly.

You'll need to call Wifi.persistent() to get the ESP to not save the credentials. This doesn't seem to be called out clearly in a lot of ESP Arduino Core writeups that I've seen.

Try this:

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

WiFi.persistent(false);
WiFi.begin(ssid, password); //Connect to the WiFi network

while ((WiFi.status() != WL_CONNECTED) && (timeout_ctr < timeout))

You'll probably want to write a bad set of credentials to flash before you update your code to tell the SDK to stop saving them, otherwise I think it will keep using the last saved set. The alternative is to wipe the sector of flash on your ESP where the credentials are stored, which is a lot more work.

There's some documentation on WiFi.persistent() here - which appears to be incorrect - I believe this call operates the way I described (passing false just doesn't store the credentials at all).

If your project is going to be restarting frequently (like going in and out of deep sleep often) I'd definitely use WiFi.persistent(false) to avoid wear on the flash.