should I be declaring
last_ms as a global variable instead of
Local static is better, as it limits the scope of the variable to just
where it is needed. Consider making it global only if the code is part
of a tutorial meant for beginners which may be confused by the keyword
should this code be at the beginning or end of loop?
The conditional early return only makes sense if
loop() has nothing
more to do once the sensor data is handled, thus this should go at the
very end of
loop(). However, if
loop() does more than just handle
this data, I think it would be cleaner to avoid the early return: either
put this in a separate function (which can return early), or condition
the handling of the sensor on
ms - last_ms >= 10.
My understanding is we are basically checking how long the previous
No. The test is looking at how much time has elapsed since the previous
last_ms was updated, which could be many
loop() iterations ago.
But doesn't that mean that we might still get deviation from 100 Hz
due to the time it takes to complete loop (about 2-5ms in my case), so
effectively it's 10 ms + loop complete time?
Indeed. With this logic, 10 ms is the minimum time between calls
sensor_data(). If you want to ensure an accurate average polling
time, you should update
last_ms by adding 10. You will still have
sole jitter though.
A small note about
millis(): since the value is updated every
1.024 ms, it occasionally has to jump by two units at once, and has
therefore 1 ms of jitter. For a period as short as 10 ms, I
would rather use
micros(). For example:
const uint32_t POLLING_PERIOD = 10000; // 1e4 us = 10 ms
// Call this from loop()
static uint32_t last_us;
if (micros() - last_us < POLLING_PERIOD) return;
last_us += POLLING_PERIOD;
Edit: About why
last_us has to be incremented by a constant
amount, consider this alternative:
static uint32_t last_us;
uint32_t now = micros()
if (now - last_us < POLLING_PERIOD) return;
last_us = now;
The code following the
if ... return; line will be executed when the
tested condition is false, i.e. when
now - last_us >= POLLING_PERIOD.
It may happen that we sometimes have strict equality (
now - last_us == POLLING_PERIOD) but, since any code execution takes time, sometimes
now - last_us will be strictly larger than
time this happens
last_us will be incremented by more than
POLLING_PERIOD. This means that the small timing errors accumulate.
last_us is updated by adding a constant amount, we still
have timing errors (because of the time needed to execute any code), but
they are not cumulative. In other words, we have jitter, but the
average polling frequency is right.