Saltar al contenido principal

Módulo Power

Power duerme la placa para que gaste menos: sleep() la pone en modo light sleep (sueño ligero) hasta que la despierta una de las fuentes que hayas puesto: un tiempo, un pin RTC o uno o varios pines GPIO. Al despertar, el programa sigue justo después de sleep(), con todas sus variables. Es útil en aparatos que funcionan con batería o con un panel solar.

En Windows se simula: sleep() espera y wakeReason() siempre dice que despertó el temporizador, para que pruebes la lógica del programa antes de llevarlo a la placa.

Ilustración del módulo Power de JARU para dormir la placa y despertarla

use Power

Para dormir la placa, pon una o más fuentes de despertar (wakeOnTimer, wakeOnPin o wakeOnGPIO) y llama a sleep().

Plataformas​

WindowsESP32 / ESP32-S3ESP32-P4ESP32-S31
sleep()Espera el tiempo de wakeOnTimer(), solo la primera vez; sin él, 100 msDuerme la placa en light sleepDuerme la placa en light sleepDuerme la placa en light sleep
wakeOnPin()No hace nadaUn pin RTC; despierta con WAKE_EXT0Un pin RTC; despierta con WAKE_EXT1Un pin RTC; despierta con WAKE_EXT1
wakeOnGPIO()No hace nada, ni comprueba el pinCualquier pinCualquier pinCualquier pin
wakeReason()Siempre WAKE_TIMERLa causa del último despertarLa causa del último despertarLa causa del último despertar
  • En la placa, cada ejecución del programa empieza sin fuentes de despertar, aunque la placa no se haya reiniciado: las que pusiera el programa anterior no cuentan.
  • En la placa, sleep() espera 100 ms antes de dormir, para que salga lo que quede por escribir, y otros 100 ms al despertar.
La Waveshare ESP32-S3-Touch-LCD-2.8 se queda sin USB al dormir

Esta placa se conecta al PC por el USB del propio chip. Desde el primer Power.sleep(), el PC deja de verla: no llega nada al monitor serie y no se le puede grabar nada. Para volver a grabarla, arráncala en modo de descarga: reiníciala con el botón BOOT pulsado. Si la vas a dormir, prueba antes el programa sin Power.sleep().

Funciones​

FunciónQué haceDevuelve
wakeOnTimer(microsegundos)Despierta la placa pasado un tiempo.true o false
wakeOnPin(pin, nivel)Despierta la placa con un pin RTC.true o false
wakeOnGPIO(pin, nivel)Despierta la placa con un pin cualquiera; se pueden poner varios.true o false
sleep()Duerme la placa hasta que la despierte una de las fuentes.true o false
wakeReason()Dice qué despertó la placa la última vez.Una de las constantes

Los errores no se lanzan: se devuelven, como valor: con un número de argumentos que no es el suyo, ERR_INVALID_ARG_NUMBER, y con un argumento que no es un número, ERR_TYPE_MISMATCH. En la placa, además, se escriben en el monitor serie. Más sobre los valores de error en Errores y excepciones.

wakeOnTimer​

wakeOnTimer(microsegundos) pone un temporizador como fuente de despertar: la placa se despierta cuando pasa ese tiempo.

use Power

// Despertar a los 5 segundos (5000000 microsegundos)
Power.wakeOnTimer(5000000)
Power.sleep()

println("¡Despertado por el temporizador!")

Parámetros:

  • microsegundos: el tiempo hasta despertar, en microsegundos (entero o decimal; cuenta la parte entera).

Devuelve: true si lo ha puesto, false si no.

Segundos a microsegundos

Multiplica los segundos por un millón: 30 segundos son 30000000 microsegundos. Llama a wakeOnTimer() antes de cada sleep(): en Windows, el tiempo solo vale para el siguiente sleep().

wakeOnPin​

wakeOnPin(pin, nivel) pone un pin RTC como fuente de despertar: la placa se despierta cuando el pin llega a ese nivel.

use Power

// Despertar cuando el pin 33 pase a HIGH
Power.wakeOnPin(33, HIGH)
Power.sleep()

println("¡Despertado por el pin!")

Parámetros:

  • pin: número de pin GPIO (tiene que ser un pin RTC)
  • nivel: el nivel que despierta la placa (HIGH o LOW)

Devuelve: true si lo ha puesto, false si no (por ejemplo, con un pin que no es RTC).

Pines RTC

Solo los pines RTC sirven para wakeOnPin(). En el ESP32 son 0, 2, 4, 12, 13, 14, 15, 25, 26, 27, 32, 33, 34, 35, 36, 37, 38 y 39. En las demás placas, mira qué pines son RTC en la documentación de su chip. Para usar cualquier pin, o varios, está wakeOnGPIO().

En el ESP32 y el ESP32-S3, la placa despierta con WAKE_EXT0; en el ESP32-P4 y el ESP32-S31, con WAKE_EXT1.

wakeOnGPIO​

La función wakeOnGPIO(pin, nivel) configura un pin GPIO como fuente de despertar. A diferencia de wakeOnPin(), vale cualquier pin, no solo los RTC, y se pueden poner varios: cada llamada añade uno.

use Power
use GPIO

// Dos botones entre el pin y GND, con la resistencia interna a 3,3 V
GPIO.pinmode(32, GPIO.PULLUP)
GPIO.pinmode(33, GPIO.PULLUP)

// Despertar cuando se pulse cualquiera de los dos
Power.wakeOnGPIO(32, LOW)
Power.wakeOnGPIO(33, LOW)
Power.sleep()

println("¡Despertado por un botón!")

Parámetros:

  • pin: número de pin GPIO
  • nivel: el nivel que despierta la placa (HIGH o LOW)

Devuelve: true si lo ha puesto, false si el pin no existe en la placa.

A tener en cuenta
  • Cada llamada añade un pin, o le cambia el nivel si ya estaba puesto. Los pines se quedan puestos para los siguientes sleep().
  • Configura antes el pin como entrada con GPIO.pinmode().
  • Si el pin ya está en ese nivel cuando llamas a sleep(), la placa no llega a dormirse: sleep() devuelve false enseguida. Con un botón, espera a que se suelte antes de volver a dormir.
  • Si el pin tiene además una interrupción de GPIO.onInterrupt(), la interrupción sigue funcionando al despertar.

sleep​

sleep() pone la placa en light sleep, el modo de bajo consumo, hasta que la despierte una de las fuentes que hayas puesto.

use Power

// Despertar con el temporizador
Power.wakeOnTimer(10000000) // 10 segundos

println("Entrando en modo de bajo consumo...")
Power.sleep()
println("¡Despertado!")

Devuelve: true si la placa ha dormido, false si no ha llegado a dormirse (por ejemplo, porque un pin de wakeOnGPIO() ya estaba en su nivel).

Light sleep y deep sleep

El light sleep conserva el estado de la CPU y la RAM, así que el programa sigue justo donde se quedó. El deep sleep reinicia el programa entero. El módulo Power solo hace light sleep.

wakeReason​

La función wakeReason() devuelve la causa del último despertar. Con ella, el programa puede hacer una cosa u otra según lo que haya despertado la placa.

use Power

// Verificar la causa del despertar
var razon = Power.wakeReason()

if (razon == Power.WAKE_TIMER) then
println("Despertado por el temporizador")
elsif (razon == Power.WAKE_EXT0) then
println("Despertado por un pin RTC")
elsif (razon == Power.WAKE_GPIO) then
println("Despertado por un GPIO")
else
println("Razón desconocida o primer arranque")
end

Devuelve: un entero que corresponde a una de las constantes de causa de despertar.

Constantes​

Las causas de despertar que devuelve wakeReason():

ConstanteValorQué despertó la placa
Power.WAKE_UNDEFINED0Nada definido: es el primer arranque del dispositivo, o la causa no se conoce.
Power.WAKE_TIMER2El temporizador configurado con wakeOnTimer().
Power.WAKE_EXT03Un pin RTC (ext0): es lo que usa wakeOnPin() en el ESP32 y el ESP32-S3.
Power.WAKE_EXT14Un pin RTC (ext1): es lo que usa wakeOnPin() en el ESP32-P4 y el ESP32-S31.
Power.WAKE_GPIO6Un GPIO configurado con wakeOnGPIO().
Power.WAKE_UART7Actividad en el puerto UART. Power no tiene ninguna función para ponerla como fuente.
use Power

if (Power.wakeReason() == Power.WAKE_UNDEFINED) then
println("Primer arranque o causa desconocida")
end

Ejemplo completo​

Sensor con ahorro de energía​

Lee un sensor cada 30 segundos, o cuando se pulsa un botón, y duerme entre lectura y lectura con la pantalla apagada.

use Power
use GPIO
use Display

// Configuración inicial
Display.open(320, 240)
var draw = Display.draw

// El sensor, en el pin 34
GPIO.pinmode(34, GPIO.INPUT)

// Intervalo de lectura: 30 segundos
var intervalo = 30000000

func mostrarTemperatura(temp)
draw.cls(0x000000)
draw.color = 0x00FF00
draw.text(60, 100, "Temperatura: " + temp.toString() + " C")
Display.update()
end

func leerSensor()
// Una lectura simulada de temperatura
return 20 + (GPIO.aread(34) / 100)
end

// Bucle principal
while (true)
// ¿Qué la ha despertado?
var razon = Power.wakeReason()

if (razon == Power.WAKE_TIMER) then
println("Lectura programada")
elsif (razon == Power.WAKE_EXT0) then // WAKE_EXT1 en el ESP32-P4 y el ESP32-S31
println("Lectura pedida con el botón")
end

// Leer y mostrar la temperatura
var temp = leerSensor()
mostrarTemperatura(temp)

// Dos segundos para ver la pantalla
pause(2000)

// Las fuentes de despertar
Power.wakeOnTimer(intervalo)
Power.wakeOnPin(33, HIGH) // el botón de lectura

// Apagar la pantalla y dormir
Display.backlight(0)
Power.sleep()

// Al despertar, encender la pantalla
Display.backlight(1)
end

Detector de movimiento​

Un sensor PIR despierta la placa, que avisa por MQTT y vuelve a dormir.

use Power
use GPIO
use MQTT

// El pin del sensor PIR
var pinPIR = 27

// La conexión al broker MQTT (servidor, puerto, credenciales) se configura en el perfil de la placa

// Despertar con el sensor
Power.wakeOnPin(pinPIR, HIGH)

while (true)
// ¿Ha despertado por el movimiento? (WAKE_EXT1 en el ESP32-P4 y el ESP32-S31)
if (Power.wakeReason() == Power.WAKE_EXT0) then
println("¡Movimiento detectado!")
MQTT.publish("casa/alarma", "movimiento")

// Esperar a que el sensor se calme
pause(5000)
end

// Volver a dormir
Power.wakeOnPin(pinPIR, HIGH)
Power.sleep()
end

Trampas y problemas conocidos​

  • En Windows no duerme nada: sleep() solo espera, y wakeReason() siempre devuelve WAKE_TIMER, también antes del primer sleep().
  • El tiempo de wakeOnTimer() va en microsegundos, no en milisegundos como pause() o Timer.
  • wakeOnPin() despierta con WAKE_EXT0 o con WAKE_EXT1 según el chip. Si tu programa va a varias placas, compara con las dos.
  • Con un pin de wakeOnGPIO() ya en su nivel, la placa no se duerme: sleep() devuelve false enseguida.
  • La Waveshare ESP32-S3-Touch-LCD-2.8 se queda sin USB al dormir: ver Plataformas.
  • Los errores se devuelven, no se lanzan: try no los captura.

Todos los problemas conocidos de JARU, juntos, están en Problemas conocidos.