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:
85
libraries/ESP8266WiFi/examples/WiFiShutdown/WiFiShutdown.ino
Normal file
85
libraries/ESP8266WiFi/examples/WiFiShutdown/WiFiShutdown.ino
Normal 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.
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user