Skip to content

timed light sleep almost works with 2.4.0-rc1 on wemos d1 mini #3320

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
netprince17 opened this issue Jun 1, 2017 · 9 comments
Closed

timed light sleep almost works with 2.4.0-rc1 on wemos d1 mini #3320

netprince17 opened this issue Jun 1, 2017 · 9 comments

Comments

@netprince17
Copy link

Hardware

Hardware: wemos d1 mini
Core Version: 2.4.0-rc1

Description

I'm testing timed light-sleep on 2.4.0-rc1, I need to sleep about 15 seconds, which works, but then the board wakes up and delays an additional 15 seconds with the CPU active.

I am using a high precision usb power monitor (from yzx studio) to monitor when the board is truely in light sleep mode vs powered up. With a stopwatch I can verify the board goes into light-sleep mode for 15 seconds (about 7ma draw), then wakes up and delays an additional 15 seconds (about 22ma draw).

Seems this could be a bug in the delay procedure perhaps?

Settings in IDE

Module: Wemos d1 r2 & mini
Flash Size: 4m (3m spiffs)
CPU Frequency: 80Mhz
Flash Mode: (not sure where this setting is)
Flash Frequency: (not sure where this setting is)
Upload Using: Serial
Reset Method: (not sure where this setting is)

Sketch

/*
ESP8266 Blink by Simon Peter
Blink the blue LED on the ESP-01 module
This example code is in the public domain

The blue LED on the ESP-01 module is connected to GPIO1
(which is also the TXD pin; so we cannot use Serial.print() at the same time)

Note that this sketch uses LED_BUILTIN to find the pin with the internal LED
*/

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

// only if you want wifi shut down completely (doesn't seem to work)
// RF_MODE(RF_DISABLED);

void setup() {
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
Serial.begin(115200);

//WiFi.mode(WIFI_OFF);
wifi_set_sleep_type(LIGHT_SLEEP_T);
WiFi.forceSleepBegin();
delay (1000);
// ~22ma

}

void wake_cb() {
Serial.println("wakeup");
wifi_fpm_close();
WiFi.forceSleepBegin();
}

// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, LOW); // Turn the LED on (Note that LOW is the voltage level
// but actually the LED is on; this is because
// it is acive low on the ESP-01)
delay(1000); // Wait for a second
digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH

wifi_set_opmode_current(NULL_MODE);
wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
wifi_fpm_open();
wifi_fpm_set_wakeup_cb(wake_cb);
wifi_fpm_do_sleep(15000000);
delay (15001);
// ~7ma for 15 seconds, then ~22ma for 15 seconds (75ma for 15 seconds without forcesleepbegin in callback)

Serial.println("loop");
}

@vlast3k
Copy link

vlast3k commented Jun 2, 2017

i had simillar observation some time ago #1381 (comment)

@netprince17
Copy link
Author

Interesting, your bullet number 7 might explain why the delay function behaves this way? Does the delay function depend on millis()?

during light_sleep, the internal timer is not updated, and millis() increases just by several hundred milliseconds (e.g. after 15 sek seep)

@vlast3k
Copy link

vlast3k commented Jun 2, 2017 via email

@bertrandlo
Copy link

marking for check later, still need a workable timing light-sleep

@netprince17
Copy link
Author

netprince17 commented Jan 23, 2018

With the latest core (2.4.0) I re-ran my testing and updated my test code... Result is the same, clock slows during the light sleep, and delay depends on clock ticks so upon wakeup the delay has not passed...

Is there some other way to trigger sleep than using delay(light_sleep_ms+1)?

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

// only if you want wifi shut down completely (doesn't seem to work)
//RF_MODE(RF_DISABLED);

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
  Serial.begin(115200);
  
  WiFi.mode(WIFI_OFF);
  wifi_set_sleep_type(LIGHT_SLEEP_T);
  wifi_fpm_set_sleep_type (LIGHT_SLEEP_T);
  WiFi.forceSleepBegin();

  delay (3000);
  // ~22ma
  
}

void wake_cb() {
  wifi_fpm_close();
  WiFi.forceSleepBegin();
}

// the loop function runs over and over again forever
void loop() {
  Serial.println("awake");
  digitalWrite(LED_BUILTIN, LOW);   // Turn the LED on (Note that LOW is the voltage level
                                    // but actually the LED is on; this is because 
                                    // it is acive low on the ESP-01)
  delay(2000);                      // Wait for a second
  digitalWrite(LED_BUILTIN, HIGH);  // Turn the LED off by making the voltage HIGH
  Serial.println("sleeping");
  

  // NOTE: looks like timers are keeping us out of timed light sleep!!??
  extern os_timer_t *timer_list;
  while(timer_list != 0) {
    /*
    Serial.printf("address_current= %p\n", timer_list);
    Serial.printf("timer_expire= %u\n", timer_list->timer_expire);
    Serial.printf("timer_period= %u\n", timer_list->timer_period);
    Serial.printf("address_next= %p\n", timer_list->timer_next);
    Serial.printf("=============\n");
    */
    os_timer_disarm(timer_list);
    timer_list = timer_list->timer_next;
  }
    
  wifi_set_opmode_current(NULL_MODE);
  wifi_set_sleep_type(LIGHT_SLEEP_T);
  wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
  wifi_fpm_open();
  wifi_fpm_set_wakeup_cb(wake_cb);
  //wifi_fpm_do_sleep(0xFFFFFF);  // works but requires interupt to wake up
  wifi_fpm_do_sleep(15000 * 1000);
  delay (15001);
  // ~7ma for 15 seconds, then ~22ma for 15 seconds (75ma for 15 seconds without forcesleepbegin in callback)
  // because ticks slow dramatically during sleep, and delay uses ticks to know when its finished

    
  // works, but wipes memory
  //ESP.deepSleep(15000000);
}

@netprince17
Copy link
Author

netprince17 commented Jan 23, 2018

After re-reading this thread, I finally got some code to work:
#1381
#1381 (comment)

The trick is to output something to serial in the callback function, and then calling Serial.flush(). Doing that causes the delay() to be interrupted upon returning from the callback function. Dont know why...

Thanks to vlast3k for leaving some pointers in that comment.

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

// only if you want wifi shut down completely
RF_MODE(RF_DISABLED);   // if you dont need wifi, this has lowest wakeup power spike

void setup() {
  delay (3000);  // delay here helps with flashing after bad code

  pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
  Serial.begin(115200);
  
  WiFi.mode(WIFI_OFF);
  wifi_fpm_set_sleep_type (LIGHT_SLEEP_T);
  WiFi.forceSleepBegin();   // if you dont need wifi, ~22ma instead of ~75ma
}

void wakeup_cb() {
  wifi_fpm_close();
  WiFi.forceSleepBegin();  // if you dont need wifi, ~22ma instead of ~75ma
  
  // required here, otherwise the delay after sleep will not be interrupted, thanks vlast3k
  // see: #6 from https://github.com/esp8266/Arduino/issues/1381#issuecomment-279117473
  Serial.printf("wakeup_cb\n");
  Serial.flush();
}

// the loop function runs over and over again forever
void loop() {
  Serial.printf("awake\n");
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
  digitalWrite(LED_BUILTIN, HIGH);
  Serial.printf("\nsleeping\n");
  

  // For some reason, moving timer_list pointer to the end of the list lets us achieve light sleep
  //Serial.printf("--timers----\n");
  extern os_timer_t *timer_list;
  while(timer_list != 0) {
    /*
    Serial.printf("address_current= %p\n", timer_list);
    Serial.printf("timer_expire= %u\n", timer_list->timer_expire);
    Serial.printf("timer_period= %u\n", timer_list->timer_period);
    Serial.printf("address_next= %p\n", timer_list->timer_next);
    Serial.printf("------------\n");
    */

    // doing the actual disarm doesn't seem to be necessary, and causes stuff to not work
    //  os_timer_disarm(timer_list);
    timer_list = timer_list->timer_next;
  }
  Serial.flush();
  
    
  wifi_set_opmode_current(NULL_MODE);
  wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
  wifi_fpm_open();
  wifi_fpm_set_wakeup_cb(wakeup_cb);
  //wifi_fpm_do_sleep(0xFFFFFF);  // works but requires interupt to wake up
  wifi_fpm_do_sleep(15000 * 1000);
  delay (15001);
  
  // ~7ma for 15 seconds, then ~22ma for 15 seconds (75ma for 5 seconds without forcesleepbegin in callback)
  // because ticks slow dramatically during sleep, and delay uses ticks to know when its finished
  // (NOTE: inside the callback function, write and flush something to serial, and the delay() will be interrupted, thanks vlast3k)

  // works, but wipes memory
  //ESP.deepSleep(15000000);
}

@rastikw
Copy link

rastikw commented Sep 18, 2018

@netprince17 I tried your last sketch and even though it wakes up as expected, it does not go into light sleep (0.5mA), only modem sleep (16-20mA, depending on voltage). Using version core 2.4.2 and ESP-12S. Does it still work for you? Or should I try older core version? Thank you.

@Tech-TX
Copy link
Contributor

Tech-TX commented Jan 29, 2020

netprince17's code does work when you remove the WiFi.forceSleepBegin(); from the callback. It's the only example of Timed Light Sleep I'd found that actually works with the current git, so I've included the essential elements from his example in my Low-Power demo, #6989

@devyte
Copy link
Collaborator

devyte commented Feb 2, 2020

Closing per previous comment.

@devyte devyte closed this as completed Feb 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants