Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BREAKING] Disable WiFi at boot by default #7902

Merged
merged 29 commits into from
Apr 9, 2021
Merged

Conversation

d-a-v
Copy link
Collaborator

@d-a-v d-a-v commented Mar 2, 2021

SDK automatically starts WiFi at boot. This was probably intended for the Espressif AT FW that is interactive and preserves state accross reboots. This behavior is generally irrelevant with the Arduino API. Sketches usually start with WiFi.begin() or softAP...

This PR will change the default: WiFi does not anymore automatically fires up at boot.

This will not change anything to standard sketches
Standard calls to WiFi.mode()+WiFi.begin/WiFi.softAP(...) will continue to enable WiFi as usual.
It may smooth current spikes at boot and also decrease DHCP stress.

Legacy behavior can be restored by calling enableWiFiAtBootTime() anywhere in the code (this is a weak void function intended to play with the linker). It may be necessary for WiFi Managers that rely on this SDK feature.

void setup () {
#ifdef WIFI_IS_OFF_AT_BOOT
  enableWiFiAtBootTime(); // can be called from anywhere with the same effect
#endif
  ....
}

This is a proposal as discussed on gitter, here and there, and with maintainers.

Fixes #7303

@d-a-v d-a-v added this to the 3.0.0 milestone Mar 2, 2021
@dok-net
Copy link
Contributor

dok-net commented Mar 2, 2021

@d-a-v Can you please clarify, whether Wifi.begin() alone is sufficient to fully re-enable everything that this PR turns off. It's not entirely clear to me due to the remark concerning Arduino library manager libraries above.

@d-a-v
Copy link
Collaborator Author

d-a-v commented Mar 2, 2021

Wifi.begin() alone is indeed sufficient to fully re-enable everything that this PR turns off.
I successfully tested some WiFiClient examples.
I haven't tried yet softAP examples but I will.

@d-a-v
Copy link
Collaborator Author

d-a-v commented Mar 3, 2021

AP mode with or without STA properly wakes WiFi up too.
Removing (WIP)

@d-a-v d-a-v changed the title [BREAKING] Disable WiFi at boot by default (WIP) [BREAKING] Disable WiFi at boot by default Mar 3, 2021
@d-a-v d-a-v added the alpha included in alpha release label Mar 3, 2021
Copy link
Collaborator

@earlephilhower earlephilhower left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks good to me now, but I really think this needs an entry in the docs somewhere.

@d-a-v
Copy link
Collaborator Author

d-a-v commented Mar 16, 2021

A fix is needed about the xref from the faq (I'm playing a local sphinx build to check sort that out).

Edit: entry point to the doc changes: last entry in this link

@dok-net
Copy link
Contributor

dok-net commented Mar 17, 2021

@d-a-v Could you please correct the opening comments to this PR, it appears that now it's

enableWiFiAtBootTime

:-)

Starting from version 3 of this core, **persistence is disabled by default
and WiFi does not anymore automatically fires up at boot** (see PR `#7902 <https://github.com/esp8266/Arduino/pull/7902>`__).

Previously, SDK was automatically starting WiFi at boot. This was probably
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest highlighting here that the prior to v3 persistent was defaulted to true, and so the wifi creds were always stored to flash when the WiFi was configured, which could lead to a reduced life of the wifi config flash sector, and hence the entire ESP. Starting with v3, persistent defaults to false, so creds aren't stored by the SDK in the flash sector and hence don't survive across reboots.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@devyte I think this is not precisely correct. Settings that were once persisted, remain that way, so thereafter, WiFi.begin(), with no WiFi.persistent(true) in the sketch, as long as enableWiFiAtBootTime() is somewhere in the sketch, will suffice to auto-connect to the AP.

enable radio as usual. It also smooths current spikes at boot and decreases
DHCP stress.

Legacy behavior can be restored by calling ``enableWiFiAtBoot()`` from
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To restore legacy behavior, in addition to calling enableWiFiAtBoot() the user has to call WiFi.persitent(true). This should be used with care, because use could lead to early wear of the wifi config flash sector and hence device failure.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comment about, WiFi.persistent(true) is only needed to change the flash credentials cache, not in a sketch that just wants to use whatever was persisted at any time prior to it.

Copy link
Collaborator Author

@d-a-v d-a-v Mar 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the user has to call WiFi.persitent(true).

True !
I will add it in enableWiFiAtBootTime()
(edit: added)

could lead to early wear of the wifi config flash sector

Given the fact that when persistence is enabled, user config is compared to stored config, I think that's OK.
What do you both think ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I always thought this mode was very important !!!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the wifi is active there is a consumption of energy that it would be good to keep in case of not use, especially if you use batteries for their power supply. In case of sending data, as sometimes I do, it is good to write to the internal memory and then make only one connection per day and send all the data recorded in the preset intervals.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also good to test with a number of different ESP modules (ESP12E/F/S for example) to see if this also has an effect on deep sleep power consumption.
There have been a number of reports on deep sleep power consumption not being close to 60 uA on some nodes, with some reporting success with the most unclear assembly blobs possible and others claiming you need to do a short deep sleep first and then again call deep sleep to get true low power deep sleep and others reporting the WiFi will not start after deep sleep until you go into deep sleep again.

So I would not be surprised to see such topics pop up again if this is changed. (or this may be the final fix for it.... who knows ;) )

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you need deep sleep and low power, you need to set up a series of special things, such as early wifi init, persistent wifi creds, static IP, etc, and then your app will usually have something in setup() and an empty loop. Then you need to check power and optimize more. That's an entirely different and very specific use case compared to the basic "start wifi, connect to some router, wiggle some pins" sketch that newer users usually start with.
In other words, deep sleep needs a special kind of sketch unlike the typical Arduino style setup - loop case addressed by this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

@Tech-TX Tech-TX Apr 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TD-er

Maybe also good to test with a number of different ESP modules (ESP12E/F/S for example) to see if this also has an effect on deep sleep power consumption.
There have been a number of reports on deep sleep power consumption not being close to 60 uA on some nodes, with some reporting success with the most unclear assembly blobs possible and others claiming you need to do a short deep sleep first and then again call deep sleep to get true low power deep sleep and others reporting the WiFi will not start after deep sleep until you go into deep sleep again.

So I would not be surprised to see such topics pop up again if this is changed. (or this may be the final fix for it.... who knows ;) )

I didn't measure any difference in the Deep Sleep current. I looked at startup current and different types of Sleep. The only expected difference with other boards/modules would be due to extra chips on the boards (LDO, USB chip, battery charger, etc.), You can get several uA of difference if your GPIO outputs go the opposite direction from the pullup/pulldown resistors on those pins, ~2uA per pin in that case or 6-8uA higher total, but you pretty much have to have the pullup/pulldown resistors either on the module or in your circuit or it won't boot to Flash. The only time I've seen people reporting WAY high Deep Sleep numbers was 'cos they had a power LED on their board. Oops. Yeah, that's your circuit, not the ESP's Deep Sleep you're seeing.

The people that needed to reset across Deep Sleep a second time to re-enable WiFi after ESP.deepSleep(uS, WAKE_RF_DISABLED) have a fix here. The only wart is that it ALWAYS does a full RF_CAL when you wake the modem that way. I guess it blanks out the stored values for the modem parameters when you do WAKE_RF_DISABLED, so it has to rebuild everything from scratch when it brings the modem up next.

As far as variable current during Deep Sleep, I've never seen it mentioned. Most likely they weren't in Deep Sleep, for whatever reason. The SDK stops WiFi and all timers before entering Sleep, and once it's asleep the CPU PLL screeches to a complete halt and the power drops to around 20uA, which is solely the RTC timer running. I get closer to 16uA since I'm frequently running at 3.0V instead of 3.3V. If someone has an MCVE that demonstrates variable Deep Sleep currents I can figure out what's going on. I have a decent set of tools built or bought now.

I have seen numerous threads about Deep Sleep Zombie mode where it never wakes properly, but the jury is still out on the actual cause(s). I vote for cheap Chinese Flash that doesn't always come up in full drive mode after the Flash has been slept prior to Deep Sleep, but Erriez thinks it's the NodeMCU reset circuit interfering. We could both be right: two different causes or more. Until I get one here I can dissect, my tools are useless at troubleshooting across the Internet.

cores/esp8266/core_esp8266_main.cpp Outdated Show resolved Hide resolved
@@ -419,7 +419,7 @@ bool ESP8266WiFiGenericClass::mode(WiFiMode_t m, WiFiState* state) {
}

if (wifi_fpm_get_sleep_type() != NONE_SLEEP_T) {
// wifi may have been put asleep by ESP8266WiFiGenericClass::preinitWiFiOff
// wifi starts asleep by default
Copy link
Collaborator

@mcspr mcspr Mar 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at esp32's ::mode:
https://github.com/espressif/arduino-esp32/blob/46d5afb17fb91965632dc5fef237117e1fe947fc/libraries/WiFi/src/WiFiGeneric.cpp#L532-L542

Should this be more in-line with that?
i.e.

  • remove this forced modem up, it happens even if we don't change the mode
  • getMode() checks for fpm -> returns null-mode when sleeping
  • mode() consecutively turns off the wifi when WIFI_OFF without an additional call to force sleep and turns it back on as well

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 thanks !

I added 1) and 3).
I'm reticent about 2) because WiFi.mode(WIFI_OFF) will not put the modem to sleep, or puting modem to sleep does not necessarily switches the mode to WIFI_OFF. 2) should come with that no ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant exactly that, to do forcesleep with WiFi.mode(WIFI_OFF) and resume with any real mode.
Not noticed the special shutdown and resume modes though, I wonder if those should be separate methods instead and not a 'mode'?

Copy link
Collaborator Author

@d-a-v d-a-v Mar 31, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are indeed "fake" modes and described as such somewhere. There are two examples making use of them.
They are designed to import the deep sleep procedure into the core and allow users to not use random fw-snippets to put the chip to sleep (and wake-up fast)

Copy link
Collaborator

@mcspr mcspr Mar 31, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aaah, both are already implemented as methods. So examples could use those directly?

Copy link
Collaborator

@earlephilhower earlephilhower left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for adding documentation and comments. I made 2 suggested edits to the wording, up to you if you want to adjust or not.

doc/esp8266wifi/generic-class.rst Outdated Show resolved Hide resolved
doc/faq/readme.rst Outdated Show resolved Hide resolved
@d-a-v d-a-v merged commit 1cc6960 into esp8266:master Apr 9, 2021
@d-a-v d-a-v deleted the WiFiOffAtBoot branch April 9, 2021 21:01
@d-a-v d-a-v mentioned this pull request Apr 10, 2021
6 tasks
@@ -432,6 +426,12 @@ bool ESP8266WiFiGenericClass::mode(WiFiMode_t m, WiFiState* state) {
return true;
}

if (m != WIFI_OFF && wifi_fpm_get_sleep_type() != NONE_SLEEP_T) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small side note / question, will test some time later today
wifi_fpm_get_sleep_type() is MODEM_SLEEP_T by default (in the previous version, or when wifi-off preinit is disabled by user currently) since this is a setting, not the actual mode that is active. is it ok do wakeup & close without fpm active?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
alpha included in alpha release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Change autoreconnect and persistent defaults to be disabled (BREAKING)
8 participants