9#ifdef USE_BMI270_BMM150
10using namespace bmm150;
18#if defined(USE_ARDUINO) && !defined(USE_ESP32)
19static constexpr size_t MAX_I2C_BUFFER_SIZE = 32;
21static constexpr size_t MAX_I2C_BUFFER_SIZE = 256;
30 if (!this->
write_byte(BMI270_REG_PWR_CONF, BMI270_PWR_CONF_ADV_POWER_SAVE_OFF))
35 if (!this->
write_byte(BMI270_REG_INIT_CTRL, BMI270_INIT_CTRL_LOAD_START))
39 const uint8_t *cfg = BMI270_CONFIG_FILE;
40 constexpr size_t cfg_len =
sizeof(BMI270_CONFIG_FILE);
43 while (index != cfg_len) {
45 uint8_t addr_lsb = (uint8_t) ((index / 2) & 0x0F);
46 uint8_t addr_msb = (uint8_t) ((index / 2) >> 4);
47 if (!this->
write_byte(BMI270_REG_INIT_ADDR_0, addr_lsb))
49 if (!this->
write_byte(BMI270_REG_INIT_ADDR_0 + 1, addr_msb))
53 size_t burst =
clamp_at_most(cfg_len - index, MAX_I2C_BUFFER_SIZE);
61 if (!this->
write_byte(BMI270_REG_INIT_CTRL, BMI270_INIT_CTRL_LOAD_DONE))
69 if ((
status & BMI270_INTERNAL_STATUS_MASK) != BMI270_INTERNAL_STATUS_INIT_OK) {
70 ESP_LOGE(TAG,
"Config load failed: INTERNAL_STATUS=0x%02X (expected 0x01)",
status);
79 MotionComponent::setup();
82 if (!this->
read_byte(BMI270_REG_CHIP_ID, &chip_id)) {
86 if (chip_id != BMI270_CHIP_ID_VALUE) {
87 ESP_LOGE(TAG,
"Wrong chip ID: 0x%02X (expected 0x%02X)", chip_id, BMI270_CHIP_ID_VALUE);
91 ESP_LOGD(TAG,
"Chip ID: 0x%02X", chip_id);
94 if (!this->
write_byte(BMI270_REG_CMD, BMI270_CMD_SOFT_RESET)) {
102 this->
mark_failed(LOG_STR(
"Config file upload failed"));
105 ESP_LOGD(TAG,
"Config blob uploaded ✓");
110 (uint8_t) (
accel_odr_) | (BMI270_CONF_BWP_NORMAL << BMI270_CONF_BWP_SHIFT) | BMI270_ACC_CONF_PERF_MODE;
111 if (!this->
write_byte(BMI270_REG_ACC_CONF, acc_conf)) {
122 uint8_t gyr_conf = (uint8_t) (
gyro_odr_) | (BMI270_CONF_BWP_NORMAL << BMI270_CONF_BWP_SHIFT) |
123 BMI270_GYR_CONF_NOISE_PERF | BMI270_GYR_CONF_FILTER_PERF;
124 if (!this->
write_byte(BMI270_REG_GYR_CONF, gyr_conf)) {
135 if (!this->
write_byte(BMI270_REG_PWR_CTRL, BMI270_PWR_CTRL_IMU)) {
143 if (!this->
write_byte(BMI270_REG_PWR_CONF, BMI270_PWR_CONF_FIFO_SELF_WAKEUP)) {
151#ifdef USE_BMI270_BMM150
155 ESP_LOGW(TAG,
"BMM150 magnetometer setup failed; continuing without it");
160 ESP_LOGCONFIG(TAG,
"BMI270 initialised successfully");
163#ifdef USE_BMI270_BMM150
173 if ((
status & BMI270_STATUS_AUX_BUSY) == 0)
175 if (
millis() - start >= timeout_ms)
182 if (!this->
write_byte(BMI270_REG_AUX_WR_DATA, value))
194 return this->
read_bytes(BMI270_REG_AUX_X_LSB, buf, BMI270_AUX_DATA_LEN);
198 uint8_t regs[BMM150_TRIM_BLOCKS * BMM150_TRIM_BLOCK_LEN];
199 for (uint8_t i = 0; i < BMM150_TRIM_BLOCKS; i++) {
200 if (!this->
read_aux_block_(BMM150_REG_TRIM_START + i * BMM150_TRIM_BLOCK_LEN, regs + i * BMM150_TRIM_BLOCK_LEN))
213 ESP_LOGD(TAG,
"Setting up BMM150 magnetometer via BMI270 aux interface...");
215 if (!this->
write_byte(BMI270_REG_IF_CONF, BMI270_IF_CONF_AUX_IF_EN))
217 if (!this->
write_byte(BMI270_REG_AUX_IF_CONF, BMI270_AUX_IF_CONF_MANUAL_EN | BMI270_AUX_IF_CONF_MAN_RD_BURST_8))
225 ESP_LOGW(TAG,
"BMM150 power-on write timed out");
228 delay(BMM150_START_UP_TIME_MS);
230 ESP_LOGW(TAG,
"BMM150 soft-reset write timed out");
233 delay(BMM150_SOFT_RESET_TIME_MS);
235 uint8_t chip_id[BMI270_AUX_DATA_LEN];
237 ESP_LOGW(TAG,
"BMM150 chip-ID read failed");
240 if (chip_id[0] != BMM150_CHIP_ID_VALUE) {
241 ESP_LOGW(TAG,
"BMM150 not detected (chip ID 0x%02X, expected 0x%02X)", chip_id[0], BMM150_CHIP_ID_VALUE);
246 ESP_LOGW(TAG,
"BMM150 trim data read failed");
251 ESP_LOGW(TAG,
"BMM150 mode write timed out");
257 if (!this->
write_byte(BMI270_REG_AUX_IF_CONF, BMI270_AUX_IF_CONF_FCU_WRITE_EN | BMI270_AUX_IF_CONF_MAN_RD_BURST_8 |
258 BMI270_AUX_IF_CONF_RD_BURST_8))
260 if (!this->
write_byte(BMI270_REG_AUX_RD_ADDR, BMM150_REG_DATA_X_LSB))
262 if (!this->
write_byte(BMI270_REG_PWR_CTRL, BMI270_PWR_CTRL_IMU | BMI270_PWR_CTRL_AUX_EN))
265 ESP_LOGD(TAG,
"BMM150 magnetometer ready");
271 ESP_LOGCONFIG(TAG,
"BMI270 IMU:");
272 LOG_I2C_DEVICE(
this);
276 ESP_LOGCONFIG(TAG,
" Accel range : %s",
277 LOG_STR_ARG(AccelRangeStrings::get_log_str(this->
accel_range_, AccelRangeStrings::LAST_INDEX)));
278 ESP_LOGCONFIG(TAG,
" Gyro range : %s",
279 LOG_STR_ARG(GyroRangeStrings::get_log_str(this->
gyro_range_, GyroRangeStrings::LAST_INDEX)));
280#ifdef USE_BMI270_BMM150
282 ESP_LOGCONFIG(TAG,
" Aux device : BMM150 magnetometer (%s)",
286 MotionComponent::dump_config();
299#ifdef USE_BMI270_BMM150
301 uint8_t buf[BMI270_AUX_DATA_LEN + REG_READ_LEN];
302 const uint8_t *mag_raw = buf;
303 const uint8_t *raw_data = read_mag ? buf + BMI270_AUX_DATA_LEN : buf;
304 const bool read_ok = read_mag ? this->
read_bytes(BMI270_REG_AUX_X_LSB, buf,
sizeof(buf))
305 : this->
read_bytes(BMI270_REG_DATA_8, buf, REG_READ_LEN);
307 uint8_t buf[REG_READ_LEN];
308 const uint8_t *raw_data = buf;
309 const bool read_ok = this->
read_bytes(BMI270_REG_DATA_8, buf, REG_READ_LEN);
312 ESP_LOGW(TAG,
"Failed to read IMU data");
318 alignas(4)
static constexpr float ACCEL_SCALE[] PROGMEM = {
326 data.
acceleration[motion::X_AXIS] = (int16_t) ((raw_data[1] << 8) | raw_data[0]) * scale;
327 data.acceleration[motion::Y_AXIS] = (int16_t) ((raw_data[3] << 8) | raw_data[2]) * scale;
328 data.acceleration[motion::Z_AXIS] = (int16_t) ((raw_data[5] << 8) | raw_data[4]) * scale;
332 alignas(4)
static constexpr float GYRO_SCALE[] PROGMEM = {
333 2000.0f / 32768.0f, 1000.0f / 32768.0f, 500.0f / 32768.0f, 250.0f / 32768.0f, 125.0f / 32768.0f,
335 static constexpr uint8_t GYR_OFFS = BMI270_REG_DATA_14 - BMI270_REG_DATA_8;
338 data.
angular_rate[motion::X_AXIS] = (int16_t) ((raw_data[GYR_OFFS + 1] << 8) | raw_data[GYR_OFFS + 0]) * scale;
339 data.angular_rate[motion::Y_AXIS] = (int16_t) ((raw_data[GYR_OFFS + 3] << 8) | raw_data[GYR_OFFS + 2]) * scale;
340 data.angular_rate[motion::Z_AXIS] = (int16_t) ((raw_data[GYR_OFFS + 5] << 8) | raw_data[GYR_OFFS + 4]) * scale;
345 static constexpr uint8_t TEMP_OFFS = BMI270_REG_TEMP_0 - BMI270_REG_DATA_8;
346 int16_t raw_t = (int16_t) ((raw_data[TEMP_OFFS + 1] << 8) | raw_data[TEMP_OFFS + 0]);
351#ifdef USE_BMI270_BMM150
void mark_failed()
Mark this component as failed.
uint8_t aux_device_address_
bool read_magnetometer_trim_()
bmm150::BMM150Trim mag_trim_
LazyCallbackManager< void(const bmm150::BMM150Data &)> magnetometer_callback_
LazyCallbackManager< void(float)> temperature_callback_
bool update_data(motion::MotionData &data) override
bool read_aux_block_(uint8_t reg, uint8_t *buf)
BMI270AuxDevice aux_device_
BMI270AccelODR accel_odr_
BMI270AccelRange accel_range_
bool wait_for_aux_idle_(uint32_t timeout_ms)
bool write_aux_register_(uint8_t reg, uint8_t value)
void dump_config() override
bool setup_magnetometer_()
BMI270GyroRange gyro_range_
ErrorCode write_register(uint8_t a_register, const uint8_t *data, size_t len) const
writes an array of bytes to a specific register in the I²C device
bool write_byte(uint8_t a_register, uint8_t data) const
bool read_byte(uint8_t a_register, uint8_t *data)
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
bool read_bytes(uint8_t a_register, uint8_t *data, uint8_t len)
Compat APIs All methods below have been added for compatibility reasons.
BMM150Data bmm150_convert(const BMM150Trim &trim, const uint8_t *raw)
BMM150Trim bmm150_parse_trim(const uint8_t *regs)
ESPHOME_LOG_TAG(TAG, "bmi270")
PROGMEM_STRING_TABLE(AccelRangeStrings, "±2g", "±4g", "±8g", "±16g")
@ BMI270_AUX_DEVICE_BMM150
@ ERROR_OK
No error found during execution of method.
T clamp_at_most(T value, U max)
void HOT delay(uint32_t ms)
uint32_t IRAM_ATTR HOT millis()