Hardware: WeMos D1 mini
Core Version: v2.2.0
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:
```mode : sta(MAC)
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
```cpp
#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.
ESP.deepSleep(1, WAKE_RF_DEFAULT)
as a hack to switch the RF back on, but surely there is a better way?
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.
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?
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.
Thanks, that seems to be working nicely.
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?
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.
How does one call __get_rf_mode() in an ino file?
@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.
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);
}
The code above does not compile verbatim. Arduino IDE complains about line 19 "'WifiOff' was not declared in this scope"...
@2000jago Yup, I wrote WifiOff instead of WiFiOff by mistake. Corrected.
@pfabri I can confirm (on wemos D1 mini) this does indeed work and it works well. Thank you sir!
Would be nice to add those functions to the core ESP.h class
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 ;
}
else
{line = ("Conexion OK a WiFi");
Serial.println (line);
}
return;
}
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!
Does your module have an LED? is it on? If so, that's likely your power drain.
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.
Closing in view of previous comment.
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?
@amadeuspzs Please make your proposal in a PR.
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/
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.

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

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.
Most helpful comment
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.