Skip to content

LIGHT_SLEEP HOW ? #1381

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

Closed
donnib opened this issue Jan 7, 2016 · 99 comments
Closed

LIGHT_SLEEP HOW ? #1381

donnib opened this issue Jan 7, 2016 · 99 comments
Assignees
Milestone

Comments

@donnib
Copy link

donnib commented Jan 7, 2016

Hi,
How is it possible to light sleep with arduino framework on the ESP8266, i know how to deepsleep and it works but i am interested to do LIGHT_SLEEP so i can benefit from "low power" equal to 0.5mA and have GPIO wake up enabled with gpio_pin_wakeup_enable.

I can't seem to find examples how to do this, anyone tried it ?

donnib

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

@stevescot
Copy link

Here's what I currently have, it runs, but does not go to Light_sleep.


#include "ESP8266WiFi.h"
#include "gpio.h"
extern "C" {
#include "user_interface.h"
  uint16 readvdd33(void);
  bool wifi_set_sleep_type(sleep_type_t);
  sleep_type_t wifi_get_sleep_type(void);
}
bool sleep = false;

int switchPin = 2;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("before Sleep");
  goToLightSleep();
  Serial.println("Woken up");
}

void loop() {
  // put your main code here, to run repeatedly:

}

void goToLightSleep()
{
  if (!sleep)
  {
    Serial.println("switching off Wifi Modem and CPU");
    //stop any clients
    ///thisclient.stop();
    delay(1000);
    wifi_set_sleep_type(LIGHT_SLEEP_T);
    WiFi.disconnect();
    WiFi.mode(WIFI_OFF);
    // how do we call this: 
    //gpio_pin_wakeup_enable(GPIO_ID_PIN(switchPin),GPIO_PIN_INTR_NEGEDGE);
    wifi_fpm_open();
    wifi_fpm_do_sleep(26843455);
    //if(WiFi.forceSleepBegin(26843455)) sleep = true;
  }
}

@antelder
Copy link

antelder commented Jan 8, 2016

From what i understand light sleep is on by default but only happens when the ESP is in station mode and connected to an access point. The default mode is WIFI_AP_STA so you need to call WiFi.mode(WIFI_STA) and then connect to an access point. I did test this out and it did seem to work and reduce power consumption to a bit less than 1 mA during inactivity, but that was quite a while back now and i've not verified it still works with the lastest ESP/Arduino code and SDK.

@stevescot
Copy link

antelder - I think you might be talking about modem_sleep where power use goes down to 20mA, - that is on by default but has no effect for me, so I force modem sleep when I don't need wifi.

Light_sleep requires a pin interrupt to wake it, and switches off the CPU and WiFi, so it can't wake itself,

http://bbs.espressif.com/viewtopic.php?t=133

@antelder
Copy link

antelder commented Jan 8, 2016

I don't think so but i admit all this area can be confusing and is not well documented so i may be mistaken. However, i'm pretty sure i've tried both those and what i described above is how i got light sleep to work and the power consumption was matching what they say it should be at a bit under 1 mA. Where have you seen it said that light sleep requires a pin interrupt to wake up?

@Links2004
Copy link
Collaborator

Modem sleep is working an implemented in staring / git.
usage:
when you want to sleep (disable WiFi):

WiFi.forceSleepBegin();

and to enable WiFi again:

WiFi.forceSleepWake();

more info starting here:
#460 (comment)
#460

@donnib
Copy link
Author

donnib commented Jan 8, 2016

@stevescot yes exactly what i am looking for. I can't find somebody that got this to work yet.

@torntrousers
Copy link
Contributor

