Power module
Power puts the board to sleep so that it uses less power: sleep() puts it in light sleep mode until one of the sources you set wakes it up: a time, an RTC pin or one or several GPIO pins. When it wakes up, the program carries on right after sleep(), with all its variables. It is useful in devices that run on a battery or a solar panel.
On Windows it is simulated: sleep() waits and wakeReason() always says the timer woke it up, so that you can test the logic of the program before taking it to the board.

use Power
To put the board to sleep, set one or more wake-up sources (wakeOnTimer, wakeOnPin or wakeOnGPIO) and call sleep().
Platforms
| Windows | ESP32 / ESP32-S3 | ESP32-P4 | ESP32-S31 | |
|---|---|---|---|---|
sleep() | Waits the time of wakeOnTimer(), only the first time; without it, 100 ms | Puts the board in light sleep | Puts the board in light sleep | Puts the board in light sleep |
wakeOnPin() | Does nothing | An RTC pin; wakes up with WAKE_EXT0 | An RTC pin; wakes up with WAKE_EXT1 | An RTC pin; wakes up with WAKE_EXT1 |
wakeOnGPIO() | Does nothing, and does not check the pin | Any pin | Any pin | Any pin |
wakeReason() | Always WAKE_TIMER | The cause of the last wake-up | The cause of the last wake-up | The cause of the last wake-up |
- On the board, each run of the program starts with no wake-up sources, even if the board has not restarted: the ones the previous program set do not count.
- On the board,
sleep()waits 100 ms before sleeping, so that whatever is left to print gets out, and another 100 ms after waking up.
This board connects to the PC through the chip's own USB. From the first Power.sleep(), the PC no longer sees it: nothing reaches the serial monitor and nothing can be flashed to it. To flash it again, start it in download mode: restart it with the BOOT button held down. If you are going to put it to sleep, test the program without Power.sleep() first.
Functions
| Function | What it does | Returns |
|---|---|---|
wakeOnTimer(microseconds) | Wakes the board up after a while. | true or false |
wakeOnPin(pin, level) | Wakes the board up with an RTC pin. | true or false |
wakeOnGPIO(pin, level) | Wakes the board up with any pin; you can set several. | true or false |
sleep() | Puts the board to sleep until one of the sources wakes it up. | true or false |
wakeReason() | Tells what woke the board up last time. | One of the constants |
The errors are not thrown: they are returned, as a value: with the wrong number of arguments, ERR_INVALID_ARG_NUMBER, and with an argument that is not a number, ERR_TYPE_MISMATCH. On the board, they are also written to the serial monitor. More on error values in Errors and exceptions.
wakeOnTimer
wakeOnTimer(microseconds) sets a timer as a wake-up source: the board wakes up when that time has passed.
use Power
// Wake up after 5 seconds (5000000 microseconds)
Power.wakeOnTimer(5000000)
Power.sleep()
println("Awakened by the timer!")
Parameters:
microseconds: the time until waking up, in microseconds (integer or decimal; the whole part counts).
Returns: true if it set it, false if not.
Multiply the seconds by a million: 30 seconds are 30000000 microseconds. Call wakeOnTimer() before each sleep(): on Windows, the time only applies to the next sleep().
wakeOnPin
wakeOnPin(pin, level) sets an RTC pin as a wake-up source: the board wakes up when the pin reaches that level.
use Power
// Wake up when pin 33 goes HIGH
Power.wakeOnPin(33, HIGH)
Power.sleep()
println("Awakened by the pin!")
Parameters:
pin: GPIO pin number (it has to be an RTC pin)level: the level that wakes the board up (HIGHorLOW)
Returns: true if it set it, false if not (for example, with a pin that is not RTC).
Only the RTC pins work with wakeOnPin(). On the ESP32 they are 0, 2, 4, 12, 13, 14, 15, 25, 26, 27, 32, 33, 34, 35, 36, 37, 38 and 39. On the other boards, look up which pins are RTC in the documentation of their chip. To use any pin, or several, there is wakeOnGPIO().
On the ESP32 and the ESP32-S3, the board wakes up with WAKE_EXT0; on the ESP32-P4 and the ESP32-S31, with WAKE_EXT1.
wakeOnGPIO
The wakeOnGPIO(pin, level) function configures a GPIO pin as a wake-up source. Unlike wakeOnPin(), it works with any pin, not just the RTC ones, and you can set several: each call adds one.
use Power
use GPIO
// Two buttons between the pin and GND, with the internal pull-up to 3.3 V
GPIO.pinmode(32, GPIO.PULLUP)
GPIO.pinmode(33, GPIO.PULLUP)
// Wake up when either of them is pressed
Power.wakeOnGPIO(32, LOW)
Power.wakeOnGPIO(33, LOW)
Power.sleep()
println("Awakened by a button!")
Parameters:
pin: GPIO pin numberlevel: the level that wakes the board up (HIGHorLOW)
Returns: true if it set it, false if the pin doesn't exist on the board.
- Each call adds a pin, or changes its level if it was already set. The pins stay set for the following
sleep()calls. - Configure the pin as an input with
GPIO.pinmode()first. - If the pin is already at that level when you call
sleep(), the board doesn't go to sleep:sleep()returnsfalseright away. With a button, wait until it's released before going back to sleep. - If the pin also has a
GPIO.onInterrupt()interrupt, the interrupt keeps working after waking up.
sleep
sleep() puts the board in light sleep, the low-power mode, until one of the sources you set wakes it up.
use Power
// Wake up with the timer
Power.wakeOnTimer(10000000) // 10 seconds
println("Entering sleep mode...")
Power.sleep()
println("Awakened!")
Returns: true if the board has slept, false if it did not get to sleep (for example, because a wakeOnGPIO() pin was already at its level).
Light sleep keeps the state of the CPU and the RAM, so the program carries on right where it left off. Deep sleep restarts the whole program. The Power module only does light sleep.
wakeReason
The wakeReason() function returns the cause of the last wake-up. This allows the program to take different actions depending on what triggered the wake-up.
use Power
// Check wake-up cause
var reason = Power.wakeReason()
if (reason == Power.WAKE_TIMER) then
println("Awakened by timer")
elsif (reason == Power.WAKE_EXT0) then
println("Awakened by RTC pin")
elsif (reason == Power.WAKE_GPIO) then
println("Awakened by GPIO")
else
println("Unknown reason or first boot")
end
Returns: an integer that corresponds to one of the wake-up cause constants.
Constants
The wake-up causes that wakeReason() returns:
| Constant | Value | What woke the board up |
|---|---|---|
Power.WAKE_UNDEFINED | 0 | Nothing defined: it is the device's first boot, or the cause is unknown. |
Power.WAKE_TIMER | 2 | The timer configured with wakeOnTimer(). |
Power.WAKE_EXT0 | 3 | An RTC pin (ext0): it's what wakeOnPin() uses on the ESP32 and the ESP32-S3. |
Power.WAKE_EXT1 | 4 | An RTC pin (ext1): it's what wakeOnPin() uses on the ESP32-P4 and the ESP32-S31. |
Power.WAKE_GPIO | 6 | A GPIO configured with wakeOnGPIO(). |
Power.WAKE_UART | 7 | Activity on the UART port. Power has no function to set it as a source. |
use Power
if (Power.wakeReason() == Power.WAKE_UNDEFINED) then
println("First boot or unknown cause")
end
Full example
Sensor with power saving
It reads a sensor every 30 seconds, or when a button is pressed, and sleeps between readings with the screen off.
use Power
use GPIO
use Display
// Initial setup
Display.open(320, 240)
var draw = Display.draw
// The sensor, on pin 34
GPIO.pinmode(34, GPIO.INPUT)
// Reading interval: 30 seconds
var interval = 30000000
func showTemperature(temp)
draw.cls(0x000000)
draw.color = 0x00FF00
draw.text(60, 100, "Temperature: " + temp.toString() + " C")
Display.update()
end
func readSensor()
// A simulated temperature reading
return 20 + (GPIO.aread(34) / 100)
end
// Main loop
while (true)
// What woke it up?
var reason = Power.wakeReason()
if (reason == Power.WAKE_TIMER) then
println("Scheduled reading")
elsif (reason == Power.WAKE_EXT0) then // WAKE_EXT1 on the ESP32-P4 and the ESP32-S31
println("Reading asked for with the button")
end
// Read and show the temperature
var temp = readSensor()
showTemperature(temp)
// Two seconds to see the screen
pause(2000)
// The wake-up sources
Power.wakeOnTimer(interval)
Power.wakeOnPin(33, HIGH) // the reading button
// Turn the screen off and sleep
Display.backlight(0)
Power.sleep()
// When it wakes up, turn the screen on
Display.backlight(1)
end
Motion detector
A PIR sensor wakes the board up, which sends a notice over MQTT and goes back to sleep.
use Power
use GPIO
use MQTT
// The PIR sensor pin
var pirPin = 27
// The MQTT broker connection (server, port, credentials) is set in the board profile
// Wake up with the sensor
Power.wakeOnPin(pirPin, HIGH)
while (true)
// Did it wake up because of the motion? (WAKE_EXT1 on the ESP32-P4 and the ESP32-S31)
if (Power.wakeReason() == Power.WAKE_EXT0) then
println("Motion detected!")
MQTT.publish("home/alarm", "motion")
// Wait for the sensor to settle
pause(5000)
end
// Go back to sleep
Power.wakeOnPin(pirPin, HIGH)
Power.sleep()
end
Pitfalls and known issues
- On Windows nothing sleeps:
sleep()only waits, andwakeReason()always returnsWAKE_TIMER, also before the firstsleep(). - The time of
wakeOnTimer()is in microseconds, not in milliseconds likepause()orTimer. wakeOnPin()wakes up withWAKE_EXT0or withWAKE_EXT1depending on the chip. If your program goes to several boards, compare with both.- With a
wakeOnGPIO()pin already at its level, the board does not go to sleep:sleep()returnsfalseright away. - The Waveshare ESP32-S3-Touch-LCD-2.8 loses its USB when it sleeps: see Platforms.
- Errors are returned, not thrown:
trydoes not catch them.
All the known issues of JARU, together, are in Known issues.