Skip to main content

Device Sleep And Pause States Explained

How impOS And Squirrel Manage Low-Power Operation

The imp API provides a number of facilities designed to put the imp to sleep: in other words, into a state in which it is not actively running code. These features support a range of use cases, from managing intervals between messages sent to peripherals, to allowing the imp to enter low-power states to conserve battery charge.

This guide describes each of the imp’s sleep and pause states, and broadly when and how they should be used. For more detailed guidance on reducing the power consumption of specific imps, please see your module’s design guide.

imp Sleep And Pause States

Pause

An imp is said to be paused when Squirrel operation is briefly suspended. Any imp can be paused at any time by calling the imp API method imp.sleep() and passing a sleep period of 20ms or less. impOS™ places the imp in a ‘busy wait’ state for the requested period: it is awake, but the Squirrel VM is suspended. Application code becomes unresponsive to incoming messages, but the impOS networking stack will acknowledge and queue incoming data in the background.

Pausing for such short periods of time does not reduce the imp’s power consumption. It is typically used to halt the imp for a fixed period of time: for example, when a connected device might need a fixed interval between messages telling it to power up and then to initialize.

If you do not want your code to block, you can use imp.wakeup() with a short timer period. But you should note that imp.sleep() pauses of 20ms or less are rounded up to the nearest microsecond, whereas imp.wakeup() timers are rounded to the nearest 10ms. Additionally, timer-driven callbacks are added to the execution queue when the timer fires — they do not interrupt Squirrel. See Scheduling Future Events, below, for more information.

Shallow Sleep/Idle

If Squirrel has come to the end of its current code path, impOS runs any handler that has been registered by calling imp.onidle(). Once such a callback completes, or immediately if no callback has been registered, impOS puts the imp into a very low power state, called ‘Shallow Sleep’. impOS continues to maintain the network connection — unless this is explicitly disabled in code — and to check for timer fires (see Scheduling Future Events).

The imp is also put into Shallow Sleep if imp.sleep() is passed a period greater than 20ms. However, in this case both Squirrel and impOS™ execution are blocked. This makes the imp unresponsive, even to incoming messages from the server. Therefore for long periods (20ms or greater) it is better to use imp.wakeup() to register a timer and then allow the imp to idle. You will get comparable power conservation, but impOS will be able to continue to monitor the server connection. Either way, the pause or timer period that you specify will be rounded to the nearest 10ms.

The power saving achieved in Shallow Sleep varies according to the imp module in use, and what peripherals and timers are in play when the imp enters Shallow Sleep. The lowest power consumption level that can be achieved in Shallow Sleep is reached when:

  • WiFi is off.
  • BlinkUp is off.
  • No PWMs are operating.
  • No UARTs are open for receive (transmit-only ones are fine).
  • A 32KHz crystal is fitted.
  • No imp.wakeup() timer is due to fire for at least 200ms.

However, even without being in every one of these circumstances, all imps will show significant power savings in Shallow Sleep over Pause and fully awake states.

Deep Sleep

The imp API method imp.deepsleepfor() immediately puts the imp entirely into Deep Sleep. Squirrel code is halted, wireless subsystems are powered down, and the imp CPU is put into an ultra-low power state consuming just microamps. The imp is all but shut down: it is only running a basic wake-up timer (not related to imp.wakeup()). This is the lowest power state that an imp can reach while it is connected to power.

If you are using an imp005 in your application, you should note that this module does not support Deep Sleep.

When the imp wakes, whether by a timer or because its wake pin has been asserted, Squirrel code restarts from the top. The only thing preserved is the nv table, on those imps that provide it (see the nv documentation for details). The network sub-system remains powered down until your application code calls an API method that requires a connection to the server.

A given imp’s wake-up pin — shown in the table below — must be configured by Squirrel before it can be used. If subsequently triggered, it will bring the imp out of sleep before the requested sleep time has elapsed.

imp imp001 imp002 imp003 imp004m imp005 imp006 impC001
Wake Pin(s) 1 1 W W N/A V, W* W

* impOS does not report which pin triggered the wake.

imp.deepsleepfor() does not cleanly close the network connection, so it is most often used when the imp’s current radio has already been disconnected. The imp API method server.sleepfor() does cleanly close the connection before putting the imp to sleep. Either method can be used to get years of battery life. Neither method should be called until the imp goes idle (Squirrel has come to the end of its current code path). This can be ensured by placing the above methods in a function registered using imp.onidle():

imp.onidle(function() {
    server.sleepfor(1800);      // 30 minutes
});

The imp API methods imp.deepsleepuntil() and server.sleepuntil() operate as described above but provide an alternative way of specifying the sleep period.

An imp can also enter Deep Sleep in two other situations. First, if it is set to SUSPEND_ON_ERROR mode (using server.setsendtimeoutpolicy()) and it fails to connect, then it will be placed in Deep Sleep. It will remain in this state for nine minutes, after which the Squirrel VM is restarted and impOS attempts to reconnect to the server.

If a Squirrel error occurs or impOS receives a ‘new Squirrel available’ notification from the server, the Squirrel VM will be shut down and the imp will attempt to get new application code. If this fails, the imp will again be placed in Deep Sleep for nine minutes, irrespective of its server.setsendtimeoutpolicy() mode. When this period elapses, the imp awakes, re-runs its existing Squirrel code and attempts to connect. What happens if this connection attempt fails does depend on the applied server.setsendtimeoutpolicy() mode. Please see the Network State Diagram for details.

Reduce Power Consumption While Awake

To reduce the imp’s power consumption while staying connected to WiFi, use:

imp.setpowersave(true);

This drops the imp’s WiFi sub-system down to around one tenth of its normal operational power consumption, with only a small impact on incoming message latency.

If you are using the imp004m, you should note that imp.setpowersave() has no effect on this module unless you have connected a 32KHz crystal to the imp and have notified impOS that the crystal is present. The OS is notified by applying a special setting in the NVRAM. For further details, please contact support.

Scheduling Future Events

The imp API method imp.wakeup() registers a function that will be called when a certain period of time, provided in seconds but with centisecond (10ms) granularity, has elapsed. Memory permitting, you can have as many of these registered at any one time as you like. A timer-triggered callback function can’t interrupt running Squirrel code — the function will be queued and run when the imp next goes idle.

imp.wakeup() can also be used in agent code to trigger future agent actions. However, unlike the device implementation, on the agent there is a maximum limit of 50 timers at any one time. Neither agent nor device can directly trigger events on the other by using this method, ie. the registered function has to exist in the calling code.