Interfacing with a BMI270 + aux BMM150: Zephyr sensor subsystem or Bosch drivers?

I have a custom board with a BMD-300 (nRF52832), a BMI270 (accelerometer, gyroscope) and BMM150 (magnetometer), where the BMM150 is connected via the auxiliary connections on the BMI270:
www.bosch-sensortec.com/.../bst-bmi270-ds000.pdf

From what I can tell, the only examples that exist for programming this use the Bosch drivers here:

github.com/.../BMI270-Sensor-API
github.com/.../BMM150-Sensor-API

There also exists a Zephyr driver for both sensors, but from what I can tell, there's no aux support in the BMI270 driver. My firmware is using the nRF Connect SDK and Zephyr already (not the legacy nRF52 SDK).

What's the recommended approach for interfacing with these two sensors? Are there any novice-friendly examples for how to accomplish this, or i2c sensor handling in general (outside of a driver, if that's what's recommended)?

Thank you for any help you can give.

  • Do you need to use the AUX interface at all? I ask because if the two sensors can share the same I2C bus then Zephyr's Sensor Device Drivers will work just fine with both devices as is.

    Zephyr's BMI270 Sensor Device Driver (zephyr\drivers\sensor\bmi270\bmi270.c) does not support the AUX interface, it would be very helpful if you'd ask Bosch to add this support.

    One "not-so-beginner-firendly" option is to add this support yourself by expanding Zephyr's BMI270 Sensor Device Driver with the corresponding behaviour of https://github.com/boschsensortec/BMI270-Sensor-API/blob/master/bmi270_examples/sensor_data/sensor_data.c (the example that includes the BMM150 on the AUX interface of the BMI270).

    One "beginner-friendly" option is to use the NRFX I2C driver directly and port github.com/.../BMI270-Sensor-API.

  • Thanks haakonsh. I tried moving the BMM150 onto the same I2C bus as the BMI270, but for some reason, it's giving me a -5 return code, which seems to be an "Address not acknowledged" error. Do you know why this would occur?

    Unfortunately, the custom board is tiny, so getting oscilloscope probes attached is difficult.

    This is the code I'm using to read from the BMM150:

    int read_bmm150_id_tmp(void) {
    	LOG_INF("IMU: Reading BMM150 CHIP ID");
    	static const struct i2c_dt_spec dev_i2c = I2C_DT_SPEC_GET(I2C0_NODE_BMM150);
    
    	// Check if the device is ready
    	if (!device_is_ready(dev_i2c.bus)) {
    		printk("IMU I2C bus %s is not ready!\n\r",dev_i2c.bus->name);
    		blink_with_colors(BRIGHTNESS_MAX_LEVEL, 0, 0, 0, 250, 2);
    		return -1;
    	}
    
    	// Write the power control bit in order to read the chip ID
    	uint8_t config_pwr[2] = {0x4B, 0x01};
    	int ret = i2c_write_dt(&dev_i2c, config_pwr, sizeof(config_pwr));
    	if (ret != 0) {
    		LOG_ERR("Failed to write to I2C device address");
    		blink_with_colors(BRIGHTNESS_MAX_LEVEL, 0, 0, 0, 250, 3);
    		return -1;
    	}
    
    	// Read device ID
    	uint8_t register_addr = 0x40;
    	uint8_t temp_reading[1] = {0};
    	uint8_t sensor_regs[1] = {register_addr};
    	ret = i2c_write_read_dt(&dev_i2c, &sensor_regs[0], 1, &temp_reading[0], 1);
    	if (ret != 0) {
    		LOG_ERR("Failed to write/read I2C device address");
    		blink_with_colors(BRIGHTNESS_MAX_LEVEL, 0, 0, 0, 250, 4);
    		return -1;
    	}
    	LOG_INF("Chip ID at register %d has value %d", register_addr, temp_reading[0]);
    
    	// BMM150 chip ID is 0x32
    	if (temp_reading[0] == 0x32) {
    		// Green
    		blink_with_colors(0, BRIGHTNESS_MAX_LEVEL, 0, 0, 250, 5);
    	} else {
    		// Red
    		blink_with_colors(BRIGHTNESS_MAX_LEVEL, 0, 0, 0, 250, 5);
    	}
    
    	return 0;
    }

    And my .dts file:

    &i2c0 {
    	compatible = "nordic,nrf-twi";
    	status = "okay";
    
    	pinctrl-0 = <&i2c0_default>;
    	pinctrl-1 = <&i2c0_sleep>;
    	pinctrl-names = "default", "sleep";
    	clock-frequency = <100000>;
    
    	bmi270: bmi270@68 {
    		compatible = "bosch,bmi270";
    		reg = <0x68>;
    		label = "BMI270";
    	};
    
    	bmm150: bmm150@10 {
    		compatible = "bosch,bmm150";
    		reg = <0x10>;
    		label = "BMM150";
    	};
    };

    In my prj.conf I have these relevant options enabled:

    CONFIG_I2C=y
    CONFIG_SENSOR=y
    CONFIG_BMI270=y
    CONFIG_BMM150=y

    Does anything jump out as being incorrect here?

    The only thing I can think of is the BMM150's SDA and SCL are still connected to the AUX SDA and SCL lines on the BMMI270 - I just connected them to the SDA/SCL of the BMI270 as well. Would that cause the problem I'm seeing? Do I need to cut these traces, or fabricate a new board?

    Any help you could provide would be greatly appreciated. Thank you.

  • deveryn said:
    I tried moving the BMM150 onto the same I2C bus as the BMI270, but for some reason, it's giving me a -5 return code, which seems to be an "Address not acknowledged" error. Do you know why this would occur?

    Is 0x10 the correct address? What is the state of the CSB and SDO pins?

    deveryn said:
    Unfortunately, the custom board is tiny, so getting oscilloscope probes attached is difficult.

    I strongly urge you to design development-friendly prototypes for future projects. The size of your end-product should have little relevance to the design of the prototype you use for development. 

    deveryn said:
    The only thing I can think of is the BMM150's SDA and SCL are still connected to the AUX SDA and SCL lines on the BMMI270 - I just connected them to the SDA/SCL of the BMI270 as well. Would that cause the problem I'm seeing? Do I need to cut these traces, or fabricate a new board?

    You should probably cut those traces, as feeding an I2C bus into the AUX interface is likely operating the device out of spec. 

  • Is 0x10 the correct address? What is the state of the CSB and SDO pins?

    Yes, I double and triple-checked. I also tried with all the potential addresses from 0x10 to 0x13 just to be sure.

    I strongly urge you to design development-friendly prototypes for future projects. The size of your end-product should have little relevance to the design of the prototype you use for development. 

    You're right - in hindsight, going straight to the tiny custom board after using an nRF DK was dumb!

    You should probably cut those traces, as feeding an I2C bus into the AUX interface is likely operating the device out of spec. 

    I will try cutting the traces. Thank you for your help!

  • deveryn said:
    You're right - in hindsight, going straight to the tiny custom board after using an nRF DK was dumb!

    We've all been there. It's a painful mistake, but your future self will thank you for remembering it :) 

Related