I dug up the old sketch i had for testing light sleep and tried it again with the current 2.0.0 release. WIth this sketch light sleep definately only seems to kick in when in station mode and Wifi is connected and i see a minimum current of about 1 mA. Its a bit hard to see the current use on a multimeter as the current dances around (which is what you'd expect with light sleep, right?, as it keeps waking up every 300 milliseconds or so) but its most of the time showing well under 10mA:

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

const char* ssid = "BTHub5-72W5";
const char* password = "xxxxxxxxxx";

void setup() {
  Serial.begin(115200);
  Serial.println();
}

void loop() {

  initWifi();

  Serial.println("Light sleep:");
  wifi_set_sleep_type(LIGHT_SLEEP_T);
  doDelays();

  Serial.println("None sleep:");
  wifi_set_sleep_type(NONE_SLEEP_T);
  doDelays();

  WiFi.disconnect();
  Serial.print("WiFi disconnected, IP address: "); Serial.println(WiFi.localIP());
  Serial.println("Light sleep:");
  wifi_set_sleep_type(LIGHT_SLEEP_T);
  doDelays();

}

void doDelays() {
  Serial.println("Yield for 20 sec");
  long endMs = millis() + 20000;
  while (millis() < endMs) {
     yield();
  }

  Serial.println("Delay for 20 sec");
  delay(20000);
}

void initWifi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while ((WiFi.status() != WL_CONNECTED)) {
     delay(500);
     Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi connected, IP address: "); Serial.println(WiFi.localIP());
}

@stevescot
Copy link

That sounds great - will try it...

@Links2004
Copy link
Collaborator

Note: sleep in AP mode is not possible, since the connected client can send something to any time.
in STA mode the WiFi standard allows the client to sleep (the ESP)

@stevescot
Copy link

Ran this script findings were:

with light_sleep, when delay is called the modem, and cpu will shut down (going down to 1mA and below for small periods between beacons, )
however - the yield time shows 70mA

@stevescot
Copy link

Setting to modem_sleep - still when delay is called then power drops to 20mA, given that sleep only happens when you have called delay (then you are not using the CPU)- no reason not to set light sleep.

@WereCatf
Copy link
Contributor

I am sorry for butting in on the conversation, but I would also be interested in learning how to make use of light-sleep. I just did some testing I can get modem-sleep to work just fine, but light-sleep only works when the ESP is actively connected to the WIFI-network -- I can't get light-sleep to work if I disconnect from the network.

If the ESP is connected to the network the current-draw keeps jumping up and down during delay() (it momentarily drops well below 10mA, so it is definitely working at times) and overall current-draw won't be anywhere near Espressif's claims. On the other hand, disconnecting from the network and forcing modem-sleep works fine -- current-draw stays stable <17mA during delay(). Disconnecting from the network and trying to enter light-sleep either draws current as if the was no power-management at all enabled, ie. >50mA or current-draw stays at <17mA if I force modem-sleep after disconnect.

Is it even possible to get light-sleep to work when disconnected so as to get power-draw down during longer periods of sleep?

@donnib
Copy link
Author

donnib commented Jan 11, 2016

I still don't get it, how can light_sleep work without having the GPIO
enable wake ? In the manual
http://russ.russmathis.com/wp-content/uploads/2015/09/9B-ESP8266__Sleep__Function-Description__EN_v1.0.pdf
it is stated that the CPU is in suspend and the clock is off so one need to
wake up the device with GPIO out of light_sleep or ?

On Mon, Jan 11, 2016 at 12:47 PM, WereCatf [email protected] wrote:

I am sorry for butting in on the conversation, but I would also be
interested in learning how to make use of light-sleep. I just did some
testing I can get modem-sleep to work just fine, but light-sleep only works
when the ESP is actively connected to the WIFI-network -- I can't get
light-sleep to work if I disconnect from the network.

If the ESP is connected to the network the current-draw keeps jumping up
and down during delay() and overall current-draw won't be anywhere near
Espressif's claims. On the other hand, disconnecting from the network and
forcing modem-sleep works fine -- current-draw stays stable <17mA during
delay(). Disconnecting from the network and trying to enter light-sleep
either draws current as if the was no power-management at all enabled, ie.

50mA or current-draw stays at <17mA if I force modem-sleep after
disconnect.

Is it even possible to get light-sleep to work when disconnected so as to
get power-draw down during longer periods of sleep?


Reply to this email directly or view it on GitHub
#1381 (comment).

@stevescot
Copy link

Yeah that confused me - my assumption is that light sleep as implemented by the core code uses the real-time clock to do an interrupt - so it is not running code and not using WiFi during these periods. However if you manually put the chip into light sleep then you will need to generate an interrupt to wake. That is all empirical - haven't seen documents to tell me that its just what seems to make sense.

@WereCatf
Copy link
Contributor

@donnib: The PDF says "Under the light-sleep mode, the CPU will not respond to the signal and interrupt from the peripheral hardware interface under the pause state. Therefore, the ESP8266 need to be waked up via external GPIO, and the wake process is less than 3 ms."

I read that as them saying that any interrupts you've attached to GPIO-pin state-changes won't work under light-sleep, but you can designate one GPIO-pin that the ESP will monitor in order to wake up from light-sleep and then it will be able to handle those interrupts. Internal mechanisms based on WIFI and RTC, however, will keep running and working even during light-sleep.

My interpretation may be completely off the base, but that's how I read it.

@mihino
Copy link

mihino commented Jan 16, 2016

@torntrousers Thanks! I've spent lot of time to lower current draw by LIGHT_SLEEP_T and the trick is to NOT use WiFi.disconnect();
finally my working the code is:

// Required for LIGHT_SLEEP_T delay mode
extern "C" {
#include "user_interface.h"
}

...


    //WiFi.disconnect(); // DO NOT DISCONNECT WIFI IF YOU WANT TO LOWER YOUR POWER !
    wifi_set_sleep_type(LIGHT_SLEEP_T);
    delay(20000); // 20s

I used it in my ESP8266 with DHT22 IoT client project.

@pigglet
Copy link

pigglet commented Feb 5, 2016

After some head scratching, many many cups of tea and some beer this is my implementation of a stable mA light sleep with gpio_pin_wakeup_enable(GPIO_ID_PIN(1), GPIO_PIN_INTR_HILEVEL);
uses staring / git. for WiFi.forceSleepBegin();

#include  <ESP8266WiFi.h>
//include  ESP8266WiFi.h needed doesnt show up on post code
extern "C" {
  #include "e:/gpio.h" //change to where you have saved gpio.h listed below
}
extern "C" {
  #include "user_interface.h"
}
const char* ssid = "SKY8606B";
const char* password = "*******";
int val = 0;

WiFiClient client;
void setup() {
  // put your setup code here, to run once:
pinMode(5, INPUT);           // set pin to input
digitalWrite(5, LOW);       // turn off pullup resistors

Serial.begin(115200);
delay(10);

WiFi.begin(ssid, password);

Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
//gpio_pin_wakeup_disable();
gpio_pin_wakeup_enable(GPIO_ID_PIN(1), GPIO_PIN_INTR_HILEVEL);
wifi_set_sleep_type(LIGHT_SLEEP_T);
}

void loop() {
  // put your main code here, to run repeatedly:
val = digitalRead(5);
while (val == 1){
  // do something repetitive
Serial.println("Pin 5 high"); 
delay (20000);
}
WiFi.forceSleepBegin();
delay(20000); // 20s
//ESP.deepSleep(60000000, WAKE_RF_DEFAULT); // Sleep for 60 seconds
}

Code needed for gpio_pin_wakeup_enable(GPIO_ID_PIN(1), GPIO_PIN_INTR_HILEVEL); needs to be saved as gpio.h

/*
 * copyright (c) Espressif System 2010
 *
 */

#ifndef _GPIO_H_
#define _GPIO_H_

#define GPIO_PIN_ADDR(i) (GPIO_PIN0_ADDRESS + i*4)

#define GPIO_ID_IS_PIN_REGISTER(reg_id) \
    ((reg_id >= GPIO_ID_PIN0) && (reg_id <= GPIO_ID_PIN(GPIO_PIN_COUNT-1)))

#define GPIO_REGID_TO_PINIDX(reg_id) ((reg_id) - GPIO_ID_PIN0)

typedef enum {
    GPIO_PIN_INTR_DISABLE = 0,
    GPIO_PIN_INTR_POSEDGE = 1,
    GPIO_PIN_INTR_NEGEDGE = 2,
    GPIO_PIN_INTR_ANYEDGE = 3,
    GPIO_PIN_INTR_LOLEVEL = 4,
    GPIO_PIN_INTR_HILEVEL = 5
} GPIO_INT_TYPE;

#define GPIO_OUTPUT_SET(gpio_no, bit_value) \
    gpio_output_set((bit_value)<<gpio_no, ((~(bit_value))&0x01)<<gpio_no, 1<<gpio_no,0)
#define GPIO_DIS_OUTPUT(gpio_no)    gpio_output_set(0,0,0, 1<<gpio_no)
#define GPIO_INPUT_GET(gpio_no)     ((gpio_input_get()>>gpio_no)&BIT0)

/* GPIO interrupt handler, registered through gpio_intr_handler_register */
typedef void (* gpio_intr_handler_fn_t)(uint32 intr_mask, void *arg);


/*
 * Initialize GPIO.  This includes reading the GPIO Configuration DataSet
 * to initialize "output enables" and pin configurations for each gpio pin.
 * Must be called once during startup.
 */
void gpio_init(void);

/*
 * Change GPIO pin output by setting, clearing, or disabling pins.
 * In general, it is expected that a bit will be set in at most one
 * of these masks.  If a bit is clear in all masks, the output state
 * remains unchanged.
 *
 * There is no particular ordering guaranteed; so if the order of
 * writes is significant, calling code should divide a single call
 * into multiple calls.
 */
void gpio_output_set(uint32 set_mask,
                     uint32 clear_mask,
                     uint32 enable_mask,
                     uint32 disable_mask);

/*
 * Sample the value of GPIO input pins and returns a bitmask.
 */
uint32 gpio_input_get(void);

/*
 * Set the specified GPIO register to the specified value.
 * This is a very general and powerful interface that is not
 * expected to be used during normal operation.  It is intended
 * mainly for debug, or for unusual requirements.
 */
void gpio_register_set(uint32 reg_id, uint32 value);

/* Get the current value of the specified GPIO register. */
uint32 gpio_register_get(uint32 reg_id);

/*
 * Register an application-specific interrupt handler for GPIO pin
 * interrupts.  Once the interrupt handler is called, it will not
 * be called again until after a call to gpio_intr_ack.  Any GPIO
 * interrupts that occur during the interim are masked.
 *
 * The application-specific handler is called with a mask of
 * pending GPIO interrupts.  After processing pin interrupts, the
 * application-specific handler may wish to use gpio_intr_pending
 * to check for any additional pending interrupts before it returns.
 */
void gpio_intr_handler_register(gpio_intr_handler_fn_t fn, void *arg);

/* Determine which GPIO interrupts are pending. */
uint32 gpio_intr_pending(void);

/*
 * Acknowledge GPIO interrupts.
 * Intended to be called from the gpio_intr_handler_fn.
 */
void gpio_intr_ack(uint32 ack_mask);

void gpio_pin_wakeup_enable(uint32 i, GPIO_INT_TYPE intr_state);

void gpio_pin_wakeup_disable();

void gpio_pin_intr_state_set(uint32 i, GPIO_INT_TYPE intr_state);

#endif // _GPIO_H_

The reason for setting gpio_pin_wakeup_enable(GPIO_ID_PIN(1), for pin 5
http://esp8266.co.uk/tutorials/introduction-to-the-gpio-api/
Yours pigglet

@koravadi
Copy link

@ pigglet thanks for posting the code for light sleep with GPIO. Could you please let me know regarding
a. do we need to keep polling the GPIO pin to check the IO status?
b. link http://esp8266.co.uk/tutorials/introduction-to-the-gpio-api/ is not working
c. The GPIO code looks like part of lib, will there be a conflict if we use another gpio.h file in our project? "copyright (c) Espressif System 2010"
d. In my application I am developing I want to be continuously stay in light sleep mode <1-2 mA current and wakeup with MQTT message or GPIO level high, please advice how it could be achieved?

Regards, kk

@mikeyoyoyo
Copy link

For anyone else still wondering, the above posters code didn't work for me. I was however able to get light sleep working with a button interrupt for wake up, current draw dropped to 0 mA on my bench power supply. The gpio.h the above poster provided is exactly the same as the one provided in the ESP8266 Arduino library so shouldn't need to save your own.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

extern "C" {
  #include "gpio.h"
}

extern "C" {
  #include "user_interface.h"
}
void setup()
{
   /* connect to WiFi/normal setup stuff */

  gpio_init(); // Initilise GPIO pins
  wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); // set sleep type, the above posters wifi_set_sleep_type() didnt seem to work for me although it did let me compile and upload with no errors 
}

void loop()
{
     /* do whatever you want */

    gpio_pin_wakeup_enable(GPIO_ID_PIN(2), GPIO_PIN_INTR_LOLEVEL); // GPIO_ID_PIN(2) corresponds to GPIO2 on ESP8266-01 , GPIO_PIN_INTR_LOLEVEL for a logic low, can also do other interrupts, see gpio.h above
    wifi_fpm_open(); // Enables force sleep
    wifi_fpm_do_sleep(0xFFFFFFF); // Sleep for longest possible time
 }


}

