Skip to content

Commit eee1600

Browse files
committed
feat(sensors): Add BMI270 sensor driver
1 parent 026a00a commit eee1600

File tree

8 files changed

+1638
-0
lines changed

8 files changed

+1638
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.3")
2+
set(REQ esp_driver_i2c esp_driver_spi)
3+
else()
4+
set(REQ driver)
5+
endif()
6+
7+
idf_component_register(SRCS src/bmi270.c src/bmi270_sensor_hub.c INCLUDE_DIRS "include" PRIV_INCLUDE_DIRS "include_priv" REQUIRES ${REQ})
8+
9+
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u bmi270_impl_init")
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Bosch BMI270 inertial measurement unit driver
2+
3+
[![Component Registry](https://components.espressif.com/components/espressif/bmi270/badge.svg)](https://components.espressif.com/components/espressif/bmi270)
4+
![maintenance-status](https://img.shields.io/badge/maintenance-actively--maintained-green.svg)
5+
6+
## Features
7+
8+
- Reading of the chip ID.
9+
- Configuring output data rate and range of the onboard accelerometer and gyroscope.
10+
- Reading normalized float values of acceleration and rotation angle.
11+
12+
### Limitations
13+
14+
- Missing implementation of the SPI interface.
15+
- Advanced features such as gesture control, FIFO buffering, interrupt on data ready and auxilary interface are not supported.
16+
17+
## Integration guide
18+
19+
This driver, along with many other components from this repository, can be used as a package from [Espressif's IDF Component Registry](https://components.espressif.com). To include this driver in your project, run the following idf.py from the project's root directory:
20+
21+
``` sh
22+
idf.py add-dependency "espressif/bmi270==*"
23+
```
24+
25+
## Usage guide
26+
27+
### Low level driver
28+
When using the low level driver directly then firstly initialize it by providing a valid low level driver configuration:
29+
``` c
30+
const bmi270_driver_config_t driver_config = {
31+
.addr = addr,
32+
.interface = BMI270_USE_I2C,
33+
.i2c_bus = i2c_bus_handle
34+
};
35+
bmi270_init(&driver_config, &bmi270_handle_pointer);
36+
```
37+
Start acquisition with a valid measurement configuration:
38+
``` c
39+
const bmi270_config_t measurement_config = {
40+
.acc_odr = BMI270_ACC_ODR_X,
41+
.acc_range = BMI270_ACC_RANGE_X,
42+
.gyr_odr = BMI270_GYR_ODR_X,
43+
.gyr_range = BMI270_GYR_RANGE_X
44+
};
45+
bmi270_start(bmi270_handle_pointer, &measurement_config);
46+
```
47+
After a completed measurement data can be read using:
48+
``` c
49+
bmi270_get_acc_data(bmi270_handle_pointer, &x, &y, &z);
50+
```
51+
Disable measurements and clean up the BMI270 driver using:
52+
``` c
53+
bmi270_stop(bmi270_handle_pointer);
54+
bmi270_delete(&bmi270_handle_pointer);
55+
```
56+
57+
### Espressif sensor hub
58+
59+
This driver can be used with [sensor-hub](https://docs.espressif.com/projects/esp-iot-solution/en/latest/sensors/sensor_hub.html) abstraction.
60+
Create a BMI270 sensor instance using a valid configuration:
61+
``` c
62+
iot_sensor_create("sensor_hub_bmi270", &bmi270_sensor_hub_configuration, sensor_handle_pointer);
63+
```
64+
65+
## Driver structure
66+
67+
```
68+
BMI270
69+
├── CMakeLists.txt # Driver component CMake file
70+
├── README.md
71+
├── idf_component.yml # Driver component configuration file
72+
├── include # Public include folder
73+
│ └── bmi270.h
74+
├── include_priv # Private include folder
75+
│ └── bmi270_priv.h
76+
├── license.txt
77+
├── src
78+
│ ├── bmi270.c # Low level driver source file
79+
│ └── bmi270_sensor_hub.c # Sensor-hub wrapper
80+
└── test_app # Test app for the low level driver
81+
├── CMakeLists.txt
82+
├── main
83+
│ ├── CMakeLists.txt
84+
│ ├── idf_component.yml
85+
│ └── test_app_bmi270.c
86+
└── sdkconfig.defaults
87+
```
88+
89+
## See also
90+
[BMI270 datasheet](https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmi270-ds000.pdf)
91+
[ESP-IDF component registry documentation](https://docs.espressif.com/projects/idf-component-manager/en/latest/)
92+
[Sensor hub documentation](https://docs.espressif.com/projects/esp-iot-solution/en/latest/sensors/sensor_hub.html)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
version: 1.0.0
2+
description: I2C driver for BMI270 inertial measurement unit
3+
url: https://github.com/espressif/esp-bsp/tree/master/components/bmi270
4+
dependencies:
5+
idf: ">=5.2"
6+
sensor_hub:
7+
version: ^0.1.4
8+
public: true
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#ifdef __cplusplus
10+
extern "C" {
11+
#endif
12+
13+
#include "driver/i2c_types.h"
14+
#include "driver/spi_master.h"
15+
16+
#define BMI270_CHIP_ID 0x24
17+
#define BMI270_I2C_ADDRESS_L 0x68
18+
#define BMI270_I2C_ADDRESS_H 0x69
19+
20+
// SPI interface is currently not supported
21+
typedef enum {
22+
BMI270_USE_I2C,
23+
BMI270_USE_SPI,
24+
} bmi270_interface_e;
25+
26+
typedef enum {
27+
BMI270_ACC_ODR_0_78 = 1,
28+
BMI270_ACC_ODR_1_5,
29+
BMI270_ACC_ODR_3_1,
30+
BMI270_ACC_ODR_6_25,
31+
BMI270_ACC_ODR_12_5,
32+
BMI270_ACC_ODR_25,
33+
BMI270_ACC_ODR_50,
34+
BMI270_ACC_ODR_100,
35+
BMI270_ACC_ODR_200,
36+
BMI270_ACC_ODR_400,
37+
BMI270_ACC_ODR_800,
38+
BMI270_ACC_ODR_1600
39+
} bmi270_acc_odr_e;
40+
41+
typedef enum {
42+
BMI270_GYR_ODR_25 = 6,
43+
BMI270_GYR_ODR_50,
44+
BMI270_GYR_ODR_100,
45+
BMI270_GYR_ODR_200,
46+
BMI270_GYR_ODR_400,
47+
BMI270_GYR_ODR_800,
48+
BMI270_GYR_ODR_1600,
49+
BMI270_GYR_ODR_3200
50+
} bmi270_gyr_odr_e;
51+
52+
typedef enum {
53+
BMI270_ACC_RANGE_2 = 0,
54+
BMI270_ACC_RANGE_4,
55+
BMI270_ACC_RANGE_8,
56+
BMI270_ACC_RANGE_16
57+
} bmi270_acc_range_e;
58+
59+
typedef enum {
60+
BMI270_GYR_RANGE_2000 = 0,
61+
BMI270_GYR_RANGE_1000,
62+
BMI270_GYR_RANGE_500,
63+
BMI270_GYR_RANGE_250,
64+
BMI270_GYR_RANGE_125
65+
} bmi270_gyr_range_e;
66+
67+
typedef struct {
68+
uint8_t addr;
69+
bmi270_interface_e interface;
70+
union {
71+
i2c_master_bus_handle_t i2c_bus;
72+
// SPI interface is currently not supported
73+
};
74+
} bmi270_driver_config_t;
75+
76+
typedef struct {
77+
bmi270_acc_odr_e acc_odr;
78+
bmi270_acc_range_e acc_range;
79+
bmi270_gyr_odr_e gyr_odr;
80+
bmi270_gyr_range_e gyr_range;
81+
} bmi270_config_t;
82+
83+
typedef struct {
84+
bool initialized;
85+
bmi270_interface_e interface;
86+
union {
87+
i2c_master_dev_handle_t i2c_handle;
88+
spi_device_handle_t spi_handle;
89+
};
90+
bmi270_acc_range_e acc_range;
91+
bmi270_gyr_range_e gyr_range;
92+
} bmi270_handle_t;
93+
94+
/**
95+
* @brief Create and initialize the BMI270 sensor object
96+
*
97+
* @param[in] config BMI270 sensor driver configuration
98+
* @param[out] dev_handle Pointer to the allocated memory for the BMI270 handle
99+
*
100+
* @return
101+
* - ESP_OK Success
102+
* - ESP_ERR_NO_MEM Memory allocation failure
103+
* - ESP_ERR_NOT_FOUND Device was not found on the data bus
104+
* - Or other errors from the underlying I2C driver
105+
*/
106+
esp_err_t bmi270_init(const bmi270_driver_config_t *config, bmi270_handle_t **dev_handle);
107+
108+
/**
109+
* @brief Free and delete the BMI270 sensor object
110+
*
111+
* @param[in] dev_handle Pointer to an initialized BMI270 handle
112+
*
113+
* @return
114+
* - ESP_OK Success
115+
* - Or other errors from the underlying I2C driver
116+
*/
117+
esp_err_t bmi270_delete(bmi270_handle_t **dev_handle);
118+
119+
/**
120+
* @brief Read the chip ID register
121+
*
122+
* @param[in] dev_handle Initialized BMI270 handle
123+
* @param[out] chip_id Value read from the chip ID register
124+
*
125+
* @return
126+
* - ESP_OK Success
127+
* - Or other errors from the underlying I2C driver
128+
*/
129+
esp_err_t bmi270_get_chip_id(const bmi270_handle_t *dev_handle, uint8_t *chip_id);
130+
131+
/**
132+
* @brief Start accelerometer, gyroscope and temperature sensor measurement
133+
*
134+
* @param[in] dev_handle Initialized BMI270 handle
135+
* @param[out] config Configuration of data acquisition
136+
*
137+
* @return
138+
* - ESP_OK Success
139+
* - Or other errors from the underlying I2C driver
140+
*/
141+
esp_err_t bmi270_start(bmi270_handle_t *dev_handle, const bmi270_config_t *config);
142+
143+
/**
144+
* @brief Stop accelerometer, gyroscope and temperature sensor measurement
145+
*
146+
* @param[in] dev_handle Initialized BMI270 handle
147+
*
148+
* @return
149+
* - ESP_OK Success
150+
* - Or other errors from the underlying I2C driver
151+
*/
152+
esp_err_t bmi270_stop(const bmi270_handle_t *dev_handle);
153+
154+
/**
155+
* @brief Read out scaled accelerometer data
156+
*
157+
* @param[in] dev_handle Initialized BMI270 handle
158+
* @param[out] x X axis accelerometer value in g
159+
* @param[out] y Y axis accelerometer value in g
160+
* @param[out] z Z axis accelerometer value in g
161+
*
162+
* @return
163+
* - ESP_OK Success
164+
* - Or other errors from the underlying I2C driver
165+
*/
166+
esp_err_t bmi270_get_acc_data(const bmi270_handle_t *dev_handle, float *x, float *y, float *z);
167+
168+
/**
169+
* @brief Read out scaled gyroscope data
170+
*
171+
* @param[in] dev_handle Initialized BMI270 handle
172+
* @param[out] x X axis gyroscope value in dps
173+
* @param[out] y Y axis gyroscope value in dps
174+
* @param[out] z Z axis gyroscope value in dps
175+
*
176+
* @return
177+
* - ESP_OK Success
178+
* - Or other errors from the underlying I2C driver
179+
*/
180+
esp_err_t bmi270_get_gyr_data(const bmi270_handle_t *dev_handle, float *x, float *y, float *z);
181+
182+
/**
183+
* @brief Set accelerometer output data rate
184+
*
185+
* @param[in] dev_handle Initialized BMI270 handle
186+
* @param[in] odr Accelerometer output data rate
187+
*
188+
* @return
189+
* - ESP_OK Success
190+
* - Or other errors from the underlying I2C driver
191+
*/
192+
esp_err_t bmi270_set_acc_odr(const bmi270_handle_t *dev_handle, bmi270_acc_odr_e odr);
193+
194+
/**
195+
* @brief Set gyroscope output data rate
196+
*
197+
* @param[in] dev_handle Initialized BMI270 handle
198+
* @param[in] odr Gyroscope output data rate
199+
*
200+
* @return
201+
* - ESP_OK Success
202+
* - Or other errors from the underlying I2C driver
203+
*/
204+
esp_err_t bmi270_set_gyr_odr(const bmi270_handle_t *dev_handle, bmi270_gyr_odr_e odr);
205+
206+
/**
207+
* @brief Set accelerometer measurement range
208+
*
209+
* @param[in] dev_handle Initialized BMI270 handle
210+
* @param[in] odr Accelerometer measurement range
211+
*
212+
* @return
213+
* - ESP_OK Success
214+
* - Or other errors from the underlying I2C driver
215+
*/
216+
esp_err_t bmi270_set_acc_range(bmi270_handle_t *dev_handle, bmi270_acc_range_e range);
217+
218+
/**
219+
* @brief Set gyroscope measurement range
220+
*
221+
* @param[in] dev_handle Initialized BMI270 handle
222+
* @param[in] odr Gyroscope measurement range
223+
*
224+
* @return
225+
* - ESP_OK Success
226+
* - Or other errors from the underlying I2C driver
227+
*/
228+
esp_err_t bmi270_set_gyr_range(bmi270_handle_t *dev_handle, bmi270_gyr_range_e range);
229+
230+
#ifdef __cplusplus
231+
}
232+
#endif

0 commit comments

Comments
 (0)