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

Can't re-enable WiFi after ESP.deepSleep(uS, WAKE_RF_DISABLED) ? #3072

Closed
sheffieldnikki opened this issue Mar 22, 2017 · 27 comments
Closed

Comments

@sheffieldnikki
Copy link

sheffieldnikki commented Mar 22, 2017

Basic Infos

Hardware

Hardware: WeMos D1 mini
Core Version: v2.2.0

Description

My sketch spends most of its time in deep sleep, just using the WiFi when it first powers up. This works fine from a full power-cycle, but not if is reset (reset button, or new sketch uploaded over serial). In that case I can't seem to switch the WiFi back on? I presume the RF is disabled from the deep sleep, even through a reset, and WiFi.mode(WIFI_STA) isn't enough to switch it back on?

I get:

add if0
f r0, 
error: pll_cal exceeds 2ms!!!
error: pll_cal exceeds 2ms!!!
error: pll_cal exceeds 2ms!!!
....
error: pll_cal exceeds 2ms!!!
error: pll_cal exceeds 2ms!!!
scandone
reconnect
f 0, error: pll_cal exceeds 2ms!!!
error: pll_cal exceeds 2ms!!!
error: pll_cal exceeds 2ms!!!
....
error: pll_cal exceeds 2ms!!!
error: pll_cal exceeds 2ms!!!
scandone
reconnect
f -180, error: pll_cal exceeds 2ms!!!
error: pll_cal exceeds 2ms!!!
error: pll_cal exceeds 2ms!!!
....
error: pll_cal exceeds 2ms!!!
error: pll_cal exceeds 2ms!!!
scandone
del if0
usl
mode : null

Settings in IDE

Module: WeMos D1 R2 & mini
Flash Size: 4MB
CPU Frequency: 80Mhz
Flash Mode: ?qio?
Flash Frequency: ?40Mhz?
Upload Using: SERIAL
Reset Method: ?ck / nodemcu?

Sketch

#include <ESP8266WiFi.h>
extern "C" {
#include <user_interface.h>
}

void setup() {
  Serial.begin(115200);
  Serial.setDebugOutput(true);
  // Connect to WiFi if we have just powered on (*not* if waking from deep sleep)
  rst_info *resetInfo = ESP.getResetInfoPtr();
  if (resetInfo->reason != REASON_DEEP_SLEEP_AWAKE) {
    WiFi.mode(WIFI_STA);
    WiFi.begin(WLAN_SSID, WLAN_PWD);
    WiFi.setAutoConnect(false);
    WiFi.setAutoReconnect(false);
    WiFi.waitForConnectResult();
    // do some networky stuff


    WiFi.disconnect();
    WiFi.mode(WIFI_OFF);
  }
}

void loop() {
  // do regular non-networking stuff

  // enter deep sleep, with radio off upon waking
  unsigned int sleep_secs = 10;
  ESP.deepSleep(sleep_secs*1000000, WAKE_RF_DISABLED);
}

NB: I'm using WiFi.setAutoConnect(false)/setAutoReconnect because otherwise the board was always trying to connect to the WiFi immediately upon waking from deep sleep, even if WiFi.disconnect(), WiFi.mode(WIFI_OFF) and WAKE_RF_DISABLED had been called.

@sheffieldnikki
Copy link
Author

#644 mentions using:
ESP.deepSleep(1, WAKE_RF_DEFAULT)
as a hack to switch the RF back on, but surely there is a better way?

@igrr
Copy link
Member

igrr commented Mar 23, 2017

No, unfortunately there isn't. If you ask it to do a deep sleep reset and wake up with RF disabled, RF is going to be exactly that — disabled.

@sheffieldnikki
Copy link
Author

OK, is there a fast way to test the RF disabled/enabled state? So my code can distinguish between my 'normal' REASON_DEEP_SLEEP_AWAKE, and when it comes awake from a brief deep sleep used to enable the RF?

@igrr
Copy link
Member

igrr commented Mar 23, 2017

Writing a flag into RTC memory prior to going into deep sleep is probably the easiest way. ESP8266 SDK doesn't provide a function to query RF state.

@sheffieldnikki
Copy link
Author

Thanks, that seems to be working nicely.

@sheffieldnikki
Copy link
Author

