2025-05-26 2:07 AM
I'm working with the IIS3DWB high-performance MEMS accelerometer and using it to calculate both acceleration RMS and velocity RMS values.
While the datasheet specifies a frequency response from DC to 6 kHz (±3 dB), I’ve noticed in practice that reliable and accurate RMS measurements only begin to appear from around 40 Hz onwards.
After enabling the digital high-pass filter (HPF) as shown in the documentation (see attached figure), I understand that the minimum cutoff is ODR/800, which translates to 33 Hz at an ODR of 26667 Hz. This explains the attenuation of low-frequency components and might be contributing to the inaccuracy in the 2–40 Hz band.
What is the best way to achieve accurate acceleration and velocity RMS values in the 2 Hz to 40 Hz frequency range using the IIS3DWB?
Any suggestions or community experience on low-frequency analysis with this sensor?
2025-05-29 2:15 AM
Hi @Rishabh_Rathod ,
To measure within the frequency range of 2 to 40 Hz, we can suggest two different approaches. The common step for both solutions is:
CTRL8_XL
register to 0, thereby setting the FDS
bit to 0 (refer to section 9.17 of the Datasheet), and choose not to enable the high-pass filter (HPF).The two possibilities involve whether or not to enable the low-pass filter (LPF):
LPF2_XL_EN
to 0 (disable LPF), acquire data at the maximum output data rate (ODR), and then process the data to extract the necessary information. This approach will result in data redundancy.LPF2_XL_EN
to 1 (enable LPF) and choose a cutoff frequency based on the desired precision or the amount of data you wish to process for your measurement. For example, for the 2-40 Hz range, you might set HPCF_XL_[2:0]
to 5.We encourage you to try this configuration and let us know the results.
2025-05-30 4:47 AM
Thank you for the helpful suggestions.
I tried disabling the HPF as recommended by setting CTRL8_XL.FDS = 0. However, I observed that doing so introduces a DC component in the acceleration signal, which artificially increases both acceleration RMS and velocity RMS values — especially noticeable in integrated velocity due to drift accumulation.
I’m working on a solution that aims to provide accurate RMS values over the full bandwidth from 10 Hz to 6.3 kHz, matching the sensor’s effective frequency response.
A few points and follow-up questions:
Is it possible to remove the DC component from the acceleration signal without using the built-in HPF?
(e.g., using a software-based approach or offset correction method)
I’m basing my code on the MotionSP library. From my experience, the software HPF implementation there does reasonably well for acceleration RMS in the 10 Hz–6.3 kHz range.
However, when calculating velocity RMS (via integration), the SW HPF does not sufficiently eliminate low-frequency drift or if aggressively filtered remove low frequency signal components itself.
Would appreciate any recommendations for:
A robust software filtering technique that works well for integration (e.g., bandpass or detrending filters)
ST’s suggestions or best practices for achieving stable velocity RMS across the full sensor bandwidth, especially avoiding the DC bias when HPF is disabled.
Thanks again for the support!
2025-06-06 8:00 AM - edited 2025-06-06 8:01 AM
Hi @Rishabh_Rathod ,
If you do not want to limit the band from 40Hz to 6.3KHz (and not from 10Hz) the only possible solution is to use an HPF sw and if it is not enough the only solution is to create an analog filter at least of 2-3 order ( with fs= 5HZ or less) and you have to apply it between sensor and uC.
To address the offset problem, I recommend following the settings described in Application Note AN5444, section 4.6. This section explains how to use the CTRL6 and CTRL7 registers to set a measurement offset compensation. You can also enter the offset value manually.
Regarding the MotionSP library, I recommend that you consult this document:
For best results, you need to use a software HPF (and possibly also a hardware HPF). From the datasheet it is noted that the hardware HPF has a cutoff frequency of 33 Hz, so below 40 Hz you will not get acceptable values.
One possible strategy is to apply a software HPF, perform integration, and then apply additional filtering to improve the results.
2025-06-09 11:51 PM
Hi @Federica Bossi,
Thank you for the detailed response.
Regarding the suggestions:
Using an analog high-pass filter between the sensor and the microcontroller is unfortunately not feasible in my case. The IIS3DWB sensor provides a fully digital SPI output, and since the signal is digitized internally, there's no access to the analog path where such a filter could be inserted.
I have already tested the offset compensation method described in AN5444, Section 4.6, using the CTRL6/CTRL7 registers. While it helps in removing static bias from the acceleration signal, it does not significantly improve the velocity RMS accuracy in the 10–40 Hz range, especially after integration.
Based on your third suggestion, I'm currently trying a software high-pass filter (SW HPF) followed by integration and post-filtering. Below is a simplified version of my current code. I’d be grateful if you could review it or provide any suggestions for improvement. My RMS results for acceleration look accurate from 10 Hz to 6.3 kHz, but for velocity, I get consistent results only above 40 Hz. Do you see any potential improvements in this approach? Would a different filter structure, or a better integration scheme help?
SW HPF for acceleration
float Smooth_acc = 0.99764f; // Tune between 0.985 - 0.999
float prev_acc_offset = input[0];
for (uint32_t i = 1; i < ODR; i++) {
float drift = Smooth_acc * prev_acc_offset + (1 - Smooth_acc) * input[i];
input[i] -= drift;
prev_acc_offset = drift;
}
Below is my Integration and filtering code for velocity
velocity[0] = 0.0f; // Assuming initial velocity is zero
// RK4 Integration for Velocity
for (uint32_t i = 0; i < 13333 - 1; i++) {
float k1 = DT * input_decimated[i];
float k2 = DT * (input_decimated[i] + 0.5f * k1);
float k3 = DT * (input_decimated[i] + 0.5f * k2);
float k4 = DT * (input_decimated[i] + k3);
velocity[i + 1] = velocity[i] + (k1 + 2 * k2 + 2 * k3 + k4) / 6.0f;
}
#define IIR_ORDER 12
#define IIR_NUMSTAGES (IIR_ORDER/2)
static float32_t m_biquad_state[IIR_ORDER];
static float32_t m_biquad_coeffs[5*IIR_NUMSTAGES] =
{
0.694626,
1.389251,
0.694626,
-1.689406,
-0.714985,
1.000000,
2.000000,
1.000000,
-1.756728,
-0.783296,
1.000000,
2.000000,
1.000000,
-1.886429,
-0.914924,
1.000000,
-2.000000,
1.000000,
1.970130,
-0.970369,
1.000000,
-2.000000,
1.000000,
1.978008,
-0.978247,
1.000000,
-2.000000,
1.000000,
1.991751,
-0.991992
};
arm_biquad_cascade_df2T_instance_f32 iir_inst;
arm_biquad_cascade_df2T_init_f32(&iir_inst, IIR_NUMSTAGES, m_biquad_coeffs, m_biquad_state);
// Process the input data through the filter
arm_biquad_cascade_df2T_f32(&iir_inst, velocity, vel, 13333);