Welcome to the Pycom forum Forum
    • \[\[global:header.categories\]\]
    • \[\[global:header.recent\]\]
    • \[\[global:header.tags\]\]
    • \[\[global:header.popular\]\]
    • Login

    Explore Pybytes | Official Documentation | Report a Firmware Bug/Issue | GitHub

    How to Deep sleep with SiPy + Pysense + 3.7V LiPo

    Scheduled Pinned Locked Moved Guides
    pysensesipydeep sleeplow power
    9 Posts 5 Posters 2.7k Views 6 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • D Offline
      dmayorquin
      last edited by

      Hi from Colombia,

      By these days I was in a battle with the deep sleep mode of the Pysense board. Finally I made It works and I want to share my discoveries with you.

      My problem was that in Deep sleep mode my SiPy + Pysense setup current consumption was around 2.5 mA (by using the Pysense library as It's adviced in the forums), which is not quite low power. I also was not powering the boards by USB but using a 3.7V LiPo connected to JST connector on Pysense. And I was using the last stable versions of SiPy and Pysense firmware (1.18.0 and 0.0.8 respectively). The following was my code in main.py:

      from pysense import Pysense
      import pycom
      import time
      
      py = Pysense()
      
      #Turn-off heartbeat
      if pycom.heartbeat() == True:
          pycom.heartbeat(False)
      
      #Blink the LED
      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()
      

      And in order to reduce power consumption in active mode (down from ~120 mA to ~40 mA), I placed the following code in boot.py:

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

      As you can see, everything looks right because I did not want to use neither the accelerometer and INT pin interruptions, I just wanted to blink an LED a few times and then put the module N seconds in Deep sleep mode (nothing out of this world).

      So testing and failing until success I found the following:

      • It's mandatory to import the LIS2HH12 library and create an object in order to turn-on the accelerometer
      • It's mandatory to enable at least one accelerometer's activity/inactivity interruption by using the setup_int_wake_up() method from Pysense library. In my case I enabled only the activity interruption:
      py.setup_int_wake_up(True, False)
      

      When I did that the Deep sleep current was reduced to ~380 µA, so much better but still too high.

      • I realized that if I removed boot.py from my project, the Deep sleep current lowers to 124 µA (not bad). The drawback: Active current rises to ~120 mA again.

      As the accelerometer was in active mode (although I did not want to use It) its current consumption should be around 110 µA according to datasheet. So I went deeper into the datasheet and the LIS2HH12 class and found a way to put the accelerometer in Power-down mode: Write a 0 to the ODR bits of the CTRL1 register. Fortunately the LIS2HH12 class has a method named set_odr() to do that. So:

      • Use set_odr(0) to put the accelerometer in Power-down mode. That lowered the Deep sleep current of my SiPy + Pysense to just 19.5 µA

      Finally, to get a low active current again, disabling WiFi at the beginning of the program made my boards drain ~120 mA during the first two seconds after power on and then It was reduced to ~40 mA (as It's supposed), the surprise was that (for some reason I can not explain) enabling WiFi again just before entering Deep sleep mode made me win 1 µA more in Deep sleep. So at the end of my experiments I got 18,3 µA!!! in Deep sleep mode with a SiPy + Pysense + 3.7V LiPo setup. Yay!!!

      Here is my main.py code (I let the comments in spanish). I hope you guys find It useful. Espero les sea de utilidad ;)

      from pysense import Pysense         #Tarjeta Pysense
      from LIS2HH12 import LIS2HH12       #Acelerómetro
      from network import WLAN            #WiFi
      import pycom                        #Usado para manejo del led RGB
      import time                         #Usado para retardos de tiempo
      
      py = Pysense()                      #Objeto para manejo de librería pysense
      acc = LIS2HH12()                    #Objeto para manejo del acelerómetro
      wlan = WLAN(mode=WLAN.STA)          #Objeto para manejo de WiFi
      
      #Desactivar wlan para reducir consumo en modo activo
      wlan.deinit()
      
      #Apagar el modo heartbeat si se encuentra activo
      if pycom.heartbeat() == True:
          pycom.heartbeat(False)
      
      print("Parpadear led tres veces...")
      for i in range(3):
          print(str(i + 1))
          pycom.rgbled(0x1F)
          time.sleep(0.05)
          pycom.rgbled(0x00)
          time.sleep(1)
      
      #Activar interrupción por acelerómetro (Actividad, Inactividad)
      py.setup_int_wake_up(True, False)
      
      #Poner acelerómetro en modo Power-down
      #  Escribir 0 en los bits ODR del registro CTRL1
      acc.set_odr(0)
      
      #Activar WLAN antes de pasar a Deep sleep
      #  Por algún motivo si dejo el WiFi desactivado el consumo sube un poco 
      #  al entrar en modo Deep sleep
      wlan.init(mode=WLAN.STA)
      
      print("A dormir por 30 segundos...")
      #Configurar tiempo y entrar en modo Deep Sleep
      py.setup_sleep(30)
      py.go_to_sleep()
      
      J D 2 Replies Last reply Reply Quote 2
      • J Offline
        jcaron @dmayorquin
        last edited by

        @dmayorquin that seems quite weird, and I’m pretty sure you can get even better, as in your case the sensors are powered by the PIC when you actually don’t need them.

        For WiFi checkout pycom.wifi_on_boot. This should only affect active mode and not deep sleep though.

        D 1 Reply Last reply Reply Quote 0
        • D Offline
          dmayorquin @jcaron
          last edited by

          Thanks @jcaron!
          Instead the init/deinit WLAN calls, I'm using pycom.wifi_on_boot(False) as you suggested. Deep sleep current lowered to 17,8 µA and I also got a better mean active current, because (according to docs) WiFi on boot flag is stored in non-volatile memory. So, after using pycom.wifi_on_boot(False) WiFi will turn-off on the next boot before executing main.py.

          Updated code is:

          from pysense import Pysense         #Tarjeta Pysense
          from LIS2HH12 import LIS2HH12       #Acelerómetro
          import pycom                        #Usado para manejo del led RGB
          import time                         #Usado para retardos de tiempo
          
          py = Pysense()                      #Objeto para manejo de librería pysense
          acc = LIS2HH12()                    #Objeto para manejo del acelerómetro
          
          #Apagar el modo heartbeat si se encuentra activo
          if pycom.heartbeat() == True:
              pycom.heartbeat(False)
          
          #Desactivar el WiFi al iniciar, si está activo
          if pycom.wifi_on_boot() == True:
              pycom.wifi_on_boot(False)
          
          print("Parpadear led tres veces...")
          for i in range(3):
              print(str(i + 1))
              pycom.rgbled(0x1F)
              time.sleep(0.05)
              pycom.rgbled(0x00)
              time.sleep(1)
          
          #Activar interrupción por acelerómetro (Actividad, Inactividad)
          py.setup_int_wake_up(True, False)
          
          #Poner acelerómetro en modo Power-down
          #  Escribir 0 en los bits ODR del registro CTRL1
          acc.set_odr(0)
          
          print("A dormir por 30 segundos...")
          #Configurar tiempo y entrar en modo Deep Sleep
          py.setup_sleep(30)
          py.go_to_sleep()
          
          S 1 Reply Last reply Reply Quote 0
          • D Offline
            dmayorquin @dmayorquin
            last edited by

            Hello everyone, I've discovered something new. The function go_to_sleep() has one parameter which can be True or False (default is True). This function is located in pycoproc.py and these are its first lines of code:

            def go_to_sleep(self, gps=True):
                    # enable or disable back-up power to the GPS receiver
                    if gps:
                        self.set_bits_in_memory(PORTC_ADDR, 1 << 7)
                    else:
                        self.mask_bits_in_memory(PORTC_ADDR, ~(1 << 7))
            

            Pysense board doesn't have GPS, so I think in this case the RC7 pin of the PIC is doing something with the power supply for sensors. Moreover, if I follow the traces in the PCB, I can see that RC7 signal is related with the pin #3 (3V3_Sensors) of the External IO Header.

            As you can see in the code, the function puts a '1' in RC7 if the parameter is True and puts a '0' if False, so I called py.go_to_sleep(False) and the Deep sleep current lowered to less than 10 µA!!!. What's more:

            • Not necessary to import LIS2HH12 nor to create an object
            • Not necessary to call py.setup_int_wake_up(True, False)
            • Not necessary to power-down the accelerometer with acc.set_odr(0)

            The new (shorter) code is:

            from pysense import Pysense         #Tarjeta Pysense
            import pycom                        #Usado para manejo del led RGB
            import time                         #Usado para retardos de tiempo
            
            py = Pysense()                      #Objeto para manejo de librería pysense
            
            #Apagar el modo heartbeat si se encuentra activo
            if pycom.heartbeat() == True:
                pycom.heartbeat(False)
            
            #Desactivar el WiFi al iniciar, si está activo
            if pycom.wifi_on_boot() == True:
                pycom.wifi_on_boot(False)
            
            print("Parpadear led tres veces...")
            for i in range(3):
                print(str(i + 1))
                pycom.rgbled(0x1F)
                time.sleep(0.05)
                pycom.rgbled(0x00)
                time.sleep(1)
            
            print("A dormir por 30 segundos...")
            #Configurar tiempo y entrar en modo Deep Sleep
            py.setup_sleep(30)
            py.go_to_sleep(False)
            
            S G 2 Replies Last reply Reply Quote 3
            • S Offline
              sslupsky @dmayorquin
              last edited by

              @dmayorquin Interesting observation. It would be so much easier to understand these things if Pycom would make the schematic available. Thanks for posting!

              1 Reply Last reply Reply Quote 0
              • G Offline
                Giorgio @dmayorquin
                last edited by

                @dmayorquin Hi I have an expansion board 3 instead of PySense. Do you know how to do the same thing (put board in deep sleep ) as you did for Pysense? Thank for your help

                D 1 Reply Last reply Reply Quote 0
                • D Offline
                  dmayorquin @Giorgio
                  last edited by

                  @giorgio Hi, I've not worked before with the EB3, but I think you should use the Deep Sleep API (https://docs.pycom.io/datasheets/boards/deepsleep/api.html), which may sends messages to the PIC in expansion board to take control of the low power mode, in a similar way as the PySense API does. Also power the board with a LiPo battery.

                  As the EB3 doesn't have an accelerometer, you should be able to wakeup the SiPy either via an external interrupt, on-board button or timer. Hope this was useful for you.

                  1 Reply Last reply Reply Quote 0
                  • S Offline
                    StijnK @dmayorquin
                    last edited by

                    @dmayorquin Do you have any idea what the maximum sleep time could be?
                    Could hours be achieved?

                    Kindest regards,

                    D 1 Reply Last reply Reply Quote 0
                    • D Offline
                      dmayorquin @StijnK
                      last edited by

                      @StijnK setup_sleep() is a function contained in the pycoproc.py library, and according to its code the maximum value is 2^24 - 1. So the maximum sleep time you could set is 16777215 seconds, which is about 4660 hours (more than six months). Here is the code of pycoproc.py in Github:

                      https://github.com/pycom/pycom-libraries/blob/f848adcfb937e7b7bbc5f78db95840fa26dabe11/pybytes/pysense/lib/pycoproc.py#L24

                      1 Reply Last reply Reply Quote 0

                      Hello! It looks like you're interested in this conversation, but you don't have an account yet.

                      Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

                      With your input, this post could be even better 💗

                      Register Login
                      • 1 / 1
                      • First post
                        Last post

                      Pycom on Twitter

                      Pycom