-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
Please document wifi.sleep function in official API docs #1115
Comments
I must have forgot to add the documentation after the PRs were merged. After you bring wifi out of sleep with I'll submit a PR with the documentation as soon as I get the chance. |
@dnc40085 This issue of how to safely use non-compliant (see #991) modules is possibly linked to this. I'd like to chat to you about this either as an issue here, by email or Skype. Up to you. I want to document a simple sequence / process for winding down and restarting the WiFi / net stacks so that is you want to run something with interrupts masked for an extended period then you can recover you comms without the ESP cratering. If you want you can PM me your email details at esp8266.com |
@dnc40085 Thanks for clarification. |
@alex3kov You're welcome. On a side note, I was thinking before documenting this that I should expose the timed sleep functionality that also has a callback that can execute on wake up, or not at all if user wakes the chip before the timer runs out. |
@TerryE I think you're right, forcing the wifi into sleep mode before using non-compliant functions would most likely stop any wifi related crashes. I'll do what i can to help. I don't mind talking here in the issues section, unless you think it would be better to talk on esp8266.com or via email. I just like having conversations in the open, so if someone is looking for the same info it can be found and maybe even be helpful. |
Can it fit somewhere else? :) I'm just looking to set up a callback function on some event monitor (not necessarily
Can callback be used without the timer please? I'm trying to react to events - as opposed to doing things at time intervals. |
When using the forced sleep API (wifi.sleep), the application developer determines when the transition occurs, it does not occur automatically. If you really need this functionality, you can setup a timer(
Unfortunately, I have no control over this as it is part of the SDK functionality. |
@dnc40085, a question. (I am on my tablet so I don't have easy access to the source.) Is this SDK call async? I assume it is. In which case the application programmer will need to do a one shot alarm and cb to allow the sleep to occur. It's just that if the app does a sleep API call and immediately starts bit banging or whatever, then the WiFi stack might still due messily. Just a thought, and time for shut-eye for me. |
@TerryE I'm pretty sure it's asynchronous. From the notes section of
When
Then when it is time to wake up (
|
@dnc40085 Doesn't your last comment confirm that we need callbacks on
A timer can be set up as you mentioned - I just noticed in your post that
But that's a rather hackish approach, no? This would be cleaner and more EDD-like:
|
@dnc40085 And another thing:
Can this "wake up timer" be set up while WiFi is sleeping? If yes, then it can be used with a timeout of 1 ms and a callback function, accomplishing what I described in previous comment. |
@alex3kov Aleksei, your model isn't quite right here. Think of turning off the WiFi in the same way that you might ask the power utility to turn off power to your house because you need to do essential repairs. Just because you have made the request doesn't mean that it is going to have been done instantly. Start sticking your fingers into the electrical sockets and you will get electrocuted. In this case the SDK will let any in progress activities complete gracefully, for example the network chip might still be in the process of sending a packet. The "in system idle task" comment is important. This means that even a |
If you're talking about my last comment regarding setting wake up timer while WiFi is sleeping - that was just a wild guess at a possible workaround. I have no knowledge of Espressif SDK, so I don't claim that things work one way or another - just asking questions.
It seems you're taking me for a more SDK-savvy person than I am :) I'm just looking for "as pure EDD as possible" ways to do things on Lua side. Do you agree with my reasoning in previous comment? |
@alex3kov Aleksei, We've been sorting issue out for a couple of years and are still trying to understand some things! This is as much a 2-way discussion. |
Before Earlier today I experimented a little with the API and found:
I was looking in the mapfile, I found two useful functions in the power management API:
Also, I was thinking that it might be a good idea to change the name of this function from It's kind of unrelated to the forced sleep API, but when I was searching for details about how the power management works, I found some useful information, A PDF and A thread on the Espressif forum that clarify the sleep modes a bit better than just reading the programming guide Also somewhat related, I found that the function |
In short the first mode powers down the WiFi module but the rest of the ESP keeps running; the second powers down both CPUs but keeps the RAM and CPU internal state so the CPU can be reawakened on a GPIO pin; deep sleep is just a power-off, but the RTC if left running and can re-coldstart the CPU on a timer. In the first two modes the shutdown of the subsystem(s) has to be orderly. |
This type of work is where the role of |
@TerryE Here's an idea for an implementation... wifi.forceSleep()Forces WiFi modem into sleep mode Syntax
Parameters
Returns
Example-- Put WiFi modem to sleep for 5 seconds
sleep_cfg={}
sleep_cfg.sleep_time=(5*1000*1000)
sleep_cfg.sleeping_cb=non_compliant_function
sleep_cfg.wakeup_cb=wifi_setup
wifi.forceSleep(sleep_cfg)
-- Get current WiFi modem sleep state
sleep_state=wifi.forceSleep()
print("wifi forced sleep is "..(sleep_state and "ENABLED" or "DISABLED")) wifi.forceWakeup()Wake WiFi modem from forced sleep Syntax
Parametersnone Returnsnil Example-- Wake WiFi modem from sleep
wifi.forceWakeup() For I was thinking this could be in it's own submodule. Any suggestions? |
From an application programmer's PoV these three mode are very different:
The word "modem" is extremely misleading. The WiFi has absolutely nothing to do with a modem, other than Espressif use the ESP-01 module with a modem-like AT command scripting framework on their AT builds. None of this applies to Lua firmware builds, so my personal preference is to avoid using this word at all in our API or documentation. "force" implies some form of immediacy, and this isn't the case here as it's an orderly request. The safest thing that the application programmer can do is to tailcall this before ending the current task. And given that these three modes are very different, then how about keeping it simple and having four different calls:
Thoughts? @jmattsson @devsaurus @pjsg etc. any comments? We also need to play with latencies etc. The Espressif document seems to imply that any Wifi station connection will persist across the suspension, and I guess UDP stuff since this is stateless (need to check). I also suspect that any TCP stack will die across the suspension, so it would be better booked any suspension by ensuring any TCP services and sockets are closed, but again something to check. |
Yes, while the ESP8266 is not a dial-up modem using acoustic tones. By its purest definition, the wifi chip is a modem. Modulating and demodulating the digital data using different modulation schemes so it can be sent or received using radio waves. So if the wifi portion of the chip turns off it is correctly stating that the modem is being turned off while the general purpose CPU is staying active. |
@karrots Johnathon, I don't find this rationale compelling. The whole WiFi subsystem on the die is powered down. I have had a quick look and haven't found a single article which uses the word in the context you suggest, for example the Wikipedia WiFi article doesn't. |
I agree with both of you. @karrots on the technical level, and @TerryE on the user-niceness level. The API as exposed by Espressif isn't the most intuitive, and let's not even get started on their naming of things. Language differences probably account for most of it, and techie jargon for the rest. That shouldn't prevent us from exposing a nicer interface to the NodeMCU users though. |
This would be perfect and I need it desperately! Any idea if/when it will be added? |
My post was a feature request, so I don't think that applies. I edited it for clarity -- I was hoping it would make it to the attention of TerryE. |
@mjmcginty My apologies, I'll work on implementing this feature so I can add it to PR #1231, that way they can both be merged at the same time. |
@dnc40085 That would be awesome! My application will need to set a short timer to assign an interrupt to the same pin used to wake it. Also it's possible the pin will transition states multiple times while it's waking. I would be happy to help you test it! :-) |
@dnc40085 I got your branch of the code from git, built it and burned it to an 8266, I see that node.sleep is there and that it accepts a table object as an argument. I see from your test code that one member of the table is named wake_gpio. I'm assuming there are two other named members of this table, an integer for the timeout and a callback function. Could you tell me the names of those members, please? |
@mjmcginty the documentation for Be aware that in addition to the UART being in an unpredictable state when entering light sleep causing current draw to fluctuate from sleep to sleep, there is a problem with If you re-download the branch (I made changes for this workaround to function) and run the following code it should make resume_func=function()
print("node is awake")
wifi.setmode(wifi_mode_temp)
if(wifi_mode_temp==wifi.STATION or wifi_mode_temp==wifi.STATIONAP) then
wifi.sta.connect()
end
wifi_mode_temp=nil
end
enter_light_sleep=function()
wifi_mode_temp=wifi.getmode()
wifi.setmode(wifi.NULLMODE)
tmr.alarm(0, 100, 1,function()
if (wifi.getmode()==0) then
tmr.stop(0)
node.sleep({wake_gpio=0, resume_cb=resume_func})
end
end)
end
enter_light_sleep() I hope to get the code refactoring done in the next week or so, until then good luck! |
@dnc40085 very cool, thank you! Just double-checking, the correct branch is dev_wifi_suspend, correct? One thing: your code in pmSleep_parse_table_lua ignored the duration value for light sleep, the code to extract it is under the if (cfg->sleep_mode==MODEM_SLEEP_T) conditional branch. I copied it to the else branch and defaulted it to 0 if not present (rather than throwing an error), and it works, but... why is PMSLEEP_SLEEP_MAX_TIME only a 28 bit value? It's max is only 268 seconds? My plan was to have it sleep for an hour, check when the last log was sent and send an unconditional log if 24 hours has past, even if no input occurred. (That way the absence of logs would unambiguously indicate device failure.) I suppose the paradigm still flies with 4.5 minute naps instead of an hour, it only needs a second or two to check time elapsed since last... Just wondering why its max would be less than 32 bits? |
Yes, that is correct.
This was on purpose. The problem with light sleep is if you try to specify a duration other than zero, which gets changed to FPM_SLEEP_MAX_TIME, the ESP8266 does not enter LIGHT_SLEEP(~3mA or less), but instead goes into MODEM_SLEEP (~15 mA) and does not suspend the CPU, therefore, Lua is still able to respond to commands received via serial. This is not the expected behavior for the function
PMSLEEP_SLEEP_MAX_TIME == FPM_SLEEP_MAX_TIME-1
The limit |
@dnc40085 So passing it max time -1 causes it to sleep indefinitely... that's intuitive! :-) It doesn't seem like any of the edge transitions wake it up, only level. And interesting that pin value is the numeric part of its GPIO name, e.g., passing 0 for GPIO0 instead of its IO index. (Not complaining, just observing.) :-) The problem I'm having is that my code, which runs fine on a Docker build, now runs out of memory, it's not even close. I still start out with 45K -- maybe it isn't releasing modules like it used to? There's a point in my app just before it loads a fair-sized module, I used to have 23K available, now I have 8.5K. I looked through user_*.h... is there something I need to comment out? |
@marcelstoer I believe that this issue can be closed now that PR #1231 has been merged |
Yep, the only documentation that we're currently missing is IMO #1861. |
Did #725 and #731 made it into official public API? I don't see this function in the docs.
If it is official - can you document its behaviour please? What should users expect from it, what will
wifi.sta.status()
return when in sleep, do I need to set wifi config and/or connect anew after waking up, how it works withwifi.autoconnect(1)
etc.I tried to use it using cloud-built
nodemcu-master-11-modules-2016-02-29-10-49-49-integer
firmware - after putting wifi to sleep withwifi.sleep(1)
wifi.sta.status()
returns 255. After waking it up (wifi.sleep(0)
)wifi.sta.status()
also returns 255 and after trying to connect to WiFi I'm getting some garbage on serial console (using ESPlorer), losing serial communication with the module and have to restart it. Tried all of the above using eitherwifi.sleeptype(wifi.LIGHT_SLEEP)
orwifi.sleeptype(wifi.MODEM_SLEEP)
- same results. I'm not claiming it's a bug (yet) - because I don't know what to expect at this point :)The text was updated successfully, but these errors were encountered: