Skip to content

Commit 9a907ac

Browse files
authored
feat(bmi270): Implement FOC and CRT calibration features for bmi270 (#595)
* feat: Add foc/crt calibration feature for bmi270 * fix: crt calibration error bit logic error * refactor(bmi270): enhance FOC/CRT stability and address review comments * docs(bmi270): improve documentation for CRT abort and gyro offset function
1 parent 1e11250 commit 9a907ac

File tree

5 files changed

+737
-6
lines changed

5 files changed

+737
-6
lines changed

components/bmi270/example/README.md

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ This example shows how to use the `espp::Bmi270` component to initialize and com
2121
- [Debug Tips](#debug-tips)
2222
- [Performance Notes](#performance-notes)
2323
- [Advanced Features](#advanced-features)
24+
- [Data Ready Interrupt](#data-ready-interrupt)
25+
- [Fast Offset Compensation (FOC)](#fast-offset-compensation-foc)
26+
- [Component Re-Trim (CRT)](#component-re-trim-crt)
27+
- [Built-in Features](#built-in-features)
2428
- [References](#references)
2529

2630
<!-- markdown-toc end -->
@@ -32,6 +36,8 @@ This example shows how to use the `espp::Bmi270` component to initialize and com
3236
- **Orientation Filtering**: Both Kalman and Madgwick filter implementations
3337
- **Real-time Data Logging**: CSV format output suitable for plotting
3438
- **Interrupt Configuration**: Data ready and motion detection interrupts
39+
- **Fast Offset Compensation (FOC)**: Calibrate accelerometer and gyroscope offsets
40+
- **Component Re-Trim (CRT)**: Compensate for gyroscope sensitivity changes
3541
- **Advanced Configuration**: Performance modes, bandwidth settings, power management
3642

3743
## How to use example
@@ -187,6 +193,16 @@ The CSV output can be imported into analysis tools like:
187193
- Consider magnetometer integration for yaw correction
188194
- Check for temperature effects
189195

196+
**Stack Overflow during Initialization**:
197+
- Device crashes or resets while calling `bmi270.init()`.
198+
- Uploading the configuration file uses a large stack buffer by default.
199+
- Reduce the burst write size in the configuration to limit stack usage.
200+
```cpp
201+
espp::Bmi270::Config config;
202+
config.burst_write_size = 128; // Use 128-byte chunks (default 0 = one chunk of config_file_size bytes, e.g. 8192)
203+
espp::Bmi270 imu(config);
204+
```
205+
190206
### Debug Tips
191207
192208
1. **Enable verbose logging:**
@@ -218,7 +234,48 @@ The CSV output can be imported into analysis tools like:
218234

219235
## Advanced Features
220236

221-
The example can be extended to demonstrate:
237+
### Data Ready Interrupt
238+
239+
The BMI270 can be configured to generate an interrupt when new data is available. This is more efficient than polling the sensor.
240+
241+
```cpp
242+
std::error_code ec;
243+
244+
Imu::InterruptConfig int_config{
245+
.pin = Imu::InterruptPin::INT1,
246+
.output_type = Imu::InterruptOutput::PUSH_PULL,
247+
.active_level = Imu::InterruptLevel::ACTIVE_HIGH,
248+
.enable_data_ready = true
249+
};
250+
imu.configure_interrupts(int_config, ec);
251+
```
252+
253+
### Fast Offset Compensation (FOC)
254+
255+
FOC allows for quick calibration of the accelerometer and gyroscope offsets.
256+
257+
```cpp
258+
// Accelerometer FOC (e.g., device flat on table, Z axis pointing up)
259+
Imu::AccelFocGValue accel_foc_target = {
260+
.x = 0, .y = 0, .z = 1, .sign = 0 // 1g on Z axis
261+
};
262+
imu.perform_accel_foc(accel_foc_target, ec);
263+
264+
// Gyroscope FOC (device must be stationary)
265+
imu.perform_gyro_foc(ec);
266+
```
267+
268+
### Component Re-Trim (CRT)
269+
270+
CRT is a feature to compensate for sensitivity changes in the gyroscope that may occur during assembly or over time.
271+
272+
```cpp
273+
imu.perform_crt(ec);
274+
```
275+
276+
### Built-in Features
277+
278+
The BMI270 also supports several on-chip features that can be demonstrated by extending this example:
222279

223280
- **Motion Detection**: Any motion, no motion, significant motion
224281
- **Step Counting**: Pedometer functionality

components/bmi270/example/main/Kconfig.projbuild

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,11 @@ config EXAMPLE_I2C_CLOCK_SPEED_HZ
3333
help
3434
I2C clock speed in Hz.
3535

36+
config EXAMPLE_RUN_CALIBRATION
37+
bool "Run calibration"
38+
default 1
39+
help
40+
Whether to run the sensor calibration (FOC & CRT) at startup.
41+
Note: Device must be stationary on a flat surface.
42+
3643
endmenu

components/bmi270/example/main/bmi270_example.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,45 @@ extern "C" void app_main(void) {
108108
// create the IMU
109109
Imu imu(config);
110110

111+
// ---------------------------------------------------------------------------
112+
// [Optional] Sensor Calibration (FOC & CRT)
113+
// WARNING:
114+
// 1. The device must be COMPLETELY STATIONARY on a flat surface.
115+
// 2. Enable these lines only when you need calibration (e.g., once after assembly).
116+
// ---------------------------------------------------------------------------
117+
#if CONFIG_EXAMPLE_RUN_CALIBRATION
118+
// Perform FOC (Fast Offset Compensation)
119+
// Note: This assumes the device is flat on a table (Z-axis = 1g)
120+
// For a real application, you might want to trigger this based on a user action
121+
// or store the offsets in NVS.
122+
std::error_code ec;
123+
124+
logger.info("Performing Accelerometer FOC...");
125+
Imu::AccelFocGValue accel_foc_target = {.x = 0, .y = 0, .z = 1, .sign = 0}; // 1g on Z axis
126+
if (imu.perform_accel_foc(accel_foc_target, ec)) {
127+
logger.info("Accelerometer FOC completed successfully");
128+
} else {
129+
logger.error("Accelerometer FOC failed: {}", ec.message());
130+
}
131+
132+
logger.info("Performing Gyroscope FOC...");
133+
// Note: Device must be stationary for Gyro FOC
134+
if (imu.perform_gyro_foc(ec)) {
135+
logger.info("Gyroscope FOC completed successfully");
136+
} else {
137+
logger.error("Gyroscope FOC failed: {}", ec.message());
138+
}
139+
140+
// Perform CRT (Component Re-Trim)
141+
// This feature compensates for sensitivity changes in the gyroscope.
142+
logger.info("Performing CRT...");
143+
if (imu.perform_crt(ec)) {
144+
logger.info("CRT completed successfully");
145+
} else {
146+
logger.error("CRT failed: {}", ec.message());
147+
}
148+
#endif
149+
111150
// make a task to read out the IMU data and print it to console
112151
auto task_fn = [&](std::mutex &m, std::condition_variable &cv) -> bool {
113152
// sleep first in case we don't get IMU data and need to exit early
@@ -159,7 +198,7 @@ extern "C" void app_main(void) {
159198
// print madgwick filter outputs
160199
text += fmt::format("{:03.3f},{:03.3f},{:03.3f},", roll, pitch, yaw);
161200
text += fmt::format("{:03.3f},{:03.3f},{:03.3f}", vx, vy, vz);
162-
201+
163202
fmt::print("{}\n", text);
164203

165204
return false;

0 commit comments

Comments
 (0)