1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-13 13:01:55 +03:00

WIFI_RESUME improve speed and example (#7877)

Improve resume speed by passing in last known BSSID
Provide a simpler example for WIFI_SHUTDOWN/WIFI_RESUME
Add documentation for WIFI_SHUTDOWN and WIFI_RESUME.
This commit is contained in:
Michael Pöttgen
2021-02-15 22:51:37 +01:00
committed by GitHub
parent e4435fa306
commit bc3daef76d
5 changed files with 122 additions and 270 deletions

View File

@ -0,0 +1,85 @@
// Demonstrate the use of WiFi.mode(WIFI_SHUTDOWN)/WiFi.mode(WIFI_RESUME)
// Released to public domain
// Current on WEMOS D1 mini (including: LDO, usbserial chip):
// ~85mA during normal operations
// ~30mA during wifi shutdown
// ~5mA during deepsleep
#ifndef STASSID
#define STASSID "mynetwork"
#define STAPSK "mynetworkpasswd"
#endif
#ifndef RTC_USER_DATA_SLOT_WIFI_STATE
#define RTC_USER_DATA_SLOT_WIFI_STATE 33u
#endif
#include <ESP8266WiFi.h>
#include <include/WiFiState.h> // WiFiState structure details
WiFiState state;
const char* ssid = STASSID;
const char* password = STAPSK;
void preinit(void) {
// Make sure, wifi stays off after boot.
ESP8266WiFiClass::preinitWiFiOff();
}
void setup() {
Serial.begin(74880);
//Serial.setDebugOutput(true); // If you need debug output
Serial.println("Trying to resume WiFi connection...");
// May be necessary after deepSleep. Otherwise you may get "error: pll_cal exceeds 2ms!!!" when trying to connect
delay(1);
// ---
// Here you can do whatever you need to do that doesn't need a WiFi connection.
// ---
ESP.rtcUserMemoryRead(RTC_USER_DATA_SLOT_WIFI_STATE, reinterpret_cast<uint32_t *>(&state), sizeof(state));
unsigned long start = millis();
if (!WiFi.mode(WIFI_RESUME, &state)
|| (WiFi.waitForConnectResult(10000) != WL_CONNECTED)) {
Serial.println("Cannot resume WiFi connection, connecting via begin...");
WiFi.persistent(false);
if (!WiFi.mode(WIFI_STA)
|| !WiFi.begin(ssid, password)
|| (WiFi.waitForConnectResult(10000) != WL_CONNECTED)) {
WiFi.mode(WIFI_OFF);
Serial.println("Cannot connect!");
Serial.flush();
ESP.deepSleep(10e6, RF_DISABLED);
return;
}
}
unsigned long duration = millis() - start;
Serial.printf("Duration: %f", duration * 0.001);
Serial.println();
// ---
// Here you can do whatever you need to do that needs a WiFi connection.
// ---
WiFi.mode(WIFI_SHUTDOWN, &state);
ESP.rtcUserMemoryWrite(RTC_USER_DATA_SLOT_WIFI_STATE, reinterpret_cast<uint32_t *>(&state), sizeof(state));
// ---
// Here you can do whatever you need to do that doesn't need a WiFi connection anymore.
// ---
Serial.println("Done.");
Serial.flush();
ESP.deepSleep(10e6, RF_DISABLED);
}
void loop() {
// Nothing to do here.
}

View File

@ -826,11 +826,10 @@ bool ESP8266WiFiGenericClass::resumeFromShutdown (WiFiState* state)
}
}
}
// state->state.fwconfig.bssid is not real bssid (it's what user may have provided when bssid_set==1)
auto beginResult = WiFi.begin((const char*)state->state.fwconfig.ssid,
(const char*)state->state.fwconfig.password,
state->state.channel,
nullptr/*(const uint8_t*)state->state.fwconfig.bssid*/, // <- try with gw's mac address?
state->state.fwconfig.bssid,
true);
if (beginResult == WL_CONNECT_FAILED)
{

View File

@ -1,258 +0,0 @@
// demonstrate the use of WiFi.mode(SHUTDOWN/RESUME)
// released to public domain
// current on wemos d1 mini (including: ldo, usbserial chip):
// ~85mA during normal operations
// ~30mA during wifi shutdown
// ~5mA during deepsleep
#ifndef STASSID
#define STASSID "mynetwork"
#define STAPSK "mynetworkpasswd"
#endif
#define WAIT_NTP 0 // define this to 1 for NTP check too
#include <ESP8266WiFi.h>
#include <coredecls.h> // crc32()
#include <include/WiFiState.h> // WiFiState structure details
enum state_e {
e_initial,
e_start_resume,
e_start_normal,
e_off_restart,
e_wait_connected,
e_wait_ntp,
e_shutdown,
e_wait_shutdown,
e_wait_off
};
static state_e step = e_initial; // step
static int wifi_timeout = 0; // wifi timeout counter
static bool time_is_set = false; // WAIT_NTP=1: wait for network - dhcp packet must have ntp server
// non volatile data
struct nv_s {
WiFiState wss; // core's wifi save state
uint32_t crc;
struct {
int rstcounter[7];
} data;
};
static nv_s* nv = (nv_s*)RTC_USER_MEM; // user non volatile area
#define SEP "###### "
#define EV "!!!!!! "
#define NFO "------ "
void resetUserCrc() {
nv->crc = crc32(&nv->data, sizeof(nv->data));
}
void printNv() {
Serial.printf(NFO "nfo1/2 wifi-nv-state: valid=%d, "
"persistent=%d, "
"mode=%d, "
"channel=%d, "
"ip=%s, "
"dns=%s, "
"ntp=%s\n",
WiFi.shutdownValidCRC(&nv->wss),
nv->wss.state.persistent,
nv->wss.state.mode,
nv->wss.state.channel,
IPAddress(&nv->wss.state.ip.ip).toString().c_str(),
IPAddress(&nv->wss.state.dns[0]).toString().c_str(),
IPAddress(&nv->wss.state.ntp[0]).toString().c_str());
Serial.printf(NFO "nfo2/2 rst reason counters: default:%d wdt:%d exception:%d softwdt:%d reset:%d deepsleep:%d extsys:%d\n",
nv->data.rstcounter[0],
nv->data.rstcounter[1],
nv->data.rstcounter[2],
nv->data.rstcounter[3],
nv->data.rstcounter[4],
nv->data.rstcounter[5],
nv->data.rstcounter[6]);
}
void timeset_cb() {
time_is_set = true;
static bool first = true;
if (first) {
first = false;
}
}
decltype(millis()) startup;
WiFiEventHandler evOff = WiFi.onWiFiModeChange([](const WiFiEventModeChange& event) {
Serial.printf(EV "mode changed event: ev:%d->%d getMode=%d\n", event.oldMode, event.newMode, wifi_get_opmode());
});
void preinit() {
ESP8266WiFiClass::preinitWiFiOff();
}
void setup() {
WiFi.persistent(false);
startup = millis();
Serial.begin(115200);
settimeofday_cb(timeset_cb);
// prepare non volatile user structure
if (crc32(&nv->data, sizeof(nv->data)) != nv->crc) {
memset(&nv->data, 0, sizeof(nv->data));
Serial.printf(SEP "reset NV user data\n");
}
// update reset reason
nv->data.rstcounter[system_get_rst_info()->reason]++;
// recalculate crc
resetUserCrc();
// nfo
printNv();
Serial.println("setup()");
}
#define TEST(x...) ({ auto v = x; Serial.printf(SEP "'%s': result = %d\n", #x, v); v; })
void loop() {
static int prev = 255;
if (step != prev) {
prev = step;
Serial.printf(NFO "step %d - wifi getMode=%d=%d heap=%d freeheap=%d\n",
prev,
WiFi.getMode(),
wifi_get_opmode(),
ESP.getFreeHeap(),
ESP.getFreeHeap());
printNv();
}
switch (step) {
case e_initial: {
if (WiFi.shutdownValidCRC(&nv->wss)) {
step = e_start_resume;
} else {
step = e_start_normal;
}
break;
}
case e_start_resume:
Serial.println(SEP "CRC valid => WIFI_RESUME");
startup = millis();
if (!TEST(WiFi.mode(WIFI_RESUME, &nv->wss))) {
Serial.printf(SEP "issue resuming WiFi\n");
step = e_off_restart;
} else {
Serial.printf(SEP "waiting for connected\\n");
step = e_wait_connected;
}
break;
case e_start_normal:
Serial.printf(SEP "CRC NOT valid, begin/WIFI_STA (current mode = %d)\n", wifi_get_opmode());
startup = millis();
if (!TEST(WiFi.mode(WIFI_STA)) || !TEST(WiFi.begin(STASSID, STAPSK))) {
Serial.printf(SEP "issue setting up STA\n");
step = e_off_restart;
} else {
Serial.printf(SEP "waiting for connected\n");
step = e_wait_connected;
}
break;
case e_wait_connected:
if (WiFi.status() == WL_CONNECTED) {
Serial.printf(SEP "connected! ---- startup time: %ld ms ----\n\n\n", millis() - startup);
wifi_timeout = 0;
if (WAIT_NTP) {
step = e_wait_ntp;
Serial.printf(SEP "wait for NTP\n");
} else {
step = e_shutdown;
}
} else if ((millis() - startup > 10000)) {
Serial.printf(SEP "connected TIMEOUT! status=%d\n", WiFi.status());
wifi_timeout++;
step = e_off_restart;
}
break;
case e_off_restart:
Serial.printf(SEP "OFF -> wait 2s\n");
(void)TEST(WiFi.mode(WIFI_OFF));
delay(2000); // test - mad wifi loop until :oom if delay not there - to verify
step = e_initial;
break;
case e_wait_ntp:
// check when NTP has set time
if (time_is_set) {
Serial.printf(SEP "NTP is set\n");
time_is_set = false;
step = e_shutdown;
}
break;
case e_shutdown: {
static int deepsleep = 0;
switch (++deepsleep) {
case 1: {
Serial.println(SEP "WIFI_OFF for 5s");
TEST(WiFi.mode(WIFI_OFF));
step = e_wait_off;
break;
}
case 2: // several loop on shutdown
case 3: // to check if it affects
case 4: { // reconnection duration
Serial.println(SEP "WIFI_SHUTDOWN for 5s");
TEST(WiFi.mode(WIFI_SHUTDOWN, &nv->wss));
step = e_wait_shutdown;
break;
}
default: {
Serial.println(SEP "DEEPSLEEP for 5s (bind GPIO16 <=> RST)");
TEST(WiFi.mode(WIFI_SHUTDOWN, &nv->wss));
Serial.flush();
ESP.deepSleep(5000000);
// will reboot, GPIO16 must be connected to reset
}
}
startup = millis();
break;
}
case e_wait_shutdown:
if (millis() - startup > 5000) {
step = e_start_resume;
}
break;
case e_wait_off:
if (millis() - startup > 5000) {
step = e_start_normal;
}
break;
}
}