MojoScale Forum
Login Sign up

How do I run a function every few seconds without blocking the ESP32?

Asked 3 weeks, 6 days ago in Firmware by Mojo Scale
Ask Question
1 Answers
44 Views
0 Comments

I'm trying to periodically read a sensor and send its value, but I don't want to use a loop with a sleep because the device also needs to handle other work.

For example, I want something like this to run every 5 seconds:

def read_sensor():
    print("reading sensor")

Is there a timer/scheduler in MojoScale Studio that can call this function automatically? Also, can I pass arguments to the callback?

Answered updated 3 weeks, 6 days ago
Log in to comment.
1 Answer
OK Accepted

Yes — you don't need to keep the ESP32 stuck in a while True + sleep loop for this. system.schedule() is meant for exactly this kind of periodic work.

For example, to read a sensor every 5 seconds:

import system

def read_sensor():
    print("reading sensor")

system.schedule("sensor_reader", 5000, 5000, -1, read_sensor)

This waits 5 seconds, calls read_sensor(), and then keeps calling it every 5 seconds. The -1 means it will continue indefinitely.

The useful part is that your script isn't sitting inside a blocking sleep loop while it waits. The device can continue dealing with things like Wi-Fi, MQTT messages, callbacks, or camera work between runs.

You can also pass arguments directly to your scheduled function:

import system

def read_sensor(sensor_name, pin):
    print("reading", sensor_name, "on pin", pin)

system.schedule(
    "dht_reader",
    5000,
    5000,
    -1,
    read_sensor,
    "dht22",
    4
)

Every five seconds that effectively calls:

read_sensor("dht22", 4)

The first argument, "dht_reader", is more than just a label. It gives the scheduled task an identity, which means you can stop it later:

system.cancel("dht_reader")

One easy mistake to avoid: pass the function itself, not its name as a string.

# Correct
system.schedule("sensor_reader", 5000, 5000, -1, read_sensor)

# Wrong
system.schedule("sensor_reader", 5000, 5000, -1, "read_sensor")

Studio handles converting the function reference into the callback representation expected by the firmware.

So for periodic sensor reads, telemetry publishing, status checks, and similar background jobs, I'd generally use system.schedule() rather than building the application around a sleeping loop.

For reference, the full signature is:

system.schedule(name, interval_ms, delay_ms, repeats, callback, *callback_args)

Use delay_ms=0 if you want the first run immediately, and use repeats=-1 when the task should keep running until you explicitly cancel it.

answered by Mojo Scale 3 weeks, 6 days ago edited 3 weeks, 6 days ago
Your Answer
Log in to answer this question.