user72368: I'm using this piece of code to try to poll an IMU sensor at 100 Hz (for a AHRS sensor fusion library).
void loop(void)
{
  // nonblocking code variables
  static uint32_t last_ms;
  uint32_t ms;
  // delay between samples
  ms = millis();
  if (ms - last_ms < 10) return;
  last_ms = ms;

  sensor_data (); //...

My 1st question is should I be declaring last_ms as a global variable instead of static?
Also, should this code be at the beginning or end of loop? My understanding is we are basically checking how long the previous loop took. And if it took less than 10 ms (100 Hz) we do nothing. 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?
Sorry if this is a stupid question.

user42015: The time range your sensor code will be executed is 10ms to 10ms + the execution time of the first part of the loop (until the return) and the execution time outside of loop(). These additional times don't always apply, but in the worst case you can have up to that additional delay (because it means you are checking the millis() value only so often).
The mentioned additional delay is rather short (microseconds realm). Your sensor code is only executed, when the time is reached. As long as you don't disable interrupts, the Timer0 interrupt will continue to count further for millis(), so its value will increase independently from the execution time of your sensor code.
That is as long as the sensor code also doesn't take longer than 10ms (or a bit less, accounting for some overhead). As your sensor code only takes up to 5ms (according to your question), you should be safe here.
If millis() is accurate enough for you I cannot say. Thats up to your exact requirements. For more accurate timing an own timer interrupt would be better, though that also limits you with what you can do. Inside an interrupt you cannot execute code, that relies on interrupts (like communication over Serial or I2C). Depending on your sensors using your above code is already enough and should work good.

should I be declaring last_ms as a global variable instead of static?

There is no definitive answer to that, but generally it is good to limit the scope of variables to the minimum needed (to avoid possible conflicts). last_ms is not needed anywhere else, so creating it locally and static is a good way to do it. Memory wise it doesn't really make a difference.

user7508: 
should I be declaring last_ms as a global variable instead of
static?

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
static.

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
loop took.

No. The test is looking at how much time has elapsed since the previous
time 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
to 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()
void handle_sensor()
{
    static uint32_t last_us;
    if (micros() - last_us < POLLING_PERIOD) return;
    last_us += POLLING_PERIOD;
    sensor_data();
    // ...
}

Edit: About why last_us has to be incremented by a constant
amount, consider this alternative:
void handle_sensor()
{
    static uint32_t last_us;
    uint32_t now = micros()
    if (now - last_us < POLLING_PERIOD) return;
    last_us = now;
    sensor_data();
    // ...
}

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 POLLING_PERIOD. Every
time this happens last_us will be incremented by more than
POLLING_PERIOD. This means that the small timing errors accumulate.
If, instead, 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.

72368: <p>I'm using this piece of code to try to poll an IMU sensor at 100 Hz (for a AHRS sensor fusion library).</p>
<pre><code>void loop(void)
{
  // nonblocking code variables
  static uint32_t last_ms;
  uint32_t ms;
  // delay between samples
  ms = millis();
  if (ms - last_ms &lt; 10) return;
  last_ms = ms;

  sensor_data (); //...
</code></pre>
<p>My 1st question is should I be declaring <code>last_ms</code> as a global variable instead of static?</p>
<p>Also, should this code be at the beginning or end of loop? My understanding is we are basically checking how long the previous loop took. And if it took less than 10 ms (100 Hz) we do nothing. 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?</p>
<p>Sorry if this is a stupid question.</p>
 42015: <p>The time range your sensor code will be executed is 10ms to 10ms + the execution time of the first part of the loop (until the return) and the execution time outside of <code>loop()</code>. These additional times don't always apply, but in the worst case you can have up to that additional delay (because it means you are checking the <code>millis()</code> value only so often).</p>
<p>The mentioned additional delay is rather short (microseconds realm). Your sensor code is only executed, when the time is reached. As long as you don't disable interrupts, the Timer0 interrupt will continue to count further for <code>millis()</code>, so its value will increase independently from the execution time of your sensor code.</p>
<p>That is as long as the sensor code also doesn't take longer than 10ms (or a bit less, accounting for some overhead). As your sensor code only takes up to 5ms (according to your question), you should be safe here.</p>
<p>If <code>millis()</code> is accurate enough for you I cannot say. Thats up to your exact requirements. For more accurate timing an own timer interrupt would be better, though that also limits you with what you can do. Inside an interrupt you cannot execute code, that relies on interrupts (like communication over Serial or I2C). Depending on your sensors using your above code is already enough and should work good.</p>
<blockquote>
<p>should I be declaring last_ms as a global variable instead of static?</p>
</blockquote>
<p>There is no definitive answer to that, but generally it is good to limit the scope of variables to the minimum needed (to avoid possible conflicts). <code>last_ms</code> is not needed anywhere else, so creating it locally and static is a good way to do it. Memory wise it doesn't really make a difference.</p>
 7508: <blockquote>
<p>should I be declaring <code>last_ms</code> as a global variable instead of
static?</p>
</blockquote>
<p>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
<code>static</code>.</p>
<blockquote>
<p>should this code be at the beginning or end of loop?</p>
</blockquote>
<p>The conditional early return only makes sense if <code>loop()</code> has nothing
more to do once the sensor data is handled, thus this should go at the
very end of <code>loop()</code>. However, if <code>loop()</code> 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 <code>ms - last_ms &gt;= 10</code>.</p>
<blockquote>
<p>My understanding is we are basically checking how long the previous
loop took.</p>
</blockquote>
<p>No. The test is looking at how much time has elapsed since the previous
time <code>last_ms</code> was updated, which could be many <code>loop()</code> iterations ago.</p>
<blockquote>
<p>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?</p>
</blockquote>
<p>Indeed. With this logic, 10 ms is the <em>minimum</em> time between calls
to <code>sensor_data()</code>. If you want to ensure an accurate <em>average</em> polling
time, you should update <code>last_ms</code> by adding 10. You will still have
sole jitter though.</p>
<p>A small note about <code>millis()</code>: 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 <code>micros()</code>. For example:</p>
<pre class="lang-cpp prettyprint-override"><code>const uint32_t POLLING_PERIOD = 10000;  // 1e4 us = 10 ms

// Call this from loop()
void handle_sensor()
{
    static uint32_t last_us;
    if (micros() - last_us &lt; POLLING_PERIOD) return;
    last_us += POLLING_PERIOD;
    sensor_data();
    // ...
}
</code></pre>
<p><strong>Edit</strong>: About why <code>last_us</code> has to be incremented by a constant
amount, consider this alternative:</p>
<pre class="lang-cpp prettyprint-override"><code>void handle_sensor()
{
    static uint32_t last_us;
    uint32_t now = micros()
    if (now - last_us &lt; POLLING_PERIOD) return;
    last_us = now;
    sensor_data();
    // ...
}
</code></pre>
<p>The code following the <code>if ... return;</code> line will be executed when the
tested condition is false, i.e. when <code>now - last_us &gt;= POLLING_PERIOD</code>.
It may happen that we sometimes have strict equality (<code>now - last_us == POLLING_PERIOD</code>) but, since any code execution takes time, sometimes
<code>now - last_us</code> will be strictly larger than <code>POLLING_PERIOD</code>. Every
time this happens <code>last_us</code> will be incremented by <em>more</em> than
<code>POLLING_PERIOD</code>. This means that the small timing errors accumulate.</p>
<p>If, instead, <code>last_us</code> 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
<em>average</em> polling frequency is right.</p>
