ESP32 (Arduino IDE): a fixed-rate loop with micros()
Video coming soon
On the ESP32, the loop keeps its own time: micros() gives microseconds since start, and every 20000 µs (fifty times per second) we do our work. We then add the period to the last start time instead of reading micros() again, so small delays never add up.
In this lesson · 3 steps
1What goes where (as in the video)
- Top of the sketch: the rate,
#define SAMPLE_RATE_HZ 50 - Below it: the period,
last_sampleand the counter (delete the old counter line) - In setup:
last_sample = micros();, and no moredelay(1000)
Why?
In the video we paste the code in three parts into the 1.4 sketch, and keep the hello line. The code below replaces the whole sketch in one go; the result is the same.
2Run the loop at SAMPLE_RATE_HZ
ch1_serial.ino · replace everything
micros() minus last_sample is the time since the last run; when it reaches the period, we run the code.
#define SAMPLE_RATE_HZ 50 const unsigned long SAMPLE_PERIOD_US = 1000000UL / SAMPLE_RATE_HZ; unsigned long last_sample = 0; int counter = 0; void setup() { Serial.begin(115200); last_sample = micros(); } void loop() { if (micros() - last_sample >= SAMPLE_PERIOD_US) { last_sample += SAMPLE_PERIOD_US; counter++; Serial.print("counter:"); Serial.print(counter); Serial.print(",time:"); Serial.println(millis()); } }
Why?
The period is one million microseconds divided by fifty: 20000 µs, or 20 ms. Then we add the period to last_sample instead of reading micros() again: each check is a little late, and reading micros() again would move the schedule, but adding the period keeps it fixed. There is no delay: the loop never waits, it just checks the time again and again.
3Check the rate in the serial plotter
- Upload; in the serial plotter press Pause / Clear if it still shows old data, then Connect and choose the port
- Two lines,
counterandtime;timegoes up by 20 on every line → 50 lines per second
Why?
time is in milliseconds and grows much faster than the counter, so next to it the counter looks flat. In the console, time goes up by 20 on each line: fifty lines per second.
Check & troubleshoot
What you should see
- Lines like
counter:226,time:4520 timegoes up by 20 on every line: fifty lines per second- On the plot, the counter looks flat because time grows much faster: that is normal
If it doesn't work
- Rate slowly drifts: use
last_sample += SAMPLE_PERIOD_US, notlast_sample = micros() - Nothing printed: close the Serial Monitor, connect the plotter, check 115200 baud
- The hello line and the 1-second delay from 1.4 are gone: that is expected, because this step replaces the whole sketch
- After about 71 minutes micros() starts again from zero: the subtraction
micros() - last_samplestill works, so the loop keeps its rate
Good to know
- Why a fixed rate? Later we turn gyro readings into an angle by adding up many small steps, so we must know the time between two readings. If the timing is wrong, the angle slowly drifts
- For example, if one run starts 300 µs late, the next deadline is still on the 20 ms grid, so the error does not add up