Deep Sleep Summary



  • Hi all,

    Edited 2017-08-06 with new Pysense data
    Edited 2017-08-22 with new Pysense wake on pin info
    Edited 2017-09-06 with Deep Sleep Shield current consumption feedback, 3V3 input
    Edited 2017-09-12 to clarify that deep sleep current is from battery, not USB

    Here is my current understanding the situation regarding the various deep sleep modes.

    Current estimates are based on the setup being powered from a battery, not over USB (this will result in noticeably higher currents).

    Battery life estimates are based on a 2500 mAh battery, but do not take into account power drawn during the "wake" periods, which depends on what you do, and how often you do it, nor power drawn by any sensor.

    • WiPy 2.0, LoPy 1.0 and SiPy 1.0, using expansion board, without Deep Sleep Shield

      • use machine.deepsleep()
      • wake on timer: Yes
      • wake on pin: Yes
      • pins: P2, P3, P4, P6, P8 to P10 and P13 to P23.
      • ESP32 powered during deep sleep (including ULP and RTC): Yes (in deep sleep mode)
      • deep sleep current: > 12 mA (bad) [±1 week?] due to DC-DC switching regulator (10 mA) and flash (2 mA)
      • -> Option 1: provide regulated 3.3V via 3V3 input -> lowers current to ±2 mA [±1 month] there is some controversy on this point, it could actually damage the board
      • -> Option 2: use Deep Sleep Shield, Pytrack or Pysense
    • Using Deep Sleep Shield

      • use Deep Sleep library
      • wake on timer: Yes
      • wake on pin: Yes
      • pins: P10, P17, P18
      • ESP32 powered during deep sleep (including ULP and RTC): No
      • deep sleep current: ±7-10 µA (good) [years?]
      • deep sleep current: ±500-620 µA [months?]. Waiting for Pycom for reason/fix.
    • Using Pysense

      • use Pysense library
      • wake on timer: Yes
      • wake on pin: Yes, but requires patched Pysense firmware and librairies and cutting one pin, see https://forum.pycom.io/topic/1673/pysense-pinout-wake-on-pin/16
      • pins: EXT_IO1 (pin 6 on the External I/O header) only
      • ESP32 powered during deep sleep (including ULP and RTC): No
      • deep sleep current: ± 12 µA (good) [years?] with updated Pysense library
    • Using Pytrack

      • use Pytrack library
      • wake on timer: Yes
      • wake on pin: Same as Pysense?
      • pins: Same as Pysense?
      • ESP32 powered during deep sleep (including ULP and RTC): No
      • deep sleep current: ± 20 µA (good) [years?]


  • @tuftec, yes you are correct, the machine.deepsleep() machine.remaining_sleep_time() and pin_deepsleep_wakeup() functions all work fine.

    I have isolated my problem was with the LoRa publishing code. When I commented out the lora_publish in my code below everything worked fine. The bug must be something to do with nvram functions i am using in my lora_publish function. Perhaps this bug is best published in a new thread. Thanks for the comment.

    Code published to allow others a quick start!

    import machine
    import utime
    from machine import Pin
    import pycom
    import config #user defined
    #import LoRa_publish #user defined
    
    rst=machine.reset_cause()
    if rst != 3: # if not woken from deepsleep
        utime.sleep(10) #to allow ctrl+C
        pycom.nvs_set('counter', 0)
        #button = Pin('P23', mode = Pin.IN, pull = Pin.PULL_UP)
        machine.pin_deepsleep_wakeup(pins = ['P23'], mode = machine.WAKEUP_ALL_LOW, enable_pull = True)
        machine.deepsleep(60000)
    else:
        if (machine.wake_reason()[0])==1: #pin wakeup
            total_count = pycom.nvs_get('counter') +1
            pycom.nvs_set('counter', total_count)
            print('remaining deepsleep time is {}'.format(machine.remaining_sleep_time()))
            machine.pin_deepsleep_wakeup(pins = ['P23'], mode = machine.WAKEUP_ALL_LOW, enable_pull = True)
            machine.deepsleep(machine.remaining_sleep_time())
    
        elif (machine.wake_reason()[0])==2: #RTC timer complete
            print('timer completed')
            total_count = pycom.nvs_get('counter')
            print('counted {} button presses'.format(total_count))
            #LoRa_publish.publish(total_count) #INT published to TTN
            pycom.nvs_set('counter', 0)
            machine.pin_deepsleep_wakeup(pins = ['P23'], mode = machine.WAKEUP_ALL_LOW, enable_pull = True)
            machine.deepsleep(60000) #this does not restart a new interval!!
    


  • @sslupsky if you are measuring wake to wake then you have the LoRa send time included, not just boot time.

    If you use LoRaWAN, then don’t forget that there’s at least 2 seconds after send for the RX1 and RX2 windows, possibly a lot more if the network sends a higher RX1 delay.

    Also, a LoRa packet can be pretty slow to send in the slower data rates. It can be even longer for LoRaWAN with the frame overhead, but even in raw LoRa you need to count the preamble. The smallest frame sent over LoRaWAN at SF12 takes nearly 1.5 seconds to send.



  • @philwilkinson Thanks for the heads up. I have a Pysense and so far the machine.deepsleep() appears to work. I've had it running continuously for about a day now: Wake, send LoRa data packet, Sleep.

    I also posted a question regarding the amount of time it takes the LoPY4 to wake. In my simple Wake, send LoRa data packet, Sleep application, it takes about 4.5 seconds to wake (I have a 10 second sleep period and the total time Wake to Wake is about 14.5 seconds). Are you aware of any way to optimize that? Or perhaps reduce the power consumption during the wake / boot?

    Thanks again for the feedback.



  • @philwilkinson I am not sure I agree with your findings.
    I have been able to use the machine.deepsleep(60000) to put the device to sleep for 10 minutes, wake up and then reboot my code. My code continues to run as expected, waking up every 10 mins.
    I am using a LoPy4.
    I also use the wake identification capability to differentiate between a reset/power up and a wake from sleep.

    Peter.



  • @sslupsky I just wanted to add a little to this discussion for new boards e.g. LoPy4 on an expansion board (not Pysense/Pytrack).
    -The machine.pin_deepsleep_wakeup() function works fine.
    -Using machine.deepsleep(time_in_ms) works fine once only. When the time_in_ms is complete, the unit wakes up OK and runs main.py. machine.wake_reason() correctly identifies a RTC WAKEUP.

    However, it is not possible to then run machine.deepsleep(time_in_ms) again. The unit thinks the time has already elapsed and immediately exits deepsleep.



  • @jcaron Ahh, that explains it. Now I understand better. Thank you.



  • @sslupsky When you use deep sleep controlled by a PySense, PyTrack or the Deep Sleep Shield, deep sleep just completely powers off the xxPy module (ESP32, LoRa/Sigfox and/or LTE modem). No RTC, no ULP, no pin wake-up (on the ESP32), nothing...

    If you use modules that support the native machine.deepsleep without the higher power consumption, it's probably always better to use that. The PySense/PyTrack/Deep Sleep Shield deep sleep was just a workaround.



  • @jcaron Thank you for the suggestion. I did not realize the Pysense API killed the RTC. That is good to know since I want to keep track of time. I have a code module working with the Pysense API now. I will try the native machine API.



  • @sslupsky even if you are using a Pysense, it probably makes sense to use the native machine.deepsleep if you are using a LoPy 4. This keeps the RTC running, for instance.



  • Hi @jcaron I have another question regarding the Pysense. Is it possible to "sleep" the SD Card? Typically that would require that power to the card is turned off since most SD card sleep current specs are 100's of uA.

    @administrators May I make a suggestion regarding a future update to the Pysense? Instead of an SD card, could you embed an eMMC chip instead? Or have both? eMMC chips typically have lower sleep current ratings and wider temperature ratings than SD cards.



  • Hi @dmayorquin ,

    Your post was extremely helpful, thank you for pointing that out. It is encouraging that you achieved < 20uA sleep current.

    Thank you @jcaron for the clarifications. I should have mentioned that I am using a Pysense and LoPY4.

    I think I understand now that when you use a Pysense, use the Pysense API to put the system to sleep (ie: py.go_to_sleep()). If you have just a LoPY4 and are not using the Pysense, then use the machine.deepsleep() to put it to sleep.



  • Hi @sslupsky, I solved the issue and the complete code is here: https://forum.pycom.io/topic/3594/how-to-deep-sleep-with-sipy-pysense-3-7v-lipo/3

    As @jcaron says, machine.deepsleep() works well with the new hardware, but I'm not sure it works too when your setup has a shield like Pysense. In that case I've read that you should use the deep sleep method from Pysense library (or Pytrack or whatever shield you're using).



  • @sslupsky if you have one of the older modules (LoPy 1, SiPy, WiPy 2), then there is an issue with the “native” deep sleep (machine.deepsleep) which results in a higher than expected power draw during deep sleep (>10 mA instead of 10-20 uA).

    For those modules, the workaround to achieve low current deep sleep is to use an external board: Deep Sleep Shield, PySense or PyTrack, and the relevant library. This will cut all power to the module during deep sleep.

    If you use one of the more recent modules, you should in most cases use the native deep sleep.



  • @dmayorquin Did you resolve this issue? Looking at your code, one question comes to mind that I have been looking to find an answer to.

    You use py.go_to_sleep() to enter sleep mode which is part of the Pysense class.

    Is that that call functionally equivalent to machine.deepsleep() ?



  • Hi @jcaron , thanks for your fast answer. Yes, I'm connecting the battery directly to the JST connector on the Pysense and I'm not using any sensor or SD card. In boot.py I disable WiFi:

    from network import WLAN
    
    wlan = WLAN()
    wlan.deinit()
    

    And main.py code is exactly as It's shown in my previous reply. I'm going to try with other releases of SiPy firmware. If you have any suggestion please let me know.



  • @dmayorquin never tried with a SiPy, only a LoPy, but the end result should be the same as the PySense will completely switch off the module.

    The usual culprit is powering through USB, but if I understand correctly your setup, this is not the case. You are connecting the battery directly to the JST-PH connector on the Pysense, right?

    Do you have anything else connected? Do you have an SD card in the slot? You haven’t setup any of the sensors to remain awake (like accelerometer wake up)?



  • Hi, I have a SiPy + Pysense + 3.7 V LiPo battery. I'm testing Deep sleep mode from Pysense library but the multimeter is not showing 12 µA current consumption.

    SiPy firmware: 1.18.0
    Pysense firmware: 0.0.8

    My program disabled WiFi in boot.py. In main.py I blink an LED for 5 seconds and then go to sleep. These are my results:

    Blinking: ~50 mA
    Deep sleep: ~2.2 mA

    main.py code:

    from pysense import Pysense
    import pycom
    import time
    
    py = Pysense()
    
    #Turn-of heartbeat
    if pycom.heartbeat() == True:
        pycom.heartbeat(False)
    
    for i in range(5):
        pycom.rgbled(0x1F)
        time.sleep(0.05)
        pycom.rgbled(0x00)
        time.sleep(1)
    
    #Sleep 20 seconds
    py.setup_sleep(20)
    py.go_to_sleep()
    

    Is there any piece of code I'm missing? What are you doing to get 12 µA with the Pysense board?



  • @iotmaker @rloro338 Updated the summary with the current draw reported with the Deep Sleep Shield.

    Also added that powering via 3V3 may not be a solution, and that wake on pin with the Pysense is not trivial.



  • @rloro338 said in Deep Sleep Summary:

    @iotmaker I am measuring the same power comsumption ... 620 uA with expansion board and 520 uA without it.

    I am glad i am not the only one.. I just took another sipy updated firmware and deepsleep library and same issue 520uA really far from 7 or 10 ua



Pycom on Twitter