esp8266 / Arduino

ESP8266 core for Arduino

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ESP.deepSleep(xxxx, WAKE_NO_RFCAL) not working since 2.0.0

wb8wka opened this issue · comments

Summary

RF Calibration cannot be turned off after 2.0.0 in wake from deepSleep causing current spike and longer boot

Hardware

Hardware: Wemos D1 mini and ESP-12S, 470uf cap between Vcc and Ground
Core Version: 2.0.0 (works - No RF Calibration current spike), 2.3.0 (Not working, current spike)
Test equipment: Rigol Scope, 1ohm current shunt, "fuzz" is because I didn't do calibration on scope but traces are accurate.

Description

Using identical code function ESP.deepSleep(6000000, WAKE_NO_RFCAL); in 2.0.0 ESP can wakeup without large current spike from RF_CAL, however after 2.0.0 RF_CAL executes causing large current spike and longer run time. Please see attached current traces. Correct data is sent in both instances, only different is current spike, which appears to be RF_CAL executing.

Sketch sends simple beacon using wifi_send_pkt_freedom. GPIO16 connected to reset.

WAKE_RF_DISABLED does behave as expected in both 2.0.0 and 2.3.0

Also

system_deep_sleep_set_option(2);  // Option 2 is WAKE_NO_RFCAL
//system_deep_sleep(6000000);
system_deep_sleep_instant(6000000);  //  Trims 98ms off go to sleep

has same characteristics in that it cannot turn off RF_CAL

Settings in IDE

Module: WeMos D1 Mini & ESP-12S
Flash Size: 4MB
CPU Frequency: 80Mhz
Flash Mode: qio
Upload Using: SERIAL

Images

061517_1ohm_100mvdiv

Version 2.0.0 without RF_CAL current spike at head

060917_1ohm_100mvdiv

Version 2.3.0 with RF_CAL current spike at head

Sketch


#include <ESP8266WiFi.h>
#include <WiFiClient.h> 
extern "C" {
  #include "user_interface.h"
// (Commented out code below for 2.0.0 to expose send_pkt_freedom, not needed in 2,3.0
//  typedef void (*freedom_outside_cb_t)(uint8 status);
//  int wifi_register_send_pkt_freedom_cb(freedom_outside_cb_t cb);
//  void wifi_unregister_send_pkt_freedom_cb(void);
//  int wifi_send_pkt_freedom(uint8 *buf, int len, bool sys_seq);
  void system_deep_sleep_instant(uint32 time_in_us);
}


byte channel;
byte RandomMac = 1; 
byte SequenceLSB = 0;
byte SequenceMSB = 0;
                 

// Packet I am sending
uint8_t packet[128] = { ......   68 bytes,,,,  };      // Obscured for example                                          


void setup() {
  delay(2);   // in this group was all 50
  wifi_set_opmode(STATION_MODE);
  delay(2);
  wifi_promiscuous_enable(1);     // need
  delay(2);
  system_phy_set_max_tpw(20);    //the maximum value of RF Tx Power, unit : 0.25dBm, range [0, 82] 19dBm = 76, 10dBm = 40, 14 dBm = 56
  delay(2);
}



void loop() {


    wifi_set_channel(1);
    delay(2);     // Delay in MS, was 20
    wifi_send_pkt_freedom(packet, 68, 0);
    //Increment fragment
    //Set fragment
    packet[22] = (SequenceLSB + 1);
    delay(10);     // Delay in MS
    wifi_send_pkt_freedom(packet, 68, 0);
    delay(10);     // Delay in MS
    SequenceLSB = (SequenceLSB & 0xF0);
    packet[22] = SequenceLSB;

    wifi_set_channel(6); 
    delay(2);     // Delay in MS
    wifi_send_pkt_freedom(packet, 68, 0);
    delay(10);     // Delay in MS
    //Increment fragment
    //Set fragment
    packet[22] = (SequenceLSB + 1);
    wifi_send_pkt_freedom(packet, 68, 0);
    delay(10);     // Delay in MS
    SequenceLSB = (SequenceLSB & 0xF0); 
    packet[22] = SequenceLSB;


    wifi_set_channel(11); 
    delay(2);     // Delay in MS
    wifi_send_pkt_freedom(packet, 68, 0);
    delay(10);     // Delay in MS
    //Increment fragment
    packet[22] = (SequenceLSB + 1);
    wifi_send_pkt_freedom(packet, 68, 0);
    delay(2);
   
/// ESP.deepSleep(microseconds, mode) will put the chip into deep sleep. mode is one of WAKE_RF_DEFAULT, WAKE_RFCAL, WAKE_NO_RFCAL, WAKE_RF_DISABLED.

    ESP.deepSleep(6000000, WAKE_NO_RFCAL); // Sleep for 6 seconds,


    //system_deep_sleep_set_option(2);
    //system_deep_sleep(6000000);
    //system_deep_sleep_instant(6000000);
 
}


Also tried 2.4.0-rc1, same issue.

commented

why didn't you post your results on espressif ESP8266 NON_OS_SDK github? Or make a thread on their BBS
It's their tree to bark up ...

Because it works fine on the NON_OS_SDK. It's an Arduino lib issue. Their tree but it appears abandoned at this point. We've now moved onto NON_OS_SDK

thanks for your interest

commented

but using the system_ ... calls accesses the sdk libs directly. Especially when using system_deep_sleep_instant(); I can't think of which arduino lib should interfere with the correct execution of deepsleep with wake_no_rfcal ...

edit: did you try to read the rf_cal byte before the deepsleep call and after bootup?

I wasn't reporting a issue with the SDK libs being used directly, I was reporting a change in behavior with:

ESP.deepSleep(6000000, WAKE_NO_RFCAL)

Between Arduino 2.0.0 and later versions

The system calls noted were commented out and just my earlier experimenting. The code posted behaved differently between 2.0.0 and 2.3.0 in that you couldn't during off RF Calibration after a wake from a deep sleep, using arduino calls, after 2.0.0

commented

according to the starting post

Also

system_deep_sleep_set_option(2); // Option 2 is WAKE_NO_RFCAL
//system_deep_sleep(6000000);
system_deep_sleep_instant(6000000); // Trims 98ms off go to sleep

has same characteristics in that it cannot turn off RF_CAL

you say that the direct use of system_... has the same problem, this is why I suggested to report to espressif directly.

I'm not quite sure why you don't understand me

This is the Github site for reporting issues with the Arduino port. The issue is with the Arduino command

ESP.deepSleep(6000000, WAKE_NO_RFCAL)

NOT the system calls even though I had issues calling them from the arduino code. That could just as easily be operator error on my part and I wasn't reporting those.

Howver I have confirmed the system call's (i.e. system_deep_sleep_instant(6000000);) work fine directly under the NON_OS_SDK. There is nothing to report to espressif because the SDK is doing what it is supposed to.

Sometime after 2.0.0 ESP.deepSleep(xxxxx, WAKE_NO_RFCAL) stop turning off the RF calibration on wake.

If you like I can go back and remove all the commented code out of my example. I had just been trying to test various things.

commented

with the parts I quoted from your OP you say that the same problem exists calling the system_ ... functions (not having problems calling them) leading to the assumption that this might be the root cause.
Since looking at code for ESP.deep_sleep() you'll see that it does practically the same... and hasn't changed for quite some time.
but believe me, I couldn't care less .....

For not "couldn't caring less" you sure seemed to want to argue this

None-the-less it's a real issue and my testing is solid. That it persisted through a few versions before being reported is irrelevant.

Hook your scope up and confirm it yourself if you doubt me

I can confirm that ESP.deepSleep(x, WAKE_RFCAL) is broken in that sense that it does not restart the mcu at all.

commented

@universam1
hmm, working like a clockwork on latest master.
is it only WAKE_RFCAL? also via direct sdk call?
which core/sdk version are you using?
gpio16 - rst are connected?

@igrr
I can now confirm that WAKE_RF_NOCAL is broken, via
ESP.deepSleep();
as well as
system_deep_sleep_set_option();
system_deep_sleep();

#include "user_interface.h"
}
void setup() {
  delay(500);
  ESP.deepSleep(1000000,WAKE_NO_RFCAL);
//  system_deep_sleep_set_option(RF_NO_CAL);
//  system_deep_sleep(1000000);
  delay(10);  
}

void loop() {
}

I can't test on plain sdk to see if its the arduino core or the sdk, most likely some "glue"
It works with core 2.0.0 & sdk 1.3.0_15_08_10_p1
it stops working on core 2.0.0 & sdk 1.5.1_16_01_08
and still won't work on recent master.

here it is ok, no spikes on startup
2 0 0_1 3 0
obvious spikes from RF_CALI at ~200ms longer startup
2 2 0_1 5 1
p.s.: WAKE_RF_DISABLED is still working as expected
master_2 1 0

I have to revert my statement a bit. So with older SDK a mere reboot did work ESP.deepSleep(1, WAKE_RFCAL) with a 1us delay, this is not working any more, I have to specify >1000us for a reliable restart.

Good grief 5chufti, this is what I reported back in July....

commented

Good grief 5chufti, this is what I reported back in July....

very helpfull remark ...

you didn't report this
It works with core 2.0.0 & sdk 1.3.0_15_08_10_p1
it stops working on core 2.0.0 & sdk 1.5.1_16_01_08

and I think it is relevant

@wb8wka I assume this is still relevant after 2.4.0 release, and I also assume you erased the whole flash before upload. You said there is no issue with using only the NONOS SDK system calls. Is this true when using pure system calls from within a simple sketch, or did you mean from a NONOS SDK standalone build without the Arduino core? Could you please pist an example?

@devyte That would be my guess. 2.4.0rc1 I tried and it the issue was still there, Reviewing the change log for 2.4.0 I see no mention of a fix.

I meant it worked with the NONOS SDK standalone build Here is a little clip

#define CAL_OPT 2

// This function executes before WiFi is set up
void user_rf_pre_init (void)
{
  // Set no RF cal
  system_deep_sleep_set_option (CAL_OPT);
  system_phy_set_powerup_option (CAL_OPT);
  system_phy_set_rfoption (CAL_OPT);
}


    wifi_send_pkt_freedom(packet, PACKET_SIZE, 0);

I think I have a fix for this, but need some time to set up a current measurement jig...

commented

@igrr did you get somewhere with your investigations?

@igrr any news on the issue? Maybe some pointers for workaround?

@wb8wka have you tried something like this?

extern "C" void __run_user_rf_pre_init(void) {
    system_phy_set_rfoption(2);
}

It would be great to get a fix for this @igrr , could we help by testing out the fix you think you have?
Or do you even need a current measurement jig - it should be much faster starting up with WAKE_NO_RFCAL so a sketch like this shows if its working or not (for me at 2.0.0 it shows setup starts in 43 milliseconds compared to about 200 in later releases):

#include <ESP8266WiFi.h>

void setup() {
    unsigned long ms = millis();
    Serial.begin(115200); Serial.println();
    Serial.print("Setup time:"); Serial.println(ms);

//    ESP.deepSleep(3000000); 
    ESP.deepSleep(3000000, WAKE_NO_RFCAL); 
}

void loop() {
}

or even any hints at what the possible fix mentioned here - #3408 (comment) - could be so we could try to implement the fix ourselves?

I'd so much like to find a fix for this. Could anyone give any hints on where abouts in the code I could be looking for the problem?

Any news on this issue? This is critical for battery power applications.

Regards,

@igrr sorry to keep pestering I know you must be busy on things but you did say earlier you thought you might know the cause of this so could you give any hints so we could try to find some fix?

A hint on the root cause will be very usefull.

On the other hand a possible work arround would be to modify the 108th byte of the init data (defined in core_esp8266_phy.c) and set it to 255. In principle this will make a call woth WAKE_RF_DEFAULT to calibrate the radio only once every 255 reboots from sleep.

Is there any way to change this byte without patching the core? If not it could included with a similar macro to ADC_MODE/RF_MODE.

Any fix date on this issue?
Regards

commented

Need this too...

I'm looking for a fix for this. Any news?

Hello, I am new to this discussion, so perhaps I missed something…
If the focus is on the broken RF_NO_CAL then this is not relevant but if it relates to costing more power please consider this:

The power cost per cycle in this example is ~ 50 mA/s. The Cal spike “cost” is ~ 5 mA/s.
However, the “cost” of the ESP to set up for the ESP.deepSleep "cost" is ~ 20 mA/s.

If power savings is what you are after, then you may want to consider gating the power to the ESP instead of the deep sleep.
In this scenario, you can bring the power consumption down from the 50 mA/s down to under 20 mA/s

commented

@igrr, please hint us what's your solution. I believe community will be able to add pull request with the fix.

@Ivoatme I don't fully understand your comment.

The problem with NO_CAL not working has two main drawbacks for battery powered applications:

  • Current Spikes are higher than typical transmission spikes and last longer. This could create problems on some regulators/Switch DC-DC and also the battery capacity.

  • "boot time": The first line of code of your setup() is executed after hw/sdk initialisation. In a normal boot it takes 40-50ms if calibration is done it takes up to 200ms to execute your code. In case that the response time is a requirement 200ms would be not suitable for most applications.

On the other hand, I have noticed that the time to connect to wifi (using static IP) is about 300-400 ms when waking from deepSleep while it takes a second when the chip is enabled via CHDP pin or powered up by external system. Completing a typical cycle of wake->measure->send via MQTT->sleep will take a second using deep sleep in contrast with more than 2 seconds it the esp is switched on/off by external timer/subsystem. This could mean theoretically doubling your battery life.

I will provide some captures from my scope. But really quickly here is better explanation...

The "power cost" is defined by integrating the current drawn by the ESP during each sleep cycle. In my example, I am using the ESPNOW code. From the powerup to transmit 250byte payload and receive CB and go to deep sleep... the shortest I can ever make it is ~ 350 ms and so each deep sleep cycle costs ~ 50 mA/s.

However, the payload is transmitted <150 ms and the remaining ~200 ms before you hit deep sleep can be cut out by simply turning off the power. Doing so the power cost to transmit this payload reliably is < 20mA/s. (the ESP literally sits there for 200 ms consuming 70 mA doing nothing except for getting ready to enter the deep sleep.}

In my opinion, there are two separate issues. Yes, the power spikes due to the CAL are detrimental to the very small battery like a coin cell but that can be dealt with by a capacitor. My point is that the spikes you are referencing are so short that their power "cost" is <10 % of the power consumed during each cycle. I do not have the older SDK to compare thing with but I doubt that you will be able to get rid of the first large spike @ ~ 100 ms. I think that this is the ESP (in my case) connecting to the peer. What is interesting is that in that 10ms spike the ESP also transmits the payload.

Did you tried bool system_deep_sleep_instant(uint64 time_in_us); sending the esp to sleep? If I remember well it takes only a few ms to do the job. This , in principle, should remove the 200ms where the esp is preparing the sleep.

As a quick update, I got a consultant to help me and we ported my code over to the native SDK. Here is the current plot (total time on is about 200ms, I send some management frames) along with the code clip.

image

#include "osapi.h"
#include "user_interface.h"

// This function executes before WiFi is set up
void user_rf_pre_init (void)
{
  system_deep_sleep_set_option (2);   // No RF cal on wake-up
  // 1: Vdd and TX power, 18 ms
  // 2: Vdd only, 2 ms
  // 3: Full cal, 200ms
  system_phy_set_powerup_option (2);
  system_phy_set_rfoption (2);

  wifi_set_opmode (NULL);
}

// MAIN CODE
void user_init(void)
{
      system_deep_sleep_instant (1000000);    // Sleep for 10s
}

******************************************************************************
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR
user_rf_cal_sector_set(void)
{
    enum flash_size_map size_map = system_get_flash_size_map();
    uint32 rf_cal_sec = 0;

    switch (size_map) {
        case FLASH_SIZE_4M_MAP_256_256:
            rf_cal_sec = 128 - 5;
            break;

        case FLASH_SIZE_8M_MAP_512_512:
            rf_cal_sec = 256 - 5;
            break;

        case FLASH_SIZE_16M_MAP_512_512:
        case FLASH_SIZE_16M_MAP_1024_1024:
            rf_cal_sec = 512 - 5;
            break;

        case FLASH_SIZE_32M_MAP_512_512:
        case FLASH_SIZE_32M_MAP_1024_1024:
            rf_cal_sec = 1024 - 5;
            break;

        default:
            rf_cal_sec = 0;
            break;
    }

    return rf_cal_sec;
}

@wb8wka am I reading this right: no cal works with the native sdk, but not with our core?

@devyte That is correct and I reported this behavior first on August 2nd, 2017. I moved onto the native SDK as I needed to get this done but do wish it would work under Ardinio.

@devyte here is the very first trace I posted in this thread, but with the code ported over to the native SDK and both no rf cal and deep_sleep_instant working. I cleaned up my scope noise a little since then as well. Wakes up, boots, sends 6 management frames, and then goes back to sleep. 200ms total time. 1 ohm resistor and 50mv per division

image

image

This is running on ESP WROOM 2 @ 160 MHz. and gated power. Note that the purple is the integral of the current and the scale is 0.5 so that the real values must be multiplied 2X.
Total power cost to reliably transmit 248 byte payload is ~ 7.5*2=15 mA/s.

I was unable to make the system_deep_sleep_instant work.
Below for comparison is identical code except using deepSleep. (same scales power cost=~ 60 mA/s !)
image

@devyte did you verify that you are receiving data on the other end?
I ask because I was able to generate something similar but I was unable to push any data across.

I don't use in my app, so I haven't tried any of this. I asked to clarify and to triage this issue.
Thank you for the nonos examples, they help tremendously in these cases.
Something to keep in mind: I understand that deep sleep waits for the wifi to safely shut down before entering deepsleep. In contrast, deep sleep instant just sleeps right away and screw it all. Our deepSleep is using the former. I mention this mostly in case you can't get data across: it's possible that the data doesn't make it out of the radio if you're using instant.
@igrr did you ever get a current measuring rig set up? If not, how about proposing your fix via PR and having @wb8wka or @Ivoatme help out with testing and measuring?

@wb8wka just a quick comment. The 200 ms current plot you shared may be possibly incorrect.
The current drawn during the Tx is way too small in proportion to the rest of the pre-Tx.
I suspect three issues worth checking.

  1. Scope bandwidth
  2. Shunt resistor is too large or otherwise soft PS or something is current limiting
  3. The sharp down rail after Tx suggests the possibility the the your ESP simply shuts down due to power starvation and not necessarily due to the code going to sleep.
    The ~ 150mA current you see during the Tx should be 300-350 mA under normal operating conditions.
    There is another possibility for the low current peaks and that is due to reduced Tx power setting, but I do not have any data on that and if that is the case we are not comparing apples to apples.

@lvoatme

No, it's correct or at least close.

  1. Scope bandwidth is 50mhz

  2. Shunt is 1 ohm with a 470uf cap next to the ESP (downstream of shunt). WiFi frames are being decoded that it is sending.

  3. What you are seeing as the "sharp down rail" is system_deep_sleep_instant() function. All 6 packets are decoded and seen by the access point.

I'm running about 14dBm, according to the data sheet of the ESP8266 that's about 140ma of current consumption. I'm showing spikes of about 160-170ma in my scope diagram. The downstream 470uf cap does round things, but not to any degree and doesn't impact power calculations. I'm also NOT gating power here, which would involve a big inrush current to your filter cap. DeepSleep is triggering the device from sleep OR I assert CE. In either case I don't need to recharge the input filter caps, which would lead to larger current spikes.

I should note this is a working application, using a coin cell and I have 100's of pieces now testing. I'm just commenting to confirm (again) that this is a arduino issue and not a SDK issue as was earlier suggested. I covered this in most of my earlier posts.

Regards

@devyte , slight tangent - "deep sleep instant just sleeps right away and screw it all. Our deepSleep is using the former " - would you accept a pull request that adds a boolean option to ESP.deepSleep for using deep_sleep_instant?

a boolean would be perfect. Nodemcu Lua Interpreter has this option for deepsleep.

commented

it is nice that wb8wka posted some code that somehow shows the wanted behaviour, but this it is no proof for

system_deep_sleep_set_option();
system_deep_sleep();

working, as he is using total different mechanism.
He is using

system_phy_set_powerup_option ();
system_phy_set_rfoption ();

in

void user_rf_pre_init (void)

what means actively supressing rf_cal after wake_up from deepsleep
instead of setting flag to not do "rf_cal at wake_up" before going into deepsleep.

this code would be more like it ...

#include "osapi.h"
#include "user_interface.h"

// MAIN CODE
void user_init(void)
{
   system_deep_sleep_set_option (2);   // No RF cal on wake-up
   system_deep_sleep_instant (1000000);    // Sleep for 10s
}

******************************************************************************
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR
user_rf_cal_sector_set(void)
{
    enum flash_size_map size_map = system_get_flash_size_map();
    uint32 rf_cal_sec = 0;

    switch (size_map) {
        case FLASH_SIZE_4M_MAP_256_256:
            rf_cal_sec = 128 - 5;
            break;

        case FLASH_SIZE_8M_MAP_512_512:
            rf_cal_sec = 256 - 5;
            break;

        case FLASH_SIZE_16M_MAP_512_512:
        case FLASH_SIZE_16M_MAP_1024_1024:
            rf_cal_sec = 512 - 5;
            break;

        case FLASH_SIZE_32M_MAP_512_512:
        case FLASH_SIZE_32M_MAP_1024_1024:
            rf_cal_sec = 1024 - 5;
            break;

        default:
            rf_cal_sec = 0;
            break;
    }

    return rf_cal_sec;
}
commented

p.s.: it is symptomatic for espressif that the current esp8266_non_os_sdk_api_reference_en does not even give the values for the different modes in system_deep_sleep_set_option(), nor on system_phy_set_rfoption(). Only for system_phy_set_powerup_option() but they can't be the same ...
(can't find them in .h of sdk either). Who knows, maybe they changed after 1.3.0 SDK?

I would like to share few thoughts regarding low power designs. My personal experience with the ESP's is that they are power hungry and there are some background processes that take up power that are unpredictable from loop to loop. To illustrate some of the challenges and to be aware of these things, I am attaching a screen capture of the shortest 248 byte transmission packet I am able to push across.
The purple plot shows the integral of the current. the real scale is 4 mA/s and the total packet is 6.6 *2= ~ 13 mA/s. the timescale is 10 ms. Note that having very hard PS the peaks are off the scale and they are as much as 500 mA. So, as an example... 470 uF capacitor stored energy @ 3.3V rail is ~ 2.5 mJ and so when using coin cell battery as a PS you will never see these peeks because of the inherent high internal resistance. The lessons I learned are that if you are experiencing an unpredictable behavior, first thing to check is the power source. The below example would require at least 2,200 uF to keep up with this packet. For stable designs consider using super-caps.
image

@lvoatme

My measurements with the 470uf cap were with a lab power supply. The application does use a coin cell and I have a one farad cap across it. My design is quite stable and any inference it isn't is not correct. It's actually going into a commercial product.

As to your experiences with the ESP8266, mine were similar with the Arduino ESDP8266 IDE, when I went to the native SDK/NONOS all of a sudden, for the most part things matched the spec sheet.. including TX currents. Now that could just as easily be because I gained more experience but I had a job to do and the Arduino release and support didn't appear to be being maintained. That this issue has been confirmed and still open well more then a year later tends to support that feeling.

That being said, I'm happy to confirm current measurements as @devyte suggested should this issue ever need confirmation.

P.S. I like the integration function on your scope

@5chufti

The reason I am actively suppressing rf_cal after wakeup from deepsleep instead of setting flag to not do "rf_cal at wakeup" before going into deepsleep is because I don't use deepsleep to wake up, hence no states are saved.

Instead, I am using chip enabled controlled by a external microcontroller drawing less the a 1 ua on average. The ~17ua of sleep current the ESP requires in deep sleep would negatively impact my battery life as I am running about one year off a coin cell. My average wake cycle is about 10 minutes on the ESP.

I hope that clears it up.

@wb8wka
My comments had nothing to do with or critiquing your design / application. I am simply sharing some experiences and to help others with design challenges.
I do realize that this is bit off the main focus which is the issues with limiting the power draw by software. The changes in behavior from SDK to SDK.
Having seen the poor quality screen captures in this forum, I wanted to illuminate that in order to troubleshoot the "spikes" you have to be able to see them. That of course creates a bit of a challenge because @ 500 mA spike 1 ohm shunt resistor is a considerable regulation problem. And for that reason I wanted to show an example of the current plot using a contact-less current probe.

I really do not want to get in-to a pissing match here but for sake of anyone that wants to learn something... a bench PS with a 470 uF cap may not be an adequate power source for debugging strange behavior in ESP. And if you throw in to the mix 1 ohm shunt for your scope, you may be in for some challenges.
It may save someone countless hours of frustration trying to catch something that may look like a bug that is actually caused by a soft PS. Once your design is stable and running scaling back to soft PS is the way to go. Again, for development with ESP's I recommend using Super cap's.
So, if I ruffle anyone's feathers, it certainly was not the intention. My apologizes ;-)

@lvoatme

The fact you pointed out "coin cell" and "470 uf cap", which I earlier stated I used, yes lead me to believe you were referring to me. I am using a 1 farad supercap. The 470uf cap is on the input pin of the ESP8266 and is more the enough with a stiff (low esr) supply. My design is up and running and what I posted was accurate. I've used lower values for the shunt resistor and other then scaling, the waveform is the same.

No interest either in getting in a pissing match but it was these sort of exchanges that caused me to leave the project a year ago. I was making a bug report, not looking for a debate.

What is the contactless probe you are using?

I am using Tektronix A 6302 current probe with the 503A amplifier.
The supecap for my development if 3000F. (the supercap is a new proprietary part that is in a late stages of development. When it becomes available I will definitely share more info about it)
In fact... you may be interested in your commercial application in this. This cap unlike "normal" supecaps has NO leakage so it behaves like a battery but with characteristic low esr of a capacitor.
With that configuration I was able to identify several issues that I thought were a software and they magically went away with the stiff PS.
Some of the capture issues are related to the equipment bandwidth also, because the ESP "spikes" have such a fast rise time. I can even see a difference between 100 MHz and 500 MHz current probes.
What makes things so elusive sometimes if the build in transmission error correction when using TCP. A packet will eventually get across and absent of some fancy triggering it is a challenge to catch.
With a soft PS and using UDP I finally came to realization that if I wanted to keep my sanity eliminating any possible issues by having a low esr PS was a must.

commented

@wb8wka
nope, that does not clear anything.
You stated that ESP.deepSleep(xxxx, WAKE_NO_RFCAL) is not working since 2.0.0 but is working in plain SDK, but you did not proof that the correct equivalent to ESP.deepSleep(xxxx, WAKE_NO_RFCAL) is working in SDK but only that you can get similar effect in plain SDK.

I'm not interested in a "Pissing match" either, but we all here are technicians and should very carefully read such statements and tell facts from fiction when dealing with an error report regarding a certain function in arduino esp core. Because the difference is the line between the error being in arduino esp core or in SDK, so not minute.

That you found a way to work around that error is good for you, but does not help in fixing the error.
It could though lead to some workaround in arduino esp core in that one could try to use

system_phy_set_powerup_option ();

in ESP.deepSleep() in case that requested wake mode is 2.

@5chufti

If you'd be so kind as to look at your post from November 7th, 2017 you'll see you stated:

@igrr
I can now confirm that WAKE_RF_NOCAL is broken, via
ESP.deepSleep();
as well as
system_deep_sleep_set_option();
system_deep_sleep();

Which of course was my bug report. Which others, including igrr, have confirmed as well.

As we've now come full circle I'll wish you well.

commented

@wb8wka
the bug report per se was correct.
Your following statement that the equivalent to ESP.deepSleep(xxxx, WAKE_NO_RFCAL) is working in SDK was not!
why is it allways so hard to discuss with HAMs on pure technical grounds?
fare well to you and good luck to @igrr, @devyte chasing down the error in the wrong direction...

@5chufti

Before your latest @igrr indicated he had a fix for this on Jan 7th 2018 so I doubt he got lead in the wrong direction by my moving onto the SDK and using a different method to achive my goal. The bug, as originally reported, was validated

As to your question, I do not know other then to point you back to your last exchange on August 3rd, 2017 which might give you some insight. This is a bug reporting system, not a debate board.

commented

It looks like this change is causing problems. At least, if I disable that block of code, I can see that wake up time is dropping to ~40ms. But I do not yet understand what it is doing.

Dude! @mailgpa you're a star. That fixes it for me too, wake up to setup() goes from about 200ms down to 39ms.

commented

Thanks to @wb8wka who gave a hint that it works in native SDK. That change seems to be a workaround for some old bug from 2015 which must have been fixed in SDK already.

I confirm that the solution also works fine also for me. Also I tested instant version of deep sleep in my scope, it put the device to sleep in about 5ms. Both PRs submitted by @torntrousers will be able to reduce the wake time more than 350ms. For espnow this will potentially double your battery life.
In mqtt scenarios, this could represent a 20%-30% of improvement.

thanks @mailgpa for the insight! Finally you have solved this old issue!

@mailgpa how in the holy source code did you arrive at that? It's like you reached into fhe haystack and pulled out the needle on the first try!

Heres the code and the output. Hw is a cheap Wemos D1 mini with ESP-12F 80Mhz in qio mode (with dio it take a few ms more to boot possibly do to reading code and init data from the flash is slower).
GPIO 4 is used to measure time in the scope of the program execution. The time it takes to go to sleep is measured from the low edge of GPIO4 to the current drop due to deep sleep. As I mentioned is about 5-6ms to shutdown .
The code:

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

extern "C" {
#include "user_interface.h"
}
uint32_t rf_time;

RF_PRE_INIT() {
   //system_deep_sleep_set_option (RF_DISABLED);   // No RF cal on wake-up
  // 1: Vdd and TX power, 18 ms
  // 2: Vdd only, 2 ms
  // 3: Full cal, 200ms
  //system_phy_set_powerup_option (1);
  //system_phy_set_rfoption (RF_DISABLED);
  rf_time= millis();
}


void setup() {
    uint32_t t=millis();
    pinMode(4,OUTPUT);
    digitalWrite(4,HIGH);
    WiFi.mode(WIFI_STA);
    WiFi.config(IPAddress(192,168,1,5),IPAddress(192,168,1,1),IPAddress(255,255,255,0));
    WiFi.begin(ssid,pwd);
    while(WiFi.status() != WL_CONNECTED && millis()<10000) {
        delay(5);
    }
    uint32_t wifi_time=millis();
    Serial.begin(74880);
    delay(1); // Just to have clean serial output
    Serial.print("Started:[");
    Serial.print(ESP.getResetReason().c_str());
    Serial.printf("]%s/%s/rf_time:%d,boot_time:%d,W_time:%d\n",
                  ESP.getCoreVersion().c_str(),ESP.getSdkVersion(),rf_time,t,wifi_time);
    Serial.print("IP:"); Serial.print(WiFi.localIP());
    Serial.print("RSSI:"); Serial.println(WiFi.RSSI());
    // Got sleep
    digitalWrite(4,LOW);
    system_deep_sleep_set_option(RF_NO_CAL);
    system_deep_sleep_instant(30*1000*1000); 
    //ESP.deepSleep(2*1000000,RF_NOCAL,true);
    delay(1000);
}

Sample output:

--- Miniterm on /dev/cu.wchusbserial1410  74880,8,N,1 ---
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v614f7c32
~ld
�Started:[Deep-Sleep Wake]2_4_1/2.2.1(cfd48f3)/rf_time:24,boot_time:29,W_time:172
␀�:192.168.1.5RSSI:-68
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v614f7c32
~ld
kStarted:[Deep-Sleep Wake]2_4_1/2.2.1(cfd48f3)/rf_time:24,boot_time:29,W_time:172
␀�:192.168.1.5RSSI:-67
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v614f7c32
~ld
�Started:[Deep-Sleep Wake]2_4_1/2.2.1(cfd48f3)/rf_time:24,boot_time:29,W_time:203
␀�:192.168.1.5RSSI:-76
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v614f7c32
~ld
�Started:[Deep-Sleep Wake]2_4_1/2.2.1(cfd48f3)/rf_time:24,boot_time:29,W_time:168
␀�:192.168.1.5RSSI:-75
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v614f7c32
~ld
�Started:[Deep-Sleep Wake]2_4_1/2.2.1(cfd48f3)/rf_time:24,boot_time:29,W_time:172
␀�:192.168.1.5RSSI:-75
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v614f7c32
~ld
�Started:[Deep-Sleep Wake]2_4_1/2.2.1(cfd48f3)/rf_time:24,boot_time:29,W_time:173
␀�:192.168.1.5RSSI:-73
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v614f7c32
~ld
�Started:[Deep-Sleep Wake]2_4_1/2.2.1(cfd48f3)/rf_time:24,boot_time:29,W_time:278
␀�:192.168.1.5RSSI:-80
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v614f7c32
~ld
�Started:[Deep-Sleep Wake]2_4_1/2.2.1(cfd48f3)/rf_time:24,boot_time:29,W_time:177
␀�:192.168.1.5RSSI:-79
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v614f7c32
~ld
�Started:[Deep-Sleep Wake]2_4_1/2.2.1(cfd48f3)/rf_time:24,boot_time:29,W_time:223
␀�:192.168.1.5RSSI:-76
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v614f7c32
~ld
�Started:[Deep-Sleep Wake]2_4_1/2.2.1(cfd48f3)/rf_time:24,boot_time:29,W_time:1198
␀�:192.168.1.5RSSI:-77
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v614f7c32
~ld
�Started:[Deep-Sleep Wake]2_4_1/2.2.1(cfd48f3)/rf_time:24,boot_time:29,W_time:1157
␀�:192.168.1.5RSSI:-75
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v614f7c32
~ld
�Started:[Deep-Sleep Wake]2_4_1/2.2.1(cfd48f3)/rf_time:24,boot_time:29,W_time:168
␀�:192.168.1.5RSSI:-75
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v614f7c32
~ld
�Started:[Deep-Sleep Wake]2_4_1/2.2.1(cfd48f3)/rf_time:24,boot_time:29,W_time:1157
␀�:192.168.1.5RSSI:-77
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v614f7c32
~ld
�Started:[Deep-Sleep Wake]2_4_1/2.2.1(cfd48f3)/rf_time:24,boot_time:29,W_time:178
␀P:192.168.1.5RSSI:-74

Boot Time is consistent under 30ms and time to connect to wifi is about 200ms with static IP. There are come cases that wifi connection takes up to 1s. This is not due to the esp but the AP and the poor RSSI i'm getting (the AP is and old one, and ther is several walls in btw).

Prior to this fixes the boot time was 220ms and the time to connect to wifi was about 400. Also having in account that no instant deep sleep took another 200ms. A typical transaction with publih mqtt is 1s after wifi connection. The improvement is quite relevat:

Before:
220ms(boot) + 180ms(wifi connect) + 1000ms(mqtt) + 200ms (deepsleep) = 1600ms
Now:
30ms(boot) + 180ms(wifi connect) + 1000ms(mqtt) + 5ms (deepsleep instant)= 1250ms

thats 24% less time but also no current spike for Calibration that reduce average current so the battery gain will be even better.

With EspNow you as you avoid the costly wifi connection and mqtt transaction the improvements will be more noticeable in relative terms.

Thnks for your contribution.

Regards,

commented

With EspNow it takes ~120ms for everything: wake up, read BME280 and APDS9930, publish message and go to sleep again

~120ms is too long, I've now an ESP-Now sensor doing the wake-send-sleep cycle in less than 40ms. (though I don't have a scope so thats a guess including @ludiazv 's comment of 5-6ms for shutdown.

There is a bug in my ESP-Now example that a lot of people copy here where it does a WiFi.disconnect(), that takes about 80ms and doesn't seem necessary, so removing the line saves the time and it still seems to work fine.

I think WiFi.diconnect() can be removed if there are no stored credentials on the flash, otherwise the SDK will try to auto-connect to the last AP. This could cause problems with ESPNOW.

To be sure is best to erase totally the flash upon scketch upload.

commented

Thanks guys. For me the slowest part seems to be initializing and polling sensors via I2C, but that's irrelevant to this issue.

@torntrousers
It looks like you can do w/o with #include <ESP8266WiFi.h> in your example. It looks like it works just fine w/o and even less power.

#5056 is merged. Great work everyone!

So excited! Could we have #5052 too?

Also merged #5052 . Still need help figuring out the deepSleepMax thing, though.

commented

Hmmm, somehow it seems with this change one can't get any RF_CAL at all?
checked ludiazv's sketch with ESP.deepSleep(2*1000000, WAKE_RFCAL);
and didn't see any boot_time:218 taht I see w/o change

Hmm, I'll have a play around with it...

As @5chufti comments this fix breaks the RF_CAL option. It seems that rtc_reg[24]/rtc_reg[30] play a role in the initization of the RF after deepsleep. AFAIK this is not documented and it should be part of the sdk implementation. Does anyone understand what this registers do?

I will try to play also to see if there is a fix for this.

commented

It would also be interesting to hear from @igrr why it is necessary to interfere with espressifs startup procedure at all.
I expect the SDK functions system_deep_sleep*() to set all necessary parameters for wake-up that from physical wake-up until the start of user code everything runs in preset order w/o need for additional tinkering.

Why is it therefor necessary to set

system_phy_set_rfoption();

in user_rf_pre_init()?

Therefor I was very pushy to get real information about system_deep_sleep*() working in plain SDK setup ... not just that it is possible to achieve similar behaviour.

It seems difficult to work this out with out any doc on what the rtc reg 24 and 30 are supposed to be for.
Adding this to an sketch:

RF_PRE_INIT() {
    volatile uint32_t* rtc_reg = (volatile uint32_t*) 0x60001000;
    rtc_reg[24] &= 0xFFFF;
}

Appears to get RF_CAL to run again. But both rtc_reg[24] and rtc_reg[30] are xFFFFFFFF on wake up no matter what sleep mode was used to put the ESP to deepSleep.

I came late to the party and so I am having a hard time replicating what is ben reported. It would be helpful to have one common set of code against everyone is testing. This way if there are different results for some reason it can be nailed down why that is.
For example, there is set up time during the ESP boot for a state of GPIO to change, so timing the GPIO externally may not show the full story about the boot time. Same with the timers, there is a set up time and it is not a constant. I am set up with hardware to take accurate measurements if anyone if interested to put up the test bed code and more info what version of SDK I should run it with.
Next as a curiosity... when running ESPNOW it looks like the #include <ESP8266WiFi.h> is not necessary for the ESPNOW to work. Can anyone test or give an opinion on that? It works fine for me w/o and as a result I get faster boot up albeit only little. @torntrousers ?

@Ivoatme the sketch I use for timing an esp-now sensor is here: https://github.com/HarringayMakerSpace/ESP-Now/blob/master/espnow-sensor-timing/espnow-sensor-timing.ino

For me that outputs:

send_cb, send done, status = 0
Boot: 24 ms, setup: 28 ms, send: 28 ms, now 29 ms, going to sleep for 35 secs...

with slight variability in the 'now' time going to 30 or 31 ms sometimes.

Would be interesting to have someone with a scope do a complete plot of the power usage and timing of the entire wake-send-sleep cycle. Or also see if there are any other savings somewhere, maybe removing all the use of Serial?

Great example @torntrousers! One caveat, running at 160Mhz has no point here as the task is mainly IO waiting time. Have in mind that a esp (with RF disabled consume 20mA at 80Mhz but about 35mA at 160Mhz). To ilustrate the net effect, lets say that the gain of executing at full speed is 10m less time that running at 80Mhz. Then it would be detrimental for the battery life;

  1. 80Mhz -> 20mA* (30+10) / 1000 = 0,8 mA/sec
  2. 160Mhz -> 35mA* 30/1000 = 1.05 mA/sec
    (using second scale for readability)

as you can see the extra power consumed at 160 Mhz will offet the speed gain of 10ms.

The same argument affects the flash chip, it will consume more at 80Mhz. Here will depend on the actual chip and mesurement will be needed on your specific board. Also there cheap versions of the ESP12 that have trouble with 80Hz as they use low quality. I suposse that using QIO will be power neutral it only using a pair of addtional datalines to speak with the flash. The problem is that not all ESP boards out there implement QIO.

Good point @ludiazv . And trying now the faster speeds don't actually make much of a difference now anyway, i think when I tried them before it was with bigger sketch and rf_cal running.

Several observations here...

  1. the power "cost" in the above is ~ 8 mA/s
  2. with this version this solution can not be used when gating the power because only the subsequent transmissions (after the first power up) "behave" this way, so if you are transmitting only one reading per sleep cycle and the power is interrupted the power cost is significantly greater.
    Perhaps there is a way to save and retain the registers settings on power-up.
commented

RF_CAL seems to be working fine if any changes to rtc_reg are disabled completely. That's how user_rf_pre_init() looks in my setup:

void user_rf_pre_init()
{
    // *((volatile uint32_t*) 0x60000710) = 0;
    spoof_init_data = false;
    /*
    volatile uint32_t* rtc_reg = (volatile uint32_t*) 0x60001000;
    if((rtc_reg[24] >> 16) > 4) {
        rtc_reg[24] &= 0xFFFF;
        rtc_reg[30] = 0;
    }
    */

    system_set_os_print(0);
    int rf_mode = __get_rf_mode();
    if (rf_mode >= 0) {
        system_phy_set_rfoption(rf_mode);
    }
    __run_user_rf_pre_init();
}

All, I'm now a bit lost with regard to which code is best for low power, or which set up is best, etc. At this time I'd like to ask you for a PR with an example sketch for lowest power, so that we can include it as part of the repo, and use it as basis for enhancements to the core api. We can continue to discuss what works better, or in which cases, in that PR, adding comments to the sketch as appropriate, including why certain inits are needed.
Who can make the PR?

@devyte I'm happy to do a PR with an example sketch but not sure what type of thing you'd like? There's a short sketch up in this issue here that shows the time for getting to setup which shows if rf calibration is happening or not, is that the type of thing you'd like?

commented

@mailgpa just tested your suggestion with @ludiazv s sketch using ESP.deepSleep(2000000, WAKE_RFCAL)
and NO, it doesn't do correct RF_CAL at boot

⸮Started:[Deep-Sleep Wake]
Info: 00000000/2.2.1(cfd48f3)/rf_time:27,boot_time:67,W_time:238
IP:192.168.1.5
RSSI:-48
⸮⸮

unfortunately even using the diverse api functions in RF_PRE_INIT() does not affect the RF_CAL behaviour at startup in current 2.4.2

@torntrousers right now we have nothing, so any example you can add would help. More than one example, if there's more than one use case.

All, what is the status here? Leaving the requested examples aside, are there any code changes needed here?

Ok let me have a look over the weekend.

I think further investigation and discussion is needed here.
Removing milestone for now until the path forward is clarified.

Ran into this today. Arduino IDE 1.8.5 (I don't like being on the bleeding edge) and board file version 2.4.1. The following DOES work for me (with the affected ESP.deepSleep calls removed)

//If we get to here, we want to wake up and talk, but the radio might not be on. Only way to turn it on is to set a flag and go back to sleep.
  if (!rtcmem.RFon) {
    debugln("Reset for RF","");
    rtcmem.RFon = true;
    ESP.rtcUserMemoryWrite(0, (uint32_t*) &rtcmem, sizeof(rtcmem)); //write data to RTC memory so we don't loose it.
    //ESP.deepSleep(1, WAKE_NO_RFCAL); //deep sleep, wake right away with RF on, assume calibration not needed
    //ESP.deepSleep(1000 * MICROSECONDS, WAKE_RFCAL); //deep sleep, wake ASAP with RF on, assume calibration not needed
    //Can't use ESP.deepSleep call, see https://github.com/esp8266/Arduino/issues/3408
    system_deep_sleep_set_option(RF_NO_CAL);
    system_deep_sleep(1000000);
    }
//we are up and radio should be on.

@JamesNewton To confirm: you're saying it doesn't work with the ESP. deepSleep() call, but it does work with the direct sdk system_deep_sleep*() calls?

Yes... "The following DOES work for me (with the affected ESP.deepSleep calls removed)"

commented

can you elaborate on what exactly is working?

//ESP.deepSleep(1000 * MICROSECONDS, WAKE_RFCAL); //deep sleep, wake ASAP with RF on, assume calibration not needed

as both of these lines may not be working for a reason:

  1. deep sleep for 1µs is not working on newer sdk, a minimum of ??? is needed, I use 100.
  2. "WAKE_RFCAL" IS doing a rfcal, so not what is expected from comment

How on earth is it not clear? The lines commented out do NOT work, the lines in the program that are not commented out DO work.

commented

The ORIGINAL issue must have been corrected some time in the last year. It's hard to tell from this tangled mess of comments since the original issue (WAKE_NO_RF_CAL not working) seems to have been utterly ignored since ~August 2018, and everyone took off in other directions. I just tested the original issue with the code scrap from well above, and RF_NO_CAL is working fine. Some of you folks that have OTHER issues than WAKE_NO_RF_CAL not working, kindly untangle yourself from this particular issue and post your own, as it's a right mess of multiple issues at the moment.

Here's proof that the ORIGINAL issue is closed:
Deep Sleep WAKE_NO_RFCAL

Deep Sleep WAKE_RFCAL

(the top trace is the TX output)

and the code chunk posted about half-way up this thread * that I tested with:

#include <ESP8266WiFi.h>

void setup() {
  unsigned long ms = millis();
  Serial.begin(115200); Serial.println();
  Serial.print("Setup time:"); Serial.println(ms);
  delay(300);
//  ESP.deepSleep(1E3, WAKE_NO_RFCAL);
  ESP.deepSleep(1E3, WAKE_RFCAL);

}

void loop() {
}
  • 'thread' is being polite; this issue's 'thread' looks like a ball of yarn that a cat has had fun with.

@Tech-TX nice work untangling this.
Closing per previous comment due to original issue already fixed.