Just noticed this line in Esp.h:

#define RF_MODE(mode) int __get_rf_mode() { return mode; }

can't I use __get_rf_mode() to read the current RF state?

@jeanfbrito
Copy link

This is what I'm searching for. I was using LUA scripts on Nodemcu, but it eats alot of battery.
Now I will program in "Arduino" and need to get if the RF is ON, to then send the packets.

@JamesNewton
Copy link

How does one call __get_rf_mode() in an ino file?

@pfabri
Copy link

pfabri commented Dec 1, 2017

@JamesNewton

Not sure about a .ino file. In a .cpp file you could do this: extern int __get_rf_mode();. This will then give you access to __get_rf_mode(), . You could then do int mode = __get_rf_mode()but according to my test this always returns -1 regardless of the active RF_MODE. Sad, I know.

@pfabri
Copy link

pfabri commented Dec 2, 2017

I've discovered a workable solution in a gist

This is the best solution I have found so far (source: GitHub gist)

The two functions below are all you need to toggle your WiFi chip. The huge advantage of using these is that they work without having to invoke an ESP.deepsleep() call.

Mind you, if you have already done an ESP.deepsleep(time, WAKE_RF_DISABLED) that means that your WiFi chip has been disabled altogether (see Igrr's comment above), and calling WiFiOn() will NOT be able to toggle it back ON. In this case you MUST do ESP.deepsleep(time, WAKE_RF_DEFAULT). But once you WiFi chip has been re-enabled, you can call WiFiOn() and WiFiOff() as many times as you please, they will work fine.

extern "C" {
	#include "user_interface.h"  // Required for wifi_station_connect() to work
}

#include <Arduino.h>
#include <ESP8266WiFi.h>

#define FPM_SLEEP_MAX_TIME 0xFFFFFFF

void WiFiOn();
void WiFiOff();

//------------------------------------------------------------------------------

void setup() {

	WiFiOn();
	delay(5000);
	WiFiOff();
	delay(5000);
	ESP.deepSleep(1e6 * 10, WAKE_RF_DEFAULT); // sleep 10 seconds

}

void loop() {
	;
}
//------------------------------------------------------------------------------

void WiFiOn() {

	wifi_fpm_do_wakeup();
	wifi_fpm_close();

	//Serial.println("Reconnecting");
	wifi_set_opmode(STATION_MODE);
	wifi_station_connect();
}


void WiFiOff() {

	//Serial.println("diconnecting client and wifi");
	//client.disconnect();
	wifi_station_disconnect();
	wifi_set_opmode(NULL_MODE);
	wifi_set_sleep_type(MODEM_SLEEP_T);
	wifi_fpm_open();
	wifi_fpm_do_sleep(FPM_SLEEP_MAX_TIME);

}

@therealsputnik
Copy link

The code above does not compile verbatim. Arduino IDE complains about line 19 "'WifiOff' was not declared in this scope"...

@pfabri
Copy link

pfabri commented Dec 16, 2017

@2000jago Yup, I wrote WifiOff instead of WiFiOff by mistake. Corrected.

@therealsputnik
Copy link

@pfabri I can confirm (on wemos D1 mini) this does indeed work and it works well. Thank you sir!

@torntrousers
Copy link
Contributor

Would be nice to add those functions to the core ESP.h class

@angeloh1969
Copy link

hello friends, I have done the following and I disconnected the WiFi, low consumption, still running all processes and then connect the Wifi again it increases the power consumption and works normally

void desc()
{

WiFi.mode(WIFI_OFF);
delay(100);
WiFi.forceSleepBegin();
delay(100);
return;
}

the high delay was very important.
To activate it again.

void conectar()
{
WiFi.begin(SSIDW,PASS);
Serial.print("Conectando..");
delay(100);
int i=0;
while (WiFi.status() != WL_CONNECTED && i<10 )
{
i++;
delay(500);
Serial.print(".");
}
if (WiFi.status() != WL_CONNECTED)
{line = ("Error NO hay conexion a WiFi");
Serial.println (line);
return ;
}

@angeloh1969
Copy link

else
{line = ("Conexion OK a WiFi");
Serial.println (line);

  }

return;
}

@mahesh2000
Copy link

hi, has anyone tested the power usage while in sleep mode? i'm getting 3mA and can't go lower. 3mA is too much for my purpose. thanks!

@ibaranov-cp
Copy link

Does your module have an LED? is it on? If so, that's likely your power drain.

@Tech-TX
Copy link
Contributor

Tech-TX commented Feb 3, 2020

Regarding the original post, I tried every trick I could think of, and I have to agree with igrr about whether you can re-enable WiFi after ESP.deepSleep(time, WAKE_RF_DISABLED)

No, unfortunately there isn't. If you ask it to do a deep sleep reset and wake up with RF disabled, RF is going to be exactly that — disabled.

@devyte
Copy link
Collaborator

devyte commented Feb 3, 2020

Closing in view of previous comment.

@devyte devyte closed this as completed Feb 3, 2020
@amadeuspzs
Copy link
Contributor

I have spent many many hours trying to fix this until I came across this (closed) issue.

Please @igrr and team can you add to the documentation a warning about using WAKE_RF_DISABLED and the tip about using WAKE_RF_DEFAULT to get things up and running again?

@devyte
Copy link
Collaborator

devyte commented May 27, 2020

@amadeuspzs Please make your proposal in a PR.

@rforro
Copy link

rforro commented Dec 9, 2020

Actually I found another solution, which I've successfully tested. The trick is after waking from WAKE_RF_DISABLED the radio has to be put into sleep and immediatelly woken up.

WiFi.forceSleepBegin();
delay(1);
WiFi.forceSleepWake();
delay(1);

Source: https://www.bakke.online/index.php/2017/05/21/reducing-wifi-power-consumption-on-esp8266-part-2/

@Tech-TX
Copy link
Contributor

Tech-TX commented Dec 16, 2020

Yep, works fine to wake the modem after ESP.deepSleep(timeus, WAKE_RF_DISABLED), thanks for finding that!
It boots at 38mA for about 1.5ms, then drops to 18mA and stays there until you enable the modem. Boot time is also significantly shorter, about 9.08ms until it hits setup() instead of 100-150ms when RF_CAL is enabled.

WAKE_RF_DISABLED

Looks like you still pay the piper once you turn the modem on:

wake modem, acquire static IP

There has GOT to be a way to fake it out so that it doesn't do that RF_CAL every time. If you're off by a couple dBm output power, do you really care?? I suspect it's stored in the system area of the RTC RAM, so I'll so snooping there to see if I can decode what changes after an RF_CAL. If you can do it once then save it to the user section of RTC RAM, you could probably copy it back before you turn the modem on. Maybe system_phy_set_powerup_option() will do it.

I'll do a PR to add the modem wake up to the docs.

I've a suspicion @torntrousers might find this of interest. ;-)

edit: Sorry Anthony, I tried every trick I could find in the SDK API book plus the ones from here and I couldn't keep the modem from doing an RF_CAL every time I turned the modem back on. Unless someone else has suggestions, I'm not seeing a benefit in doing WAKE_RF_DISABLED unless you don't want the modem at all. WAKE_NO_RF_CAL is probably a better option, power-wise.

@panosss
Copy link

panosss commented Jan 4, 2022

Actually I found another solution, which I've successfully tested. The trick is after waking from WAKE_RF_DISABLED the radio has to be put into sleep and immediatelly woken up.

WiFi.forceSleepBegin();
delay(1);
WiFi.forceSleepWake();
delay(1);

Source: https://www.bakke.online/index.php/2017/05/21/reducing-wifi-power-consumption-on-esp8266-part-2/

Does not work for me, maybe something has changed in the code?

@nbolton
Copy link

nbolton commented Dec 3, 2022

Does not work for me

Seems to still work for me. Maybe we have different versions?

@nbolton
Copy link

nbolton commented Dec 3, 2022

Hmm, or maybe not. It's a bit unpredictable. Sometimes after using the workaround (below), the ESP8266 will consume 40 mA (not the expected 70 mA), and the connection will fail.

WiFi.forceSleepBegin();
delay(1);
WiFi.forceSleepWake();
delay(1);

After it gets in this weird state, the only way to fix it is to hard power cycle the ESP8266, or call ESP.deepSleep(n, WAKE_RF_DEFAULT)

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

No branches or pull requests