Skip to content

Commit 6dd006c

Browse files
committed
feat(sensors): Add BMI270 sensor driver
1 parent 4f43c11 commit 6dd006c

File tree

8 files changed

+1689
-0
lines changed

8 files changed

+1689
-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_create(&driver_config, &bmi270_handle_pointer);
36+
```
37+
Start acquisition with a valid measurement configuration:
38+
``` c
39+
const bmi270_config_t measurement_config = {
40+
.acce_odr = BMI270_ACC_ODR_X,
41+
.acce_range = BMI270_ACC_RANGE_X,
42+
.gyro_odr = BMI270_GYR_ODR_X,
43+
.gyro_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_acce_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: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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+
tags:
5+
- i2c
6+
- sensor_hub
7+
dependencies:
8+
idf: ">=5.2"
9+
sensor_hub:
10+
version: ^0.1.4
11+
public: true
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
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+
/**
21+
* @brief Selection for the BMI270 communication interface
22+
* @note The SPI interface is currently not supported
23+
*/
24+
typedef enum {
25+
BMI270_USE_I2C,
26+
BMI270_USE_SPI,
27+
} bmi270_interface_e;
28+
29+
/**
30+
* @brief BMI270 accelerometer output data rates
31+
*/
32+
typedef enum {
33+
BMI270_ACC_ODR_0_78_HZ = 1,
34+
BMI270_ACC_ODR_1_5_HZ,
35+
BMI270_ACC_ODR_3_1_HZ,
36+
BMI270_ACC_ODR_6_25_HZ,
37+
BMI270_ACC_ODR_12_5_HZ,
38+
BMI270_ACC_ODR_25_HZ,
39+
BMI270_ACC_ODR_50_HZ,
40+
BMI270_ACC_ODR_100_HZ,
41+
BMI270_ACC_ODR_200_HZ,
42+
BMI270_ACC_ODR_400_HZ,
43+
BMI270_ACC_ODR_800_HZ,
44+
BMI270_ACC_ODR_1600_HZ
45+
} bmi270_acce_odr_e;
46+
47+
/**
48+
* @brief BMI270 gyroscope output data rates
49+
*/
50+
typedef enum {
51+
BMI270_GYR_ODR_25_HZ = 6,
52+
BMI270_GYR_ODR_50_HZ,
53+
BMI270_GYR_ODR_100_HZ,
54+
BMI270_GYR_ODR_200_HZ,
55+
BMI270_GYR_ODR_400_HZ,
56+
BMI270_GYR_ODR_800_HZ,
57+
BMI270_GYR_ODR_1600_HZ,
58+
BMI270_GYR_ODR_3200_HZ
59+
} bmi270_gyro_odr_e;
60+
61+
/**
62+
* @brief BMI270 accelerometer data ranges
63+
*/
64+
typedef enum {
65+
BMI270_ACC_RANGE_2_G = 0,
66+
BMI270_ACC_RANGE_4_G,
67+
BMI270_ACC_RANGE_8_G,
68+
BMI270_ACC_RANGE_16_G
69+
} bmi270_acce_range_e;
70+
71+
/**
72+
* @brief BMI270 gyroscope data ranges
73+
*/
74+
typedef enum {
75+
BMI270_GYR_RANGE_2000_DPS = 0,
76+
BMI270_GYR_RANGE_1000_DPS,
77+
BMI270_GYR_RANGE_500_DPS,
78+
BMI270_GYR_RANGE_250_DPS,
79+
BMI270_GYR_RANGE_125_DPS
80+
} bmi270_gyro_range_e;
81+
82+
/**
83+
* @brief Driver interface configuration structure
84+
* @note The SPI interface is currently not supported
85+
*/
86+
typedef struct {
87+
uint8_t addr;
88+
bmi270_interface_e interface;
89+
union {
90+
i2c_master_bus_handle_t i2c_bus;
91+
};
92+
} bmi270_driver_config_t;
93+
94+
/**
95+
* @brief BMI270 data acquisition configuration
96+
*/
97+
typedef struct {
98+
bmi270_acce_odr_e acce_odr;
99+
bmi270_acce_range_e acce_range;
100+
bmi270_gyro_odr_e gyro_odr;
101+
bmi270_gyro_range_e gyro_range;
102+
} bmi270_config_t;
103+
104+
/**
105+
* @brief BMI270 handle
106+
*/
107+
typedef struct {
108+
bool initialized;
109+
bmi270_interface_e interface;
110+
union {
111+
i2c_master_dev_handle_t i2c_handle;
112+
spi_device_handle_t spi_handle;
113+
};
114+
bmi270_acce_range_e acce_range;
115+
bmi270_gyro_range_e gyro_range;
116+
} bmi270_handle_t;
117+
118+
/**
119+
* @brief Create and initialize the BMI270 sensor object
120+
*
121+
* @param[in] config BMI270 sensor driver configuration
122+
* @param[out] dev_handle Pointer to the allocated memory for the BMI270 handle
123+
*
124+
* @return
125+
* - ESP_OK Success
126+
* - ESP_ERR_NO_MEM Memory allocation failure
127+
* - ESP_ERR_NOT_FOUND Device was not found on the data bus
128+
* - Or other errors from the underlying I2C driver
129+
*/
130+
esp_err_t bmi270_create(const bmi270_driver_config_t *config, bmi270_handle_t **dev_handle);
131+
132+
/**
133+
* @brief Free and delete the BMI270 sensor object
134+
*
135+
* @param[in] dev_handle Pointer to an initialized BMI270 handle
136+
*
137+
* @return
138+
* - ESP_OK Success
139+
* - Or other errors from the underlying I2C driver
140+
*/
141+
esp_err_t bmi270_delete(bmi270_handle_t *dev_handle);
142+
143+
/**
144+
* @brief Read the chip ID register
145+
*
146+
* @param[in] dev_handle Initialized BMI270 handle
147+
* @param[out] chip_id Value read from the chip ID register
148+
*
149+
* @return
150+
* - ESP_OK Success
151+
* - Or other errors from the underlying I2C driver
152+
*/
153+
esp_err_t bmi270_get_chip_id(const bmi270_handle_t *dev_handle, uint8_t *chip_id);
154+
155+
/**
156+
* @brief Start accelerometer, gyroscope and temperature sensor measurement
157+
*
158+
* @param[in] dev_handle Initialized BMI270 handle
159+
* @param[out] config Configuration of data acquisition
160+
*
161+
* @return
162+
* - ESP_OK Success
163+
* - Or other errors from the underlying I2C driver
164+
*/
165+
esp_err_t bmi270_start(bmi270_handle_t *dev_handle, const bmi270_config_t *config);
166+
167+
/**
168+
* @brief Stop accelerometer, gyroscope and temperature sensor measurement
169+
*
170+
* @param[in] dev_handle Initialized BMI270 handle
171+
*
172+
* @return
173+
* - ESP_OK Success
174+
* - Or other errors from the underlying I2C driver
175+
*/
176+
esp_err_t bmi270_stop(const bmi270_handle_t *dev_handle);
177+
178+
/**
179+
* @brief Read out scaled accelerometer data
180+
*
181+
* @param[in] dev_handle Initialized BMI270 handle
182+
* @param[out] x X axis accelerometer value in g
183+
* @param[out] y Y axis accelerometer value in g
184+
* @param[out] z Z axis accelerometer value in g
185+
*
186+
* @return
187+
* - ESP_OK Success
188+
* - Or other errors from the underlying I2C driver
189+
*/
190+
esp_err_t bmi270_get_acce_data(const bmi270_handle_t *dev_handle, float *x, float *y, float *z);
191+
192+
/**
193+
* @brief Read out scaled gyroscope data
194+
*
195+
* @param[in] dev_handle Initialized BMI270 handle
196+
* @param[out] x X axis gyroscope value in dps
197+
* @param[out] y Y axis gyroscope value in dps
198+
* @param[out] z Z axis gyroscope value in dps
199+
*
200+
* @return
201+
* - ESP_OK Success
202+
* - Or other errors from the underlying I2C driver
203+
*/
204+
esp_err_t bmi270_get_gyro_data(const bmi270_handle_t *dev_handle, float *x, float *y, float *z);
205+
206+
/**
207+
* @brief Set accelerometer output data rate
208+
*
209+
* @param[in] dev_handle Initialized BMI270 handle
210+
* @param[in] odr Accelerometer output data rate
211+
*
212+
* @return
213+
* - ESP_OK Success
214+
* - Or other errors from the underlying I2C driver
215+
*/
216+
esp_err_t bmi270_set_acce_odr(const bmi270_handle_t *dev_handle, bmi270_acce_odr_e odr);
217+
218+
/**
219+
* @brief Set gyroscope output data rate
220+
*
221+
* @param[in] dev_handle Initialized BMI270 handle
222+
* @param[in] odr Gyroscope output data rate
223+
*
224+
* @return
225+
* - ESP_OK Success
226+
* - Or other errors from the underlying I2C driver
227+
*/
228+
esp_err_t bmi270_set_gyro_odr(const bmi270_handle_t *dev_handle, bmi270_gyro_odr_e odr);
229+
230+
/**
231+
* @brief Set accelerometer measurement range
232+
*
233+
* @param[in] dev_handle Initialized BMI270 handle
234+
* @param[in] odr Accelerometer measurement range
235+
*
236+
* @return
237+
* - ESP_OK Success
238+
* - Or other errors from the underlying I2C driver
239+
*/
240+
esp_err_t bmi270_set_acce_range(bmi270_handle_t *dev_handle, bmi270_acce_range_e range);
241+
242+
/**
243+
* @brief Set gyroscope measurement range
244+
*
245+
* @param[in] dev_handle Initialized BMI270 handle
246+
* @param[in] odr Gyroscope measurement range
247+
*
248+
* @return
249+
* - ESP_OK Success
250+
* - Or other errors from the underlying I2C driver
251+
*/
252+
esp_err_t bmi270_set_gyro_range(bmi270_handle_t *dev_handle, bmi270_gyro_range_e range);
253+
254+
#ifdef __cplusplus
255+
}
256+
#endif

0 commit comments

Comments
 (0)