The WiFi.forceSleepBegin() function seems to set the sleep type to MODEM_SLEEP_T which would explain why people have had trouble getting into light sleep. (from ...AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.1.0\libraries\ESP8266WiFi\src\ESP8266WiFiGeneric.cpp)

bool ESP8266WiFiGenericClass::forceSleepBegin(uint32 sleepUs) {
    _forceSleepLastMode = getMode();
    if(!mode(WIFI_OFF)) {
        return false;
    }

    if(sleepUs == 0) {
        sleepUs = 0xFFFFFFF;
    }

    wifi_fpm_set_sleep_type(MODEM_SLEEP_T);
    wifi_fpm_open();
    return (wifi_fpm_do_sleep(sleepUs) == 0);
}

@TomTom101
Copy link

Do you know whether it restarts the whole device on wakeup like deep sleep does or does it continue in the loop()? I would assume keeping a wireless connection does not work during light sleep, right?

@mikeyoyoyo
Copy link

It actually does keep the wireless connection and doesn't restart, just continues in the loop(). I had it sending UDP packets on button press (same GPIO pin that woke up the device) and it didn't need to reset or reconnect.

@koravadi
Copy link

koravadi commented Mar 8, 2016

@mikeyoyoyo
Is it possible to make it light sleep till the device get MQTT message or interrupt triggered?

@mikeyoyoyo
Copy link

I haven't tried but the documentation would imply not, "Under the light-sleep mode, the CPU will not respond to the signal and interrupt from the peripheral hardware
interface under the pause state. Therefore, the ESP8266 need to be waked up via external GPIO,". (from Sleep_Function_Description_V1 http://espressif.com/sites/default/files/documentation/9b-esp8266_sleep_function_description_en_v1.0.pdf)

@TomTom101
Copy link

Not much luck for me, I can get it to sleep, but it won't wake up on the designated pin (GPIO4, made sure with an LED that I was using the correct one), not on GPIO_PIN_INTR_LOLEVEL or GPIO_PIN_INTR_HILEVEL or …ANY
GPIO2 and CH_PD are connected as well as RESET and GPIO16 which is supposedly required to enable deep_sleep (which seems to work, although I can't really say that waking up from deep sleep is any faster than a "cold start", it runs through setup() as well).

@mikeyoyoyo
Copy link

You couldn't wake it from light sleep or deep sleep? If light what was your code?

@TomTom101
Copy link

I realized I also gave up on deep sleep some time ago and are actually powering down. So the restart is no surprise.

I slightly changed to code above to this:

void setup() {
  Serial.write("Setup!");
  // Edited to what code really looks like in reply to @mikeyoyoyo 
  gpio_init();
  wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); 
}

void loop() {
  sleep();
  delay(100);
  Serial.write("Woke up!");
}

void sleep()
{
    wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); 
    gpio_pin_wakeup_enable(GPIO_ID_PIN(4), GPIO_PIN_INTR_HILEVEL); // or LO/ANYLEVEL, no change
    wifi_fpm_open(); 
    wifi_fpm_do_sleep(0xFFFFFFF);
 }

Without the delay in the loop, I saw continuous writes to Serial which reminded me that I read somewhere that the CPU keeps going for a few more cycles after being put to sleep. With the delay, I don't get to see the "woke up" message anymore and I assume real sleep. Then however, it neither will wake up when I pull up Pin4 to 3.3V.

So if it needs to be sent to sleep in a loop() continuously, this seems strange and I don't understand why you still saw 0mA.

Can you confirm the loop() does in fact stop, without a delay() on the first call to wifi_fpm_do_sleep() in your case?

@mikeyoyoyo
Copy link

Did you set

wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);

anywhere?

I tried your code, it wouldn't compile unless I moved sleep() above loop() after I did, it just seemed to make my chip reset until I added a delay before the sleep() function in loop, but otherwise this worked (I used gpio 2 and low level though)

extern "C" {
  #include "gpio.h"
}

extern "C" {
  #include "user_interface.h"
}

void setup() {
  Serial.begin(115200);
  delay(10);
  Serial.write("Setup!");
  wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
}

void sleep()
{
    gpio_pin_wakeup_enable(GPIO_ID_PIN(2), GPIO_PIN_INTR_LOLEVEL); // or LO/ANYLEVEL, no change
    wifi_fpm_open(); 
    wifi_fpm_do_sleep(0xFFFFFFF);
}

void loop() {
  delay(1000);
  sleep();
  delay(100);
  Serial.write("Woke up!");
}

And yes if I removed the delay after sleep() it would still execute Serial.write("Woke up!"); before it went to sleep.

@TomTom101
Copy link

@mikeyoyoyo Thanks! That was a sloppy job of mine, I did not copy and paste real code but wrote it on the fly from memory; I basically put your code from loop() in a separate function and added Serial.write()s and delay().

In your example, there's no more gpio_init() – maybe I'll try it without!

@TomTom101
Copy link

@Yoshi20 writes in #557:

The problem now is, that light sleep won't be activated unless the ESP8266 is connected to a WLAN (or was connected once -> it seems to save the ssid and the ssid-pw internaly!)

@mikeyoyoyo It seems to work for you w/o being connected to an AP, right?

@devyte
Copy link
Collaborator

devyte commented Oct 19, 2017

@igrr from looking at the current code base, I see that there is a way to set the sleep mode to light-sleep, but from reading the Espressif docs, I suspect that means "automatic sleep". When doing a forced sleep, the current code forces modem-sleep.
Does the code propsed in this discussion make sense?

@devyte devyte added the waiting for feedback Waiting on additional info. If it's not received, the issue may be closed. label Oct 19, 2017
@davescherler
Copy link

Hey @mikeyoyoyo and @torntrousers it's been nearly a year since I last posted but I'm hoping you guys are able to help me out with a similar issue. So my project is going on like 10 months and working perfectly. Much thanks to the many contributors to this thread! But now I want to make some hardware adjustments and wake up my ESP from light sleep using a alarm-based interrupt generated from a DS3231 real time clock. When the alarm is asserted, its active-low SQW/INT pin is supposed to produce a logic 0 pulse. So what that means for this thread is that I need to go from using gpio_pin_wakeup_enable(GPIO_ID_PIN(12), GPIO_PIN_INTR_HILEVEL); to gpio_pin_wakeup_enable(GPIO_ID_PIN(12), GPIO_PIN_INTR_LOLEVEL);. The thing is, the LOLEVEL just isn't working. The ESP goes to sleep but never wakes up. It seems like you guys have had success using LOLEVEL and getting the ESP to wake up. Are you using pullup resistors? If so what value? And what is triggering the pulse? External hardware or some software based event? I'd appreciate your input!

@mikeyoyoyo
Copy link

mikeyoyoyo commented Oct 27, 2017 via email

@davescherler
Copy link

Hey @mikeyoyoyo thanks for the reply. That helps. I was able to confirm the low pulse. But unfortunately, I also confirmed that what I've been working on is programmatically impossible - at least with my current skills and knowledge. I've been trying to wake up my ESP using the alarm function of my RTC, since the RTC can be configured to output a low pulse when the alarm is asserted. The thing is, you have to clear the alarm register every time its asserted or else the RTC constantly outputs a low pulse, i.e. there's no momentary "pulse". So once my ESP goes to sleep, the pin thats monitoring for the low pulse goes low but just stays low because I can't clear the alarm flag. I'm glad I at least understand my problem now but bummed cause I'm sort of back at square one. Anyway, I appreciate you following up.

@drmpf
Copy link

drmpf commented Oct 27, 2017

Add a "one shot ic" in series with the RTC output (and a couple of inverters)
If you only want a low pulse, add a capacitor coupling (or another one shot)
Of course these will use more power :-(
the LTC6993 uses 70uA

@netprince17
Copy link

I managed to get some timed light-sleep code working... its not pretty but it works, tested with 2.4.0

#3320

mauriciojost added a commit to mauriciojost/botino-arduino that referenced this issue Aug 24, 2018
esp8266/Arduino#1381

torntrousers proposed this, which seems to work (RST not connected to
anything).
@EUA
Copy link

EUA commented Oct 5, 2018

Apart from GPIO waking, 2.4.1 and 2.4.2 has issues with light sleep.
Use 2.4.0 and WiFi.setSleepMode(WIFI_LIGHT_SLEEP); command.
When you issue delay(); you will see your device enter LIGHT_SLEEP.

But you also need to adjust your router's DTIM. Extended explanation is here:
#4485 (comment)

@devyte
Copy link
Collaborator

devyte commented Oct 9, 2018

Light sleep is now reported to work correctly with #5210 . In addition, you can set DTIM if desired, but that could miss broadcasts. See Espressif docs quoted in the comments in the PR for details.

@devyte devyte closed this as completed Oct 9, 2018
@devyte devyte added type: bug staged-for-release component: SDK and removed waiting for feedback Waiting on additional info. If it's not received, the issue may be closed. labels Oct 9, 2018
@devyte devyte added this to the 2.5.0 milestone Oct 9, 2018
@bertrandlo
Copy link

long time no see this issue. Thanks for the work.

@Rosa2905
Copy link

Hey Mike - thanks for the reply. I have good news! On a whim, I decided to use some of Simonliu009 callback code and everything seems to be working as I expected. I think what I wasn't putting together is that I needed to declare wifi_fpm_set_wakeup_cb(some_wakeup_function); before I called wifi_fpm_do_sleep(0xFFFFFFF); so that it knows what to do when the interrupt registers on the Pin. Now that I type that out it's like, duh, but I guess I had a hard time making sense of the comments in the gpio header file. Anyway, I wanted to share my successful code since I'm able to put the ESP to sleep, and wake it up using a PIR sensor, without having to pull any gpio's up or down, or have RST connected to 16 or EN. So a pretty simple hardware solution to use as a starting place for others. Thanks to everyone for helpful thread! I learned a lot.

#include <ESP8266WiFi.h

extern "C" {
#include "gpio.h"
}
extern "C" {
#include "user_interface.h"
}

const char* ssid = "myNetwork";
const char* password = "myPassword";
WiFiClient client;

void setup() {
  Serial.begin(115200);
  Serial.print("initializing GPIOs");
  gpio_init();
  pinMode(0, INPUT); // this pin is connected to the PIR sensor.
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  delay(1000);
}

void loop() {
  Serial.println("Ready to go into light sleep...");
  delay(1000);
  Serial.println("3...");
  delay(1000);
  Serial.println("2...");
  delay(1000);
  Serial.println("1...");
  sleepNow();
}

void sleepNow() {
  Serial.println("going to light sleep...");
  wifi_station_disconnect();
  wifi_set_opmode(NULL_MODE);
  wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); //light sleep mode
  gpio_pin_wakeup_enable(GPIO_ID_PIN(0), GPIO_PIN_INTR_HILEVEL); //set the interrupt to look for HIGH pulses on Pin 0 (the PIR).
  wifi_fpm_open();
  delay(100);
  wifi_fpm_set_wakeup_cb(wakeupFromMotion); //wakeup callback
  wifi_fpm_do_sleep(0xFFFFFFF); 
  delay(100);
}

void wakeupFromMotion(void) {
  wifi_fpm_close;
  wifi_set_opmode(STATION_MODE);
  wifi_station_connect();
  Serial.println("Woke up from sleep");
}

Hi, sorry any idea about why only woke up one time? I've tried to copy parts from the setup to "initialize again", but it keeps just working one time (wake up) , I'm using a cable in (D5-14) to switch G - V, not a button, do you think that can be the problem?

@aditya-rotithor
Copy link

I am sorry for butting in on the conversation, but I would also be interested in learning how to make use of light-sleep. I just did some testing I can get modem-sleep to work just fine, but light-sleep only works when the ESP is actively connected to the WIFI-network -- I can't get light-sleep to work if I disconnect from the network.

If the ESP is connected to the network the current-draw keeps jumping up and down during delay() (it momentarily drops well below 10mA, so it is definitely working at times) and overall current-draw won't be anywhere near Espressif's claims. On the other hand, disconnecting from the network and forcing modem-sleep works fine -- current-draw stays stable <17mA during delay(). Disconnecting from the network and trying to enter light-sleep either draws current as if the was no power-management at all enabled, ie. >50mA or current-draw stays at <17mA if I force modem-sleep after disconnect.

Is it even possible to get light-sleep to work when disconnected so as to get power-draw down during longer periods of sleep?

May I know how the modem sleep mode works? along with code?

@Rosa2905
Copy link

Rosa2905 commented May 13, 2021 via email

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

No branches or pull requests