lightsleep

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
danjperron
Posts: 51
Joined: Thu Dec 27, 2018 11:38 pm
Location: Québec, Canada

lightsleep

Post by danjperron » Wed Jul 06, 2022 11:16 pm

Is this was merge https://github.com/micropython/micropython/pull/8832 to the current master?

I tried it but it doesn't work if the lightsleep value is more than 1.

this is my m1.py

Code: Select all

import machine
import utime

def m1():
    count = 1
    while True:
        print(count)
        utime.sleep_ms(500)
        machine.lightsleep(1)
        count = count + 1
        utime.sleep_ms(500)
To run it I use
import m1
m1.m1()
and it never returns if the lightsleep is not 1.

P.S. i'm using thonny with the latest version that I compiled today
MicroPython v1.19.1-102-g07cae9178 on 2022-07-06; Raspberry Pi Pico with RP2040.

B.T.W. I tried the pico and the picoW and I got the same problem.
Last edited by danjperron on Thu Jul 07, 2022 12:44 am, edited 1 time in total.

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: lightsleep

Post by jimmo » Thu Jul 07, 2022 12:41 am

danjperron wrote:
Wed Jul 06, 2022 11:16 pm
Is this was merge https://github.com/micropython/micropython/pull/8832 to the current master?
I think it's waiting for feedback and testing. It would be good if you could post your findings on the bug.

Edit: misread the question... yes this was merged last week and is in current master and nightly builds dated after that point.

danjperron
Posts: 51
Joined: Thu Dec 27, 2018 11:38 pm
Location: Québec, Canada

Re: lightsleep

Post by danjperron » Thu Jul 07, 2022 2:02 am

Well this code works on pico flashing the led

Code: Select all

import machine
import sys

led = machine.Pin(25, machine.Pin.OUT)
while True:
    machine.lightsleep(2000)
    led.toggle()

But this doesn't work on picoW if I add lightsleep
This is the part to publish cpu temperature via MQTT

Code: Select all

while True:
  try:
      client.check_msg()
      reading = sensor_temp.read_u16() * conversion_factor
      temperature = 27 - (reading - 0.706)/0.001721
      pub_msg = str(temperature)
      client.publish(pub_topic, pub_msg)
      time.sleep(5)
      wlan.active(False)
      #machine.lightsleep(5000)
      wlan.active(True)
      time.sleep(5)
  except OSError as e:
    restart_and_reconnect()

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: lightsleep

Post by jimmo » Thu Jul 07, 2022 2:50 am

I think the idea of lightsleep is that it sleeps for at most the interval, so if you want to use it to set the period for something then you need to use time.ticks_ms and time.ticks_diff in a loop.

danjperron
Posts: 51
Joined: Thu Dec 27, 2018 11:38 pm
Location: Québec, Canada

Re: lightsleep

Post by danjperron » Thu Jul 07, 2022 2:58 am

I think the idea of lightsleep is that it sleeps for at most the interval, so if you want to use it to set the period for something then you need to use time.ticks_ms and time.ticks_diff in a loop.
My goal is to use the PicoW with a lipo battery to record sensor info via MQTT. I want to use lightsleep to reduce power consumption.
Right now I'm using arduino pro mini with nrf24L01. I just want to check how long a small battery will last. Looks like that the arduino method uses way less power. (Comparing uA versus mA).

Still want to figure out how to minimize power when I just need to record sensor data every 5 mins.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: lightsleep

Post by pythoncoder » Thu Jul 07, 2022 7:58 am

Micropower operation is something of a black art with behaviour varying between platforms.

I have had success using deepsleep on the UM Feather S2 - my example uses 66μA in deepsleep. See this script discussed here. The script sends data via MQTT then goes to sleep for a period. On waking main.py starts it again.
Peter Hinch
Index to my micropython libraries.

danjperron
Posts: 51
Joined: Thu Dec 27, 2018 11:38 pm
Location: Québec, Canada

Re: lightsleep

Post by danjperron » Fri Jul 08, 2022 11:47 pm

Ok I got it working!!! Yeah!!

Two things.
1- Thonny stop connecting after the light sleep. I only put a power adapter to the picoW and it works. Maybe is my Mac with Thonny who knows.
2- I need to disconnect the wifi before light sleep and do a restart after and then it is working.


this is my new code with MQTT. N.B. I added a ds18B20.

Code: Select all

import machine
import rp2
import network
import ubinascii
import time
import sys
from secrets import secrets
import socket
from onewire import OneWire
from ds18x20 import DS18X20
from umqtt.simple import MQTTClient
from machine import Pin
     

ds = DS18X20(OneWire(Pin(28)))

sensor = (0x28,0xff,0x69,0x67,0xc1,0x17,0x01,0x98)

sensor_temp = machine.ADC(machine.ADC.CORE_TEMP)
conversion_factor = 3.3 / (65535)

last_message = 0
message_interval = 5
counter = 0

#
# Set country to avoid possible errors / https://randomnerdtutorials.com/micropython-mqtt-esp32-esp8266/
rp2.country('CA')

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
# If you need to disable powersaving mode

# See the MAC address in the wireless chip OTP
mac = ubinascii.hexlify(network.WLAN().config('mac'),':').decode()
print('mac = ' + mac)

# Other things to query
# print(wlan.config('channel'))
# print(wlan.config('essid'))
# print(wlan.config('txpower'))

# Load login data from different file for safety reasons
ssid = secrets['ssid']
pw = secrets['pw']
broker = secrets['broker']
sub_topic = secrets['subtopic']
pub_topic = secrets['pubtopic']
pub_topic2 = secrets['pubtopic2']
#client_id = ubinascii.hexlify(machine.unique_id())
#client_id = mac
client_id = secrets['client_id']

#if machine.reset_cause() != machine.SOFT_RESET:
if True:
    #wlan.init(network.WLAN.STA)
    # configuration below MUST match your home router settings!!
    wlan.ifconfig(('10.11.12.21', '255.255.255.0', '10.11.12.253', '8.8.8.8'))
    #wlan.ifconfig(('172.19.0.41', '255.255.255.0', '172.19.0.253', '8.8.8.8'))
if not wlan.isconnected():
    # change the line below to match your network ssid, security and password
    wlan.connect(ssid,pw)
    while not wlan.isconnected():
        machine.idle() # save power while waiting

# Wait for connection with 10 second timeout
timeout = 10
while timeout > 0:
    if wlan.status() < 0 or wlan.status() >= 3:
        break
    timeout -= 1
    print('Waiting for connection...')
    time.sleep(1)
    
# Handle connection error
# Error meanings
# 0  Link Down
# 1  Link Join
# 2  Link NoIp
# 3  Link Up
# -1 Link Fail
# -2 Link NoNet
# -3 Link BadAuth
if wlan.status() != 3:
    raise RuntimeError('Wi-Fi connection failed')
else:
    led = machine.Pin('LED', machine.Pin.OUT)
    for i in range(wlan.status()):
        led.on()
        time.sleep(.1)
        led.off()
    print('Connected')
    status = wlan.ifconfig()
    print('ip = ' + status[0])
    
### Topic Setup ###

def sub_cb(topic, msg):
  #print((topic, msg))
  if msg == b'LEDon':
    print('Device received LEDon message on subscribed topic')
    led.value(1)
  if msg == b'LEDoff':
    print('Device received LEDoff message on subscribed topic')
    led.value(0)


def connect_and_subscribe():
  global client_id, mqtt_server, topic_sub
  client = MQTTClient(client_id, broker)
  client.set_callback(sub_cb)
  client.connect()
  client.subscribe(sub_topic)
  print('Connected to %s MQTT broker as client ID: %s, subscribed to %s topic' % (broker, client_id, sub_topic))
  return client

def restart_and_reconnect():
  print('Failed to connect to MQTT broker. Reconnecting...')
  time.sleep(10)
  machine.reset()

try:
  client = connect_and_subscribe()
except OSError as e:
  restart_and_reconnect()

led = machine.Pin('LED', machine.Pin.OUT)


while True:
  try:
      led.value(True)
      ds.convert_temp()
      reading = sensor_temp.read_u16() * conversion_factor
      temperature = 27 - (reading - 0.706)/0.001721
      pub_msg = str(temperature)
      client.publish(pub_topic2, pub_msg)
      pub_msg = "%6.1f" % (ds.read_temp(sensor))
      client.publish(pub_topic, pub_msg)
      time.sleep_ms(250)
      led.value(False)
      wlan.disconnect()
      time.sleep_ms(100)
      machine.lightsleep(5000)
  except OSError as e:
      pass
  restart_and_reconnect()


danjperron
Posts: 51
Joined: Thu Dec 27, 2018 11:38 pm
Location: Québec, Canada

Re: lightsleep

Post by danjperron » Sat Jul 09, 2022 8:19 pm

ok I got other problems!

1 - On light sleep I still have 40ma of current. I think it is the wifi. How to turn it off completely?
right now I'm using. disconnect() and active("Down").

~40ma on lightsleep and up to 80ma when transmitting.

2 - Using MQTT with a lipo battery it should be good to read VSys. but machine.ADC(29) freeze the wifi.

To counteract this I read GPIO29 pad, use machine.ADC(3), change the pad to NO (pulls,In and OUT), read_u16() and then put GPIO29 back like it was.

This is my code.

Code: Select all

import machine
import rp2
import network
import ubinascii
import time
import sys
from secrets import secrets
from onewire import OneWire
from ds18x20 import DS18X20
from umqtt.simple import MQTTClient
from machine import Pin

sensor = (0x28,0xff,0x69,0x67,0xc1,0x17,0x01,0x98)

#sensor DS18b20 on pin 28
ds = DS18X20(OneWire(machine.Pin(28)))


sensor_temp = machine.ADC(machine.ADC.CORE_TEMP)
conversion_factor = 3.3 / (65535)

last_message = 0
message_interval = 5
counter = 0



#
# Set country to avoid possible errors / https://randomnerdtutorials.com/micropython-mqtt-esp32-esp8266/
rp2.country('CA')

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
# If you need to disable powersaving mode

# See the MAC address in the wireless chip OTP
mac = ubinascii.hexlify(network.WLAN().config('mac'),':').decode()
print('mac = ' + mac)

# Other things to query
# print(wlan.config('channel'))
# print(wlan.config('essid'))
# print(wlan.config('txpower'))

# Load login data from different file for safety reasons
ssid = secrets['ssid']
pw = secrets['pw']
broker = secrets['broker']
sub_topic = secrets['subtopic']
pub_topic = secrets['pubtopic']
pub_topic2 = secrets['pubtopic2']
pub_topic3 = secrets['pubtopic3']
#client_id = ubinascii.hexlify(machine.unique_id())
#client_id = mac
client_id = secrets['client_id']

def setPad(gpio, value):
    machine.mem32[0x4001c000 | (4+ (4 * gpio))] = value
    
def getPad(gpio):
    return machine.mem32[0x4001c000 | (4+ (4 * gpio))]


#if machine.reset_cause() != machine.SOFT_RESET:
if True:
    #wlan.init(network.WLAN.STA)
    # configuration below MUST match your home router settings!!
    wlan.ifconfig(('192.168.0.21', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
if not wlan.isconnected():
    # change the line below to match your network ssid, security and password
    wlan.connect(ssid,pw)
    while not wlan.isconnected():
        machine.idle() # save power while waiting

# Wait for connection with 10 second timeout
timeout = 10
while timeout > 0:
    if wlan.status() < 0 or wlan.status() >= 3:
        break
    timeout -= 1
    print('Waiting for connection...')
    time.sleep(1)
    
# Handle connection error
# Error meanings
# 0  Link Down
# 1  Link Join
# 2  Link NoIp
# 3  Link Up
# -1 Link Fail
# -2 Link NoNet
# -3 Link BadAuth
if wlan.status() != 3:
    raise RuntimeError('Wi-Fi connection failed')
else:
    led = machine.Pin('LED', machine.Pin.OUT)
    for i in range(wlan.status()):
        led.on()
        time.sleep(.1)
        led.off()
    print('Connected')
    status = wlan.ifconfig()
    print('ip = ' + status[0])
    
### Topic Setup ###

def sub_cb(topic, msg):
  #print((topic, msg))
  if msg == b'LEDon':
    print('Device received LEDon message on subscribed topic')
    led.value(1)
  if msg == b'LEDoff':
    print('Device received LEDoff message on subscribed topic')
    led.value(0)


def connect_and_subscribe():
  global client_id, mqtt_server, topic_sub
  client = MQTTClient(client_id, broker)
  client.set_callback(sub_cb)
  client.connect()
  client.subscribe(sub_topic)
  print('Connected to %s MQTT broker as client ID: %s, subscribed to %s topic' % (broker, client_id, sub_topic))
  return client

def restart_and_reconnect():
  print('Failed to connect to MQTT broker. Reconnecting...')
  time.sleep(10)
  machine.reset()

try:
  client = connect_and_subscribe()
except OSError as e:
  restart_and_reconnect()

led = machine.Pin('LED', machine.Pin.OUT)


while True:
  try:
      led.value(True)
      ds.convert_temp()
      reading = sensor_temp.read_u16() * conversion_factor
      temperature = 27 - (reading - 0.706)/0.001721
      pub_msg = str(temperature)
      print(pub_topic2,"  ",pub_msg)
      client.publish(pub_topic2, pub_msg)
      time.sleep_ms(50)
      pub_msg = "%6.1f" % (ds.read_temp(sensor))
      print(pub_topic2,"  ",pub_msg)
      client.publish(pub_topic, pub_msg)
      time.sleep_ms(50)
      oldpad = getPad(29)
      setPad(29,128)  #no pulls, no output, no input
      Vsys = machine.ADC(3)
      v = Vsys.read_u16()
      setPad(29,oldpad)
      pub_msg = "%5.2f" % (v*3*conversion_factor)
      print(pub_topic3,"  ",pub_msg)
      client.publish(pub_topic3, pub_msg)
      time.sleep_ms(500)
      
      led.value(False)
      wlan.disconnect()
      wlan.active("Down")
      time.sleep_ms(100)
      machine.lightsleep(120000)
  except OSError as e:
      pass
  restart_and_reconnect()
This is the MQTT output using a 3.7V lipo battery full charge right now

Code: Select all

pi@Pihome:~ $ mosquitto_sub -v -t "PicoW/#" | xargs -d$'\n' -L1 bash -c 'date "+%Y-%m-%d %T.%3N $0"'
2022-07-09 16:15:59.890 PicoW/tempCPU 31.2577
2022-07-09 16:15:59.999 PicoW/temp   27.4
2022-07-09 16:16:00.114 PicoW/Vsys  4.05
2022-07-09 16:18:17.959 PicoW/tempCPU 31.72584
2022-07-09 16:18:18.005 PicoW/temp   27.5
2022-07-09 16:18:18.223 PicoW/Vsys  4.05
Last edited by danjperron on Sat Jul 09, 2022 8:37 pm, edited 2 times in total.

davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: lightsleep

Post by davef » Sat Jul 09, 2022 8:34 pm

I am not familiar with your board but for ESP32 dev boards I have to remove the 3V3 regulator and cut power to the USB to serial chip (CP2102) to reduce significant current.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: lightsleep

Post by pythoncoder » Sun Jul 10, 2022 4:42 pm

I now have a Pico W :D
From a quick test, machine.lightsleep puts the RP2040 into lightsleep, but does not shut down the WiFi chip. If I power up the board and issue lightsleep, current drops to under 1mA. However if I power up, connect to WiFi, then issue lightsleep, current drops from 40mA to about 25mA.
Peter Hinch
Index to my micropython libraries.

Post Reply