Sketch structure and timing
All Arduino/ESP32 sketches follow the same basic pattern:
setup()runs once at the start.loop()runs over and over again.
Understanding this, and how to deal with time, is essential for responsive projects.
1. Basic sketch structure
Minimal skeleton:
1 2 3 4 5 6 7 | |
Example:
1 2 3 4 5 6 7 8 9 10 11 12 | |
2. Why delay() can be a problem
delay(ms) blocks the whole loop() for the given time:
- The ESP32 does nothing else in your sketch during a delay.
- Multiple long delays can make your project feel “frozen” or sluggish.
Use delay() for:
- Simple first examples (like
Blink). - Very small delays (a few milliseconds) when needed.
For more complex projects, use non‑blocking timing with millis().
3. Non‑blocking timing with millis()
millis() returns the number of milliseconds since the board started.
You can compare it to previous timestamps to decide when to do something, without blocking.
Example: blink without delay()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
This pattern lets you handle multiple tasks (reading sensors, updating a display, etc.) in a single loop().
4. Simple "state machine" pattern
As projects grow, it helps to think in states (e.g. IDLE, MEASURING, ALARM) instead of one big block of code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
You can combine the millis() pattern with this state machine to build responsive, readable sketches.