Skip to content

wifi.radio.listen_interval not available #10170

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
blackketter opened this issue Mar 23, 2025 · 9 comments · Fixed by #10271
Closed

wifi.radio.listen_interval not available #10170

blackketter opened this issue Mar 23, 2025 · 9 comments · Fixed by #10271
Assignees
Milestone

Comments

@blackketter
Copy link

CircuitPython version and board name

Adafruit CircuitPython 9.2.5 on 2025-03-19; M5Stack Atom Echo with ESP32
Board ID:m5stack_atom_echo
UID:052019F95D04

Code/REPL

import wifi
wifi.radio.listen_interval = -1

Behavior

code.py output:
Traceback (most recent call last):
  File "code.py", line 42, in <module>
AttributeError: can't set attribute 'listen_interval'

Description

I'm trying to disable wifi power savings, which seems to improve reliability of ESP32 connections on some wifi networks. According to the documentation, as far as I can tell, this should be available. And I think by setting it to less than zero wifi power saving should be disabled. In any case, the api seems to be missing on this platform. It was apparently added in #9476.

First circuitpython bug report, could be I am holding it wrong. Thanks.

Additional information

No response

@dhalbert dhalbert changed the title wifi.radio.listen_interval not available on M5Stack Atom Echo wifi.radio.listen_interval not available Mar 23, 2025
@dhalbert
Copy link
Collaborator

I looked at this, and found that listen_interval had not been added to the Radio class dictionary. When I added this:

+    { MP_ROM_QSTR(MP_QSTR_listen_interval),    MP_ROM_PTR(&wifi_radio_listen_interval_obj) },

it showed up.

@EternityForest (author of #9476) not sure how we all missed that, but no one else had tried to use it.

I wonder if we should see if the RP2 WiFi impl has some power-saving implementation that is similar, and maybe come up with a more general API that would be applicable to both.

@dhalbert dhalbert added this to the 10.0.0 milestone Mar 25, 2025
@dhalbert
Copy link
Collaborator

The CYW43 driver does have something equivalent to listen_interval. See https://github.com/georgerobotics/cyw43-driver/blob/dd7568229f3bf7a37737b9e1ef250c26efe75b23/src/cyw43.h#L627C24-L627C38. In MicroPython, you can choose one of three power modes for wifi, but it could also be more flexible: https://docs.micropython.org/en/latest/library/network.WLAN.html#network.WLAN.PM_PERFORMANCE

So I'll fix this, and open an issue for CYW43 support.

@dhalbert dhalbert self-assigned this Apr 10, 2025
@dhalbert
Copy link
Collaborator

@blackketter @EternityForest : I have started on a PR to fix this. One thing I noticed it there seems to be a standard of "min", "max", and "none" for power savings / power management. I've seen the same terms used in ESP-IDF and in the CYW43 driver. It's something like this (this is from my work in progress):

//|     MIN: PowerManagement
//|     """Minimum power management (default). The WiFi station wakes up to receive a beacon every DTIM period.
//|        The DTIM period is set by the access point."""
//|     MAX: PowerManagement
//|     """Maximum power managment, at the expense of some performance. The WiFi station wakes up at the `listen_interval` [Q: is this often 100 ms]."""
//|     NONE: PowerManagement
//|     """No power management: the WiFi station does not sleep."""

It looks like the listen interval is only used for max power management. I started adding a radio.wifi.power_management property similar to what MicroPython does. (Same link as in my previous comment.)

But in the case of "max", I also need to supply a listen interval. Or, I could just default it to something reasonable (100 ms??) as MicroPython does. This is simpler. Otherwise I'll need something like radio.wifi.set_power_management(power_management: PowerManagement, listen_interval: Optional[int] = None), and then some read-only properties to get back the current power_management and listen_interval settings. The listen_interval would be ignored except in the case of "max".

Which API would be good enough for your user case?

@blackketter
Copy link
Author

For my case, I just want to disable wifi power savings as much as possible to reduce latency and improve reliability. My experience with ESP32 on my network (Apple AirPort Extreme, mostly) was that connectivity was unreliable until I disabled power savings when developing on Arduino.

Indeed, I've found that the circuitpython web workflow can be unreliable and I'm betting that this is the cause.

@anecdata
Copy link
Member

For CYW43, is this different from #6976 ? (issue is still open in MicroPython)

FWIW, I believe NINA firmware uses PS_MIN_MODEM by default.

@dhalbert
Copy link
Collaborator

For CYW43, is this different from #6976 ? (micropython#9455 is still open in MicroPython)

@anecdata: Well, that's interesting! I had no idea that was in cyw43. I'm adding it to wifi.Radio.

❗ Note this bug, fixed this fall: georgerobotics/cyw43-driver#122. I am not sure if we have updated to that or not.

I can take advantage of that in the code I'm writing.

FWIW, I believe NINA firmware adafruit/Adafruit_CircuitPython_ESP32SPI#101 PS_MIN_MODEM by default.

Yes, MIN seems to be the ESP-IDF default.

@anecdata
Copy link
Member

@dhalbert
Copy link
Collaborator

dhalbert commented Apr 17, 2025

@anecdata There was a bug (georgerobotics/cyw43-driver#122) in cyw43-driver that pointed out the "AGGRESSIVE" and "PERFORMANCE" power management driver settings were wrong, and seemingly backwards. This was fixed by georgerobotics/cyw43-driver#126 in August, 2024.

We have updated cyw43-driver in CircuitPython, but the settings constants, which we had duplicate definitions of, were not corrected.

This may explain your original bug #6958, from 2022, which was fixed by #6976, by disabling WiFi power management entirely.

MicroPython and pico-sdk now use the corrected "PERFORMANCE" setting as the default. My inclination is to switch to that, because I think our choice was predicated on the incorrect definition of "PERFORMANCE" initially, which was worse (poorer performance) than intended.

Any comment? I will be making a PR not too long from now and the revised default can be tested.

@anecdata
Copy link
Member

anecdata commented Apr 18, 2025

More intuitive and easier to maintain if we match MicroPython / pico-sdk. But the differences are more than the swapped constants, jepler may recall why the values for each differ from MP.

I had tested our DISABLED vs. our STANDARD (I think MP's default) for #6976. I don't think I gave too much attention to AGGRESSIVE or PERFORMANCE. IIRC, some MicroPython folks said the settings worked for them that didn't work for me - not surprising if network differences matter. Not sure how important power savings is on raspberrypi. Happy to test a new PR, any trouble should manifest relatively quickly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants