-
Notifications
You must be signed in to change notification settings - Fork 13.3k
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
Comments
Here's what I currently have, it runs, but does not go to Light_sleep.
|
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. |
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, |
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? |
Modem sleep is working an implemented in staring / git. WiFi.forceSleepBegin(); and to enable WiFi again: WiFi.forceSleepWake(); more info starting here: |
@stevescot yes exactly what i am looking for. I can't find somebody that got this to work yet. |
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:
|
That sounds great - will try it... |
Note: sleep in AP mode is not possible, since the connected client can send something to any time. |
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, ) |
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. |
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? |
I still don't get it, how can light_sleep work without having the GPIO On Mon, Jan 11, 2016 at 12:47 PM, WereCatf [email protected] wrote:
|
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. |
@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. |
@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();
I used it in my ESP8266 with DHT22 IoT client project. |
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); #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 |
@ pigglet thanks for posting the code for light sleep with GPIO. Could you please let me know regarding Regards, kk |
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);
} |
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? |
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. |
@mikeyoyoyo |
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 |
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 |
You couldn't wake it from light sleep or deep sleep? If light what was your code? |
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? |
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. |
@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 |
@mikeyoyoyo It seems to work for you w/o being connected to an AP, right? |
@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. |
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 |
Hi @davesherler, I'll be honest I haven't used it in a while. When I was I
only ever tested with a switch and a pull up/pull down resistor. Probably
used 5k of 10k, doesn't really matter.
Were you able to verify the low pulse?
On 27 Oct. 2017 12:51 am, "davescherler" <[email protected]> wrote:
Hey @mikeyoyoyo <https://github.com/mikeyoyoyo> and @torntrousers
<https://github.com/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!
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1381 (comment)>,
or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ALPNydXw9DFC2AK8PiuaR-cRT3oS3Pdpks5swI5pgaJpZM4HAMqu>
.
|
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. |
Add a "one shot ic" in series with the RTC output (and a couple of inverters) |
I managed to get some timed light-sleep code working... its not pretty but it works, tested with 2.4.0 |
esp8266/Arduino#1381 torntrousers proposed this, which seems to work (RST not connected to anything).
Apart from GPIO waking, 2.4.1 and 2.4.2 has issues with light sleep. But you also need to adjust your router's DTIM. Extended explanation is here: |
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. |
long time no see this issue. Thanks for the work. |
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? |
May I know how the modem sleep mode works? along with code? |
Hi, This works for me and i'm using Wemos D1 :3, I hope it works for you !
El mié, 12 may 2021 a las 1:25, aditya-rotithor ***@***.***>)
escribió:
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?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#1381 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AFKMHUR3VGKXJJ2EEYG6UL3TNI3PPANCNFSM4BYAZKXA>
.
#include <ESP8266WiFi.h>
extern "C" {
#include "gpio.h"
}
extern "C" {
#include "user_interface.h"
}
const char* ssid = "*****";
const char* password = "**";
WiFiClient client;
void setup() {
Serial.begin(115200);
Serial.print("initializing GPIOs");
gpio_init();
pinMode(D7, INPUT); // this pin is connected to the PIR sensor.
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
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();
while(digitalRead(D7)== HIGH){
Serial.println("Motion detected!");
delay(500);
}
}
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(D7), GPIO_PIN_INTR_HILEVEL); //set the interrupt to look for HIGH pulses on Pin 0 (the PIR).
wifi_fpm_open();
delay(1000);
wifi_fpm_set_wakeup_cb(wakeupFromMotion); //wakeup callback
wifi_fpm_do_sleep(0xFFFFFFF);
delay(1000);
}
void wakeupFromMotion(void) {
wifi_set_sleep_type(NONE_SLEEP_T);
gpio_pin_wakeup_disable();
wifi_fpm_close();
wifi_set_opmode(STATION_MODE);
wifi_station_connect();
Serial.println("Woke up from sleep");
}
|
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.
The text was updated successfully, but these errors were encountered: