-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
deep sleep works the first time it is called for the set time and then the microcontroller always wakes up again immediately #7300
Comments
I'm not seeing this behavior on an ESP32-S3 USB OTG board. Here is my bootloader output showing repeated 2 minute deep sleeps:
My test code is: import alarm
import time
import board
board.DISPLAY.brightness = 1
time.sleep(1)
# Create a an alarm that will trigger 120 seconds from now.
time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + 120)
# Exit the program, and then deep sleep until the alarm wakes us.
print ("120 seconds in deep sleep")
board.DISPLAY.brightness = 0
alarm.exit_and_deep_sleep_until_alarms(time_alarm)
# Does not return, so we never get here. |
Version: |
Version tested 12/6/2022 2:20 pm est This code does not even go into light sleep much less deep sleep import alarm
import time
import board
import digitalio
# board.DISPLAY.brightness = 1
led = digitalio.DigitalInOut(board.LED)
led.switch_to_output(True)
time.sleep(2)
led.value = False
# Create a an alarm that will trigger 120 seconds from now.
time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + 30)
# Exit the program, and then deep sleep until the alarm wakes us.
print ("30 seconds in deep sleep")
# board.DISPLAY.brightness = 0
led.value = True
alarm.exit_and_deep_sleep_until_alarms(time_alarm) |
Latest uf2-File installed - no change in behaviour: First time: 120 seconds sleep, from then on starts immediately #Adafruit` CircuitPython 8.0.0-beta.4-77-g5cb867e85 on 2022-12-06; Adafruit Feather ESP32-S3 TFT with ESP32S3
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
# Adafruit esp32-s3 TFT feather Board
# mit drei Sensoren:
# - Distanz vl53l4cd
# - Helligkeit bh1750
# - Luftqualität, Luftdruck, Temperatur, Feuchtigkeit, Höhe über Meer bme680
# Soll die Distanz zur Wasseroberfläche messen, aber dank der Sensorenabschaltung im DeepSleep auch über Tage messen können
# Beat Arnet, 01.10.2022
# art, 13.10.2022
# Es fehlt noch der Schlafmodus und die Messung der Batteriespannung
# art, 15.10.2022
# Circuitpython 8.0.0 Beta 4 installiert und die beiden bisher nicht funktionierenden Funktionen getestet;
# - Batteriespannung messen: Funktioniert nur mit vorangehendem i2c-Scanning
# - deep sleep funktioniert nicht, auch wenn nur Batterie angehängt ist. der esp32 startet sofort wieder und macht keine Pause
import time
import alarm
import board
import digitalio
import adafruit_bme680
import adafruit_bh1750
import adafruit_vl53l4cd
from adafruit_lc709203f import LC709203F, PackSize
import displayio
import terminalio
from adafruit_display_text import label
import ssl
import socketpool
import wifi
import adafruit_minimqtt.adafruit_minimqtt as MQTT
import json
import gc
board.TFT_I2C_POWER
# TFT_I2C_POWER initialisieren
p = digitalio.DigitalInOut(board.TFT_I2C_POWER)
p.switch_to_output() # turned the display OFF (default output is False)
p.value = True # Display und Sensoren einschalten
# Create sensor object, communicating over the board's default I2C bus
i2c = board.I2C() # uses board.SCL and board.SDA
bme680 = adafruit_bme680.Adafruit_BME680_I2C(i2c, debug=False)
bh1750 = adafruit_bh1750.BH1750(i2c)
vl53 = adafruit_vl53l4cd.VL53L4CD(i2c)
# TFT-Display initialisieren
# built-in display
display = board.DISPLAY
# Make the display context
main_group = displayio.Group()
display.show(main_group)
# change this to match the location's pressure (hPa) at sea level
bme680.sea_level_pressure = 995.0
# You will usually have to add an offset to account for the temperature of
# the sensor. This is usually around 5 degrees but varies by use. Use a
# separate temperature sensor to calibrate this one.
temperature_offset = -5
# OPTIONAL: can set non-default values
vl53.inter_measurement = 0
vl53.timing_budget = 200
# Der nachfolgende Code zum Scannen der I2C-Adressen ist notwendig, damit die Spannung gemessen werden kann
BATTERY_MON_ADDRESS = 0x0B # Address for ESP32-s3 tft Feather
def hack_for_i2c_issue():
i2c = board.I2C()
while not i2c.try_lock():
pass
running = True
try:
while running:
print("I2C addresses found:",
[hex(device_address) for device_address in i2c.scan()]
)
# time.sleep(2)
running = False
return i2c
finally: # unlock the i2c bus when ctrl-c'ing out of the loop
i2c.unlock()
try:
print("Searching for battery monitor...")
# There is a known issue with the ESP32-S3:
# https://github.com/adafruit/circuitpython/issues/6311
# Therefore this will not work -> board.I2C()
i2c = hack_for_i2c_issue()
battery_monitor = LC709203F(i2c)
# Update to match the mAh of your battery for more accurate readings.
# Can be MAH100, MAH200, MAH400, MAH500, MAH1000, MAH2000, MAH3000.
# Choose the closest match. Include "PackSize." before it, as shown.
battery_monitor.pack_size = PackSize.MAH2000 # type: ignore
print(f"Battery Percent: {battery_monitor.cell_percent:.2f} %")
print(f"Battery Voltage: {battery_monitor.cell_voltage:.2f} V")
time.sleep(1)
except Exception as e:
print(f"Error reading battery: {e}")
print("All done.")
yDist = 15
labelTemperatur = label.Label(
font=terminalio.FONT, scale=1, anchor_point=(0, 0), anchored_position=(10, yDist)
)
labelLuftqualitaet = label.Label(
font=terminalio.FONT,
scale=1,
anchor_point=(0, 0),
anchored_position=(10, 2 * yDist),
)
labelFeuchtigkeit = label.Label(
font=terminalio.FONT,
scale=1,
anchor_point=(0, 0),
anchored_position=(10, 3 * yDist),
)
labelLuftdruck = label.Label(
font=terminalio.FONT,
scale=1,
anchor_point=(0, 0),
anchored_position=(10, 4 * yDist),
)
labelHoehe = label.Label(
font=terminalio.FONT,
scale=1,
anchor_point=(0, 0),
anchored_position=(10, 5 * yDist),
)
labelHelligkeit = label.Label(
font=terminalio.FONT,
scale=1,
anchor_point=(0, 0),
anchored_position=(10, 6 * yDist),
)
labelDistanz = label.Label(
font=terminalio.FONT,
scale=1,
anchor_point=(0, 0),
anchored_position=(10, 7 * yDist),
)
labelSpannung = label.Label(
font=terminalio.FONT,
scale=1,
anchor_point=(0, 0),
anchored_position=(10, 8 * yDist),
)
# add label to group that is showing on display
main_group.append(labelTemperatur)
main_group.append(labelLuftqualitaet)
main_group.append(labelFeuchtigkeit)
main_group.append(labelLuftdruck)
main_group.append(labelHoehe)
main_group.append(labelHelligkeit)
main_group.append(labelDistanz)
main_group.append(labelSpannung)
# Add a secrets.py to your filesystem that has a dictionary called secrets with "ssid" and
# "password" keys with your WiFi credentials. DO NOT share that file or commit it into Git or other
# source control.
# pylint: disable=no-name-in-module,wrong-import-order
try:
from secrets import secrets
except ImportError:
print("WiFi secrets are kept in secrets.py, please add them there!")
raise
# Set your Adafruit IO Username and Key in secrets.py
# (visit io.adafruit.com if you need to create an account,
# or if you need your Adafruit IO key.)
aio_username = secrets["aio_username"]
aio_key = secrets["aio_key"]
print("Connecting to %s" % secrets["ssid"])
wifi.radio.connect(secrets["ssid"], secrets["password"])
print("Connected to %s!" % secrets["ssid"])
### Feeds ###
# Setup a feed named 'distance' for publishing to a feed
distance_feed = secrets["aio_username"] + "/distance"
light_feed = secrets["aio_username"] + "/light"
soil_feed = secrets["aio_username"] + "/soil"
salt_feed = secrets["aio_username"] + "/salt"
voltage_feed = secrets["aio_username"] + "/voltage"
voltagepercent_feed = secrets["aio_username"] + "/voltagepercent"
batterytemperature_feed = secrets["aio_username"] + "/batterytemperature"
temperature_feed = secrets["aio_username"] + "/temperature"
humidity_feed = secrets["aio_username"] + "/humidity"
airpressure_feed = secrets["aio_username"] + "/airpressure"
altitude_feed = secrets["aio_username"] + "/altitude"
salt_feed = secrets["aio_username"] + "/salt"
wasserfass_feed = secrets["aio_username"] + "/wasserfass"
# Setup a feed named 'switch' for subscribing to changes
switch_feed = secrets["aio_username"] + "/output"
# Define callback methods which are called when events occur
# pylint: disable=unused-argument, redefined-outer-name
def connected(client, userdata, flags, rc):
# This function will be called when the client is connected
# successfully to the broker.
print("Connected to raspiart IO! Listening for topic changes on %s" % switch_feed)
# Subscribe to all changes on the switch_feed.
client.subscribe(switch_feed)
def disconnected(client, userdata, rc):
# This method is called when the client is disconnected
print("Disconnected from raspiart!")
def message(client, topic, message):
# This method is called when a topic the client is subscribed to
# has a new message.
print("New message on topic {0}: {1}".format(topic, message))
# Create a socket pool
pool = socketpool.SocketPool(wifi.radio)
# Set up a MiniMQTT Client
mqtt_client = MQTT.MQTT(
broker=secrets["broker"],
port=secrets["port"],
username=secrets["aio_username"],
password=secrets["aio_key"],
socket_pool=pool,
ssl_context=ssl.create_default_context(),
)
# Setup the callback methods above
mqtt_client.on_connect = connected
mqtt_client.on_disconnect = disconnected
mqtt_client.on_message = message
# Connect the client to the MQTT broker.
print("Connecting to raspiart IO...")
mqtt_client.connect()
# Dummy Werte zur Initialisierung
Temperatur = 20.0
Luftqualitaet = 100.0
Feuchtigkeit = 40.0
Luftdruck = 1000.0
Hoehe = 500.0
Helligkeit = 100.0
Distanz = 1.0
Spannung = 5.0
SpannungProzent = 100.0
AkkuTemperatur = 20.0
Salz = 0.0 # Dummy-Wert, weil der nicht h^gemessen werden kann
Temperatur = bme680.temperature + temperature_offset
Luftqualitaet = bme680.gas
Feuchtigkeit = bme680.relative_humidity
Luftdruck = bme680.pressure
Hoehe = bme680.altitude
Helligkeit = bh1750.lux
SpannungProzent = battery_monitor.cell_percent
Spannung = battery_monitor.cell_voltage
AkkuTemperatur = battery_monitor.cell_temperature
vl53.start_ranging()
while not vl53.data_ready:
pass
vl53.clear_interrupt()
Distanz = vl53.distance
labelTemperatur.text = "Temperatur: %0.1f C" % Temperatur
labelLuftqualitaet.text = "Luftqualität: %d Index" % Luftqualitaet
labelFeuchtigkeit.text = "Feuchtigkeit: %0.1f %%" % Feuchtigkeit
labelLuftdruck.text = "Luftdruck: %0.3f hPa" % Luftdruck
labelHoehe.text = "Höhe über Meer: %0.2f Meter" % Hoehe
labelHelligkeit.text = "Helligkeit: %.2f Lux" % Helligkeit
labelDistanz.text = "Distanz: {} cm".format(Distanz)
labelSpannung.text = "Spannung: {} V, {} %".format(Spannung, SpannungProzent)
print("\nTemperatur: %0.1f C" % Temperatur)
print("Luftqualität: %d Index" % Luftqualitaet)
print("Feuchtigkeit: %0.1f %%" % Feuchtigkeit)
print("Luftdruck: %0.3f hPa" % Luftdruck)
print("Höhe über Meer: %0.2f Meter" % Hoehe)
print("Helligkeit: %.2f Lux" % Helligkeit)
print("Distanz: {} cm".format(Distanz))
print("Spannung: {} V, {} %".format(Spannung, SpannungProzent))
# Nachrichten empfangen
try:
mqtt_client.loop()
except (ValueError, RuntimeError) as e:
print("Failed to get data, retrying\n", e)
wifi.reset()
mqtt_client.reconnect()
# continue
# Send a new message
print("Es werden nun die Werte via MQTT an den raspiart gesendet")
mqtt_client.publish(distance_feed, Distanz)
mqtt_client.publish(temperature_feed, Temperatur)
mqtt_client.publish(soil_feed, Luftqualitaet)
mqtt_client.publish(light_feed, Helligkeit)
mqtt_client.publish(airpressure_feed, Luftdruck)
mqtt_client.publish(humidity_feed, Feuchtigkeit)
mqtt_client.publish(altitude_feed, Hoehe)
mqtt_client.publish(voltage_feed, Spannung)
mqtt_client.publish(voltagepercent_feed, SpannungProzent)
mqtt_client.publish(batterytemperature_feed, AkkuTemperatur)
wasserfass={
"distance":Distanz,
"temperature":Temperatur,
"soil":Luftqualitaet,
"light":Helligkeit,
"pressure":Luftdruck,
"humidity":Feuchtigkeit,
"altitude":Hoehe,
"voltage":Spannung,
"voltagepercent":SpannungProzent,
"batterytemeperature":AkkuTemperatur,
"salt":Salz
}
wasserfass_json=json.dumps(wasserfass)
# print(wasserfass_json)
try:
mqtt_client.publish(wasserfass_feed,wasserfass_json)
print("Werte wurden gesendet")
except (ValueError, RuntimeError) as e:
print("Werte konnten nicht gesendet werden\n", e)
# 5" warten bis zum tiefen Schlaf gewechselt wird
print ("5 Sekunden bei voller Leistung")
time.sleep(5)
# Delete objects before powering down
#del i2c
#del bme680
#del bh1750
#del vl53
#del display
#del battery_monitor
# garbage collector
#gc.collect()
# Powering down TFT-display and sensors
p.value = False
# Create a an alarm that will trigger 10 seconds from now.
#time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + 4)
# Do a light sleep until the alarm wakes us.
#print ("4 Sekunden im leichtem Schlaf")
#alarm.light_sleep_until_alarms(time_alarm)
# Finished sleeping. Continue from here.
# Create a an alarm that will trigger 120 seconds from now.
time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + 120)
# Exit the program, and then deep sleep until the alarm wakes us.
print ("120 Sekunden im tiefen Schlaf")
alarm.exit_and_deep_sleep_until_alarms(time_alarm)
# Does not return, so we never get here. |
In my tests with beta 5, it never goes to deep sleep but just resets, like before I think.
Running that code. import alarm
import time
time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + 20)
alarm.exit_and_deep_sleep_until_alarms(time_alarm) Does not go to deep sleep but resets immediately instead when on power only (USB power adapter or battery). Same thing with a UM FeatherS3.
|
I tested this yesterday and found that the ULP was incorrectly waking up the S3. I'll try and sort it out today. |
The IDF's wakeup cause is only for deep sleep. Without ignoring it, light sleep will wake up too early when done after a deep sleep wake. Fixes #7300
CircuitPython version
Code/REPL
Behavior
First time after booting: waits 120 seconds in deep sleep
Second time and the following: immediately wakes up again and starts
Description
No response
Additional information
No response
The text was updated successfully, but these errors were encountered: