Blog

Making sense of smart sensor sampling

Intelligent MEMS sensors on breakout boards jumpstart many maker projects. Off-the-shelf drivers can get an analog sensor reading from a prototype in minutes. If sample rates are in seconds instead of milliseconds, those off-the-shelf drivers may work. Want to sample faster? Looking at sampling strategies can help makers unlock more smart sensor capabilities.

A microcontroller in one of these smart sensors handles I2C or SPI timing, analog-to-digital (A/D) sampling mode and rates, digital filtering, and more. Advanced inertial measurement units (IMUs) often add sensor fusion processing. For a simpler example, I’ll use the Bosch Sensortec BMP390L digital pressure sensor I’m working with in a project.

photo of the Adafruit BMP390L precision barometric pressure sensor and altimeter

Adafruit has employed the BMP390L digital pressure sensor in its precision barometric pressure and altimeter breakout.

Simple polling, inexact sample rate

The BMP390L starts out in “forced” mode: wake up, read, and go back to sleep. Adafruit’s CircuitPython driver runs in this mode, saving power in many applications. It returns pressure and temperature readings and performs compensation. An application snippet reveals three important parameters:

import board
import busio
import adafruit_bmp3xx

# I2C setup
i2c = busio.I2C(board.SCL, board.SDA)
bmp = adafruit_bmp3xx.BMP3XX_I2C(i2c)

samples = 1000

bmp.pressure_oversampling = 16
bmp.temperature_oversampling = 1
bmp.filter_coefficient = 2

n = 0
while n < samples:
PAm[n] = bmp.altitude
n += 1

Oversampling settings for pressure and temperature reduce noise and increase effective resolution of A/D conversion. In the BMP390 sensor, resolution is 16 bits with no oversampling, increasing to 21 bits with x32 oversampling. Filter coefficient configures an infinite impulse response (IIR) filter, handy for taking out sudden spikes from a wind gust or a slammed door.

Why not oversample and filter all the time for noise, precision, and spikes? The big tradeoff is power consumption. When reading once a minute with oversampling off—a weather station use case—sensor power is only 4 μA and pressure noise is 3.7 Pa. For a 50-Hz drone use case, x8 oversampling and x2 filtering cut pressure noise by 80%, but power consumption is 570 μA.

The other tradeoff is output data rate, or ODR. In a tight loop like this, the limiting factor for ODR is the conversion time of the sensor, which increases with oversampling. For the BMP390, the pressure sensor has a bit longer settling time than the temperature sensor.

Tconv = 234 μs + press_en * (392 μs + (press_osr) * 2020 μs) + temp_en * (163 μs + (temp_osr) * 2020 μs)

With both pressure and temperature sensors enabled and no oversampling (press_osr = 1), this works out to a typical 4.83-ms time for a 207-Hz theoretical ODR. With x16 pressure oversampling in our example code, conversion time is 35.13 ms, for a 28.47 Hz theoretical ODR.

Measuring the actual polling code on 1,000 samples, the best average ODR has seen is 26.2 Hz, and the worst is 23.6 Hz. That wide range is likely due to variation in sensor wake-up time for every sample—a figure unspecified in the BMP390 docs.

Free running for selected ODRs

Another BMP390L sampling mode removes some uncertainty. Placing the sensor in “normal” mode cycles readings at a programmed rate into a shadow register, preventing values from changing while being read. Prescaler settings are fixed; the BMP390L starts at an ODR of 200 Hz and divides down to 100, 50, 25, 12.5, 6.25, and so on to times in seconds.

The Adafruit CircuitPython BMP390L driver requires a bit of surgery, creating setters for sensor_mode and sample_rate. The application snippet is mostly unchanged, using the modified driver and introducing a slight read delay.

import board
import busio
import adafruit_bmp3xx_normal

# I2C setup
i2c = busio.I2C(board.SCL, board.SDA)
bmp = adafruit_bmp3xx_normal.BMP3XX_I2C(i2c)

samples = 1000

ODR = 25
bmp.sample_rate = ODR
bmp.sensor_mode = "normal"
sample_wait = 1/ODR - 0.002

bmp.pressure_oversampling = 16
bmp.temperature_oversampling = 1
bmp.filter_coefficient = 2

n = 0
while n < samples:

PAm[n] = bmp.altitude
n += 1
time.sleep(sample_wait)

Measuring the free running code on 1,000 samples shows an actual 25-Hz ODR nearly every run. There’s some risk in the 2 ms sample_wait, nearing CircuitPython’s 1 ms system timer resolution. Even if read timing varies slightly, sensor timing is known to be 25 Hz.

For faster ODRs, power consumption in normal mode and forced mode is similar, because the sensor is awake for almost the entire duty cycle. Also note that the conversion time formula still applies. If the ODR is set higher than 25 Hz, oversampling must be reduced accordingly, or the actual ODR falls behind as samples accumulate.

Dig into the docs and drivers

I took this free running approach because it was simpler driver work. I haven’t yet worked on a unified BMP390 driver for both forced and normal modes. If CircuitPython supported external interrupts, another option would be replacing the asynchronous read/delay with a routine serving the data-ready interrupt from the BMP390L. Also, the BMP390L supports a FIFO, which would be a much more complex driver effort, but would keep reads on schedule.

Another point is that different intelligent MEMS sensors have different ODR choices. For example, my project also has an ICM-20649 accelerometer and gyro, which has a prescaler setting of 23.9 Hz instead of 25 Hz. That may force a move to an ODR of 50 Hz for the BMP390 and 50.4 Hz for the ICM-20649, with slightly less oversampling.

When projects need sub-second sampling at specific intervals, there’s more to think about than just reading the sensor. Drivers should provide control of sampling mode, ODR, oversampling, and filtering. Digging into sensor docs and code provides insights for successful projects.

After spending a decade in missile guidance systems at General Dynamics, Don Dingee became an evangelist for VMEbus and single-board computer technology at Motorola. He writes about sensors, ADCs/DACs, and signal processing for Planet Analog.

Related Content:

0 comments on “Making sense of smart sensor sampling

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.