Yesuah Balderas
Yesuah Balderas

Reputation: 1

Struggling with auxilary I2C communication with BMI270

I have a breakout board that uses the BMI270 and the LIS2MDL magnetometer, the lis2MDL SDA and SCL pins are connected though the ASCX and ASDX pins of the BMI270. Essentially making it a slave device of the BMI270. The BMI270 uses the address 0x68, which should be the same address I communicate with the LIS2MDL, too. However, I'm getting issues actually communicating with the LIS2MDL, but have no issues communicating to the IMU. On page 60 of this PDF, it goes over auxiliary communication via I2C:

https://www.lcsc.com/datasheet/lcsc_datasheet_2207152130_Bosch-Sensortec-BMI270_C2836813.pdf

I'm very confused and lost at this point. Below is part of my Arduino code, the end print statement should be the chip ID of the LIS2MDL, however, I just get "42" which is not supposed to be it. This indicates I'm maybe not communicating to the sensor. Additionally, when I try to get values from the sensor I get "16962" but does not update.

Below is the code:

// I2C addresses
#define BMI270_ADDR 0x68   // I2C address of BMI270
#define LIS2MDL_ADDR 0x1E  // Default I2C address of LIS2MDL (on auxiliary bus)

// BMI270 Register Addresses
#define BMI270_AUX_CONFIG 0x4B  // Auxiliary I2C configuration register
#define BMI270_AUX_WRITE 0x4C   // Write to auxiliary device (LIS2MDL)
#define BMI270_AUX_READ 0x4D    // Read from auxiliary device (LIS2MDL)
#define BMI270_CTRL 0x7E        // Control register for sensor modes
#define BMI270_AUX_EN 0x44      // Auxiliary I2C enable

// LIS2MDL Register Addresses
#define LIS2MDL_WHO_AM_I 0x4F   // WHO_AM_I register to verify sensor identity
#define LIS2MDL_OUTX_L  0x68    // Output registers for magnetometer data

#define SDA_PIN 21  // Define your SDA pin
#define SCL_PIN 26  // Define your SCL pin

// Variables to hold sensor data
int16_t magX, magY, magZ;

void setup() {
  Wire.begin(SDA_PIN, SCL_PIN);    // Start I2C communication for ESP32

  Serial.begin(115200);  // Start serial communication for debugging

  delay(1000);

  // Initialize BMI270 (primary sensor)
  initBMI270();

  // Enable auxiliary I2C to communicate with LIS2MDL
  enableAuxiliaryI2C();

  // Check communication with LIS2MDL (WHO_AM_I)
  uint8_t whoAmI = readAuxRegister(LIS2MDL_WHO_AM_I);
  if (whoAmI == 0x40) {  // Expected WHO_AM_I response from LIS2MDL
    Serial.println("LIS2MDL communication successful!");
  } else {
    Serial.print("LIS2MDL communication failed, WHO_AM_I: ");
    Serial.println(whoAmI, HEX);
  }
}

void loop() {
  // Read magnetometer data from LIS2MDL through the BMI270
  readMagnetometerData();
  Serial.print("Magnetometer X: "); Serial.println(magX);
  Serial.print("Magnetometer Y: "); Serial.println(magY);
  Serial.print("Magnetometer Z: "); Serial.println(magZ);
  delay(1000);  // Wait before reading again
}

// Function to initialize the BMI270
void initBMI270() {
  // Put BMI270 into configuration mode
  writeRegister(BMI270_ADDR, BMI270_CTRL, 0x00);  // Placeholder configuration mode
  delay(10);

  // Additional setup if required (e.g., accelerometer or gyroscope config)
  Serial.println("BMI270 initialized.");
}

// Function to enable the auxiliary I2C on the BMI270
void enableAuxiliaryI2C() {
  // Enable auxiliary I2C in BMI270 to talk to LIS2MDL
  writeRegister(BMI270_ADDR, BMI270_AUX_CONFIG, 0x01);  // Enable AUX I2C mode
  delay(10);  // Allow time for configuration
  Serial.println("Auxiliary I2C enabled.");
}

// Function to read magnetometer data from LIS2MDL
void readMagnetometerData() {
  uint8_t data[6];
  
  // Read 6 bytes from LIS2MDL (magnetometer output)
  for (int i = 0; i < 6; i++) {
    data[i] = readAuxRegister(LIS2MDL_OUTX_L + i);
  }

  // Combine bytes into 16-bit integers (LSB first)
  magX = (int16_t)(data[1] << 8 | data[0]);
  magY = (int16_t)(data[3] << 8 | data[2]);
  magZ = (int16_t)(data[5] << 8 | data[4]);
}

// Helper function to write to BMI270 register
void writeRegister(uint8_t address, uint8_t reg, uint8_t value) {
  Wire.beginTransmission(address);
  Wire.write(reg);
  Wire.write(value);
  Wire.endTransmission();
}

// Helper function to read from BMI270's auxiliary I2C bus (LIS2MDL)
uint8_t readAuxRegister(uint8_t reg) {
  // Set the register to read from in the auxiliary device (LIS2MDL)
  writeRegister(BMI270_ADDR, BMI270_AUX_WRITE, reg);
  delay(10);  // Wait for the register to be set

  // Read the result from the auxiliary read register of BMI270
  Wire.beginTransmission(BMI270_ADDR);
  Wire.write(BMI270_AUX_READ);
  Wire.endTransmission(false);
  Wire.requestFrom(BMI270_ADDR, 1);

  if (Wire.available()) {
    return Wire.read();
  }
  return 0xFF;  // Return an invalid value if communication failed
}

schematic

I tried using a combination of pre-made libraries for both sensors and even made some custom I2C code, which to be honest, I've never done. So I did use ChatGPT for help. Each time, I simply was not able to communicate to the magnetometer but was able to communicate to the Gyro.

Upvotes: 0

Views: 167

Answers (1)

Marwan275
Marwan275

Reputation: 1

In the Arduino examples, there is an example named i2c_scanner, run it and check if two addresses appeared in the serial monitor.

Upvotes: 0

Related Questions