Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 56 additions & 1 deletion components/bmi270/example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ This example shows how to use the `espp::Bmi270` component to initialize and com
- [Debug Tips](#debug-tips)
- [Performance Notes](#performance-notes)
- [Advanced Features](#advanced-features)
- [Data Ready Interrupt](#data-ready-interrupt)
- [Fast Offset Compensation (FOC)](#fast-offset-compensation-foc)
- [Component Re-Trim (CRT)](#component-re-trim-crt)
- [Built-in Features](#built-in-features)
- [References](#references)

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

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

**Stack Overflow during Initialization**:
- Device crashes or resets while calling `bmi270.init()`.
- Uploading the configuration file uses a large stack buffer by default.
- Reduce the burst write size in the configuration to limit stack usage.
```cpp
espp::Bmi270::Config config;
config.burst_write_size = 128; // Use 128-byte chunks (default is 0/unlimited)
espp::Bmi270 imu(config);
```

### Debug Tips

1. **Enable verbose logging:**
Expand Down Expand Up @@ -218,7 +234,46 @@ The CSV output can be imported into analysis tools like:

## Advanced Features

The example can be extended to demonstrate:
### Data Ready Interrupt

The BMI270 can be configured to generate an interrupt when new data is available. This is more efficient than polling the sensor.

```cpp
Imu::InterruptConfig int_config{
.pin = Imu::InterruptPin::INT1,
.output_type = Imu::InterruptOutput::PUSH_PULL,
.active_level = Imu::InterruptLevel::ACTIVE_HIGH,
.enable_data_ready = true
};
imu.configure_interrupts(int_config, ec);
```

### Fast Offset Compensation (FOC)

FOC allows for quick calibration of the accelerometer and gyroscope offsets.

```cpp
// Accelerometer FOC (e.g., device flat on table, Z axis pointing up)
Imu::AccelFocGValue accel_foc_target = {
.x = 0, .y = 0, .z = 1, .sign = 0 // 1g on Z axis
};
imu.perform_accel_foc(accel_foc_target, ec);

// Gyroscope FOC (device must be stationary)
imu.perform_gyro_foc(ec);
```

### Component Re-Trim (CRT)

CRT is a feature to compensate for sensitivity changes in the gyroscope that may occur during assembly or over time.

```cpp
imu.perform_crt(ec);
```

### Built-in Features

The BMI270 also supports several on-chip features that can be demonstrated by extending this example:

- **Motion Detection**: Any motion, no motion, significant motion
- **Step Counting**: Pedometer functionality
Expand Down
57 changes: 39 additions & 18 deletions components/bmi270/example/main/bmi270_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,45 @@ extern "C" void app_main(void) {
// create the IMU
Imu imu(config);

// ---------------------------------------------------------------------------
// [Optional] Sensor Calibration (FOC & CRT)
// WARNING:
// 1. The device must be COMPLETELY STATIONARY on a flat surface.
// 2. Enable these lines only when you need calibration (e.g., once after assembly).
// ---------------------------------------------------------------------------
#if 0
// Perform FOC (Fast Offset Compensation)
// Note: This assumes the device is flat on a table (Z-axis = 1g)
// For a real application, you might want to trigger this based on a user action
// or store the offsets in NVS.
std::error_code ec;

logger.info("Performing Accelerometer FOC...");
Imu::AccelFocGValue accel_foc_target = {.x = 0, .y = 0, .z = 1, .sign = 0}; // 1g on Z axis
if (imu.perform_accel_foc(accel_foc_target, ec)) {
logger.info("Accelerometer FOC completed successfully");
} else {
logger.error("Accelerometer FOC failed: {}", ec.message());
}

logger.info("Performing Gyroscope FOC...");
// Note: Device must be stationary for Gyro FOC
if (imu.perform_gyro_foc(ec)) {
logger.info("Gyroscope FOC completed successfully");
} else {
logger.error("Gyroscope FOC failed: {}", ec.message());
}

// Perform CRT (Component Re-Trim)
// This feature compensates for sensitivity changes in the gyroscope.
logger.info("Performing CRT...");
if (imu.perform_crt(ec)) {
logger.info("CRT completed successfully");
} else {
logger.error("CRT failed: {}", ec.message());
}
#endif

// make a task to read out the IMU data and print it to console
auto task_fn = [&](std::mutex &m, std::condition_variable &cv) -> bool {
// sleep first in case we don't get IMU data and need to exit early
Expand Down Expand Up @@ -142,24 +181,6 @@ extern "C" void app_main(void) {
fmt::format("{:02.3f},{:02.3f},{:02.3f},", (float)accel.x, (float)accel.y, (float)accel.z);
text += fmt::format("{:03.3f},{:03.3f},{:03.3f},", (float)gyro.x, (float)gyro.y, (float)gyro.z);
text += fmt::format("{:02.1f},", temp);
// print kalman filter outputs
text += fmt::format("{:03.3f},{:03.3f},{:03.3f},", (float)orientation.x, (float)orientation.y,
(float)orientation.z);
text += fmt::format("{:03.3f},{:03.3f},{:03.3f},", (float)gravity_vector.x,
(float)gravity_vector.y, (float)gravity_vector.z);

auto madgwick_orientation = madgwick_filter_fn(dt, accel, gyro);
float roll = madgwick_orientation.roll;
float pitch = madgwick_orientation.pitch;
float yaw = madgwick_orientation.yaw;
float vx = sin(pitch);
float vy = -cos(pitch) * sin(roll);
float vz = -cos(pitch) * cos(roll);

// print madgwick filter outputs
text += fmt::format("{:03.3f},{:03.3f},{:03.3f},", roll, pitch, yaw);
text += fmt::format("{:03.3f},{:03.3f},{:03.3f}", vx, vy, vz);

fmt::print("{}\n", text);

return false;
Expand Down
Loading