BNO055: change I2C address during runtime

Dear Forum-users,

in my project I want to connect multiple BNO055 sensors to my Arduino mega. However, the BNO055 can also take two different addresses on the I2C bus (0x28 and 0x29) which can be changed by pulling the address pin HIGH or LOW. So, as a start, I had the idea to connect the address pins of the sensors to I/O pins and change them in a loop and read only one sensor at a time. For checking, if the BNO055 can change its address during runtime I wrote this little sketch

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>

int delayTime = 1000;

int OutPin = 8;

Adafruit_BNO055 bno = Adafruit_BNO055(4, BNO055_ADDRESS_A);

void setup() {
  pinMode(OutPin,OUTPUT);
  digitalWrite(OutPin,LOW);
 
  Serial.begin(9600);


  bno.setExtCrystalUse(true);

  // calibrate sensor
  Serial.println("Calibrate the first sensor!");
  sensors_event_t event;
    while (!bno.isFullyCalibrated())
    {
    bno.getEvent(&event);
    Serial.print("X: ");
    Serial.print(event.orientation.x, 4);
    Serial.print("\tY: ");
    Serial.print(event.orientation.y, 4);
    Serial.print("\tZ: ");
    Serial.print(event.orientation.z, 4);
    uint8_t system, gyro, accel, mag = 0;
    bno.getCalibration(&system, &gyro, &accel, &mag);
    Serial.print("CALIBRATION: Sys=");
    Serial.print(system, DEC);
    Serial.print(" G=");
    Serial.print(gyro, DEC);
    Serial.print(" A=");
    Serial.print(accel, DEC);
    Serial.print(" M=");
    Serial.println(mag, DEC);  
    delay(delayTime);
    }  
    Serial.println("Sensor 1 is fully calibrated!");

}

void loop() {
    // first address 0x28  
    digitalWrite(OutPin,LOW);
    bno = Adafruit_BNO055(4, BNO055_ADDRESS_A);

   sensors_event_t event;
    bno.getEvent(&event);
    Serial.println("First address:");
    Serial.print("X: ");
    Serial.print(event.orientation.x, 4);
    Serial.print("\tY: ");
    Serial.print(event.orientation.y, 4);
    Serial.print("\tZ: ");
    Serial.print(event.orientation.z, 4);
    uint8_t system, gyro, accel, mag = 0;
    bno.getCalibration(&system, &gyro, &accel, &mag);
    Serial.print("CALIBRATION: Sys=");
    Serial.print(system, DEC);
    Serial.print(" G=");
    Serial.print(gyro, DEC);
    Serial.print(" A=");
    Serial.print(accel, DEC);
    Serial.print(" M=");
    Serial.println(mag, DEC);  
    delay(delayTime);


    // second address 0x29  
    digitalWrite(OutPin,HIGH);
    bno = Adafruit_BNO055(4, BNO055_ADDRESS_B);

    bno.getEvent(&event);
    Serial.println("Second address:");
    Serial.print("X: ");
    Serial.print(event.orientation.x, 4);
    Serial.print("\tY: ");
    Serial.print(event.orientation.y, 4);
    Serial.print("\tZ: ");
    Serial.print(event.orientation.z, 4);

    bno.getCalibration(&system, &gyro, &accel, &mag);
    Serial.print("CALIBRATION: Sys=");
    Serial.print(system, DEC);
    Serial.print(" G=");
    Serial.print(gyro, DEC);
    Serial.print(" A=");
    Serial.print(accel, DEC);
    Serial.print(" M=");
    Serial.println(mag, DEC);  
    delay(delayTime);


}

Although the principle is really simple, it seems that the change of address somehow is not working. Has anyone any experience with this? I would appreciate any help. Or is the only way to get multiple sensors working with a multiplexer?

Thanks in advance.

What evidence do you have that it doesn't work? Provide some program output.

Regardless, I'm not convinced that the test you have done is valid. You don't treat the sensor the same way between setup() and loop(). After it has been initialized, the internal CPU in the sensor may not be reading the address pin.

Do a new test, in which you hard wire the address pin either high or low. Have the program address the device at either 0x28 or 0x29. Note that there is a BNO055 command to perform a system reset.

Thanks for the answer. Here is a piece of the output of the code above in the serial monitor (in the loop):

First address:
X: 26.0625	Y: 13.3750	Z: 118.9375 CALIBRATION: Sys=0 G=3 A=3 M=3
Second address:
X: -0.0625	Y: -0.0625	Z: -0.0625 CALIBRATION: Sys=3 G=3 A=3 M=3
First address:
X: 102.1250	Y: 63.1875	Z: 115.7500 CALIBRATION: Sys=0 G=3 A=3 M=3
Second address:
X: -0.0625	Y: -0.0625	Z: -0.0625 CALIBRATION: Sys=3 G=3 A=3 M=3
First address:
X: 111.5000	Y: 52.0625	Z: 34.5000 CALIBRATION: Sys=0 G=3 A=3 M=3
Second address:
X: -0.0625	Y: -0.0625	Z: -0.0625 CALIBRATION: Sys=3 G=3 A=3 M=3
First address:
X: 114.3750	Y: 51.8750	Z: 27.8125 CALIBRATION: Sys=0 G=3 A=3 M=3
Second address:
X: -0.0625	Y: -0.0625	Z: -0.0625 CALIBRATION: Sys=3 G=3 A=3 M=3

While "First address" changes when moving the sensor, "Second address" just returns random values. As you said, it seems that the address change is not noticed. So how do I get the CPU read the new address? A system reset would mean the sensor has to calibrate again, doesnt it? I would like to avoid that.

I hardwired the ADR pin of the sensor to low and high, and addressing the sensor at either address works perfectly.

Thanks for your help.

1 Like

The second address values aren't random, but they clearly are wrong, suggesting that the BNO055 CPU does not read the address pin after startup.

Try sending the BNO055 a system reset command after (or "instantaneously" before) changing the address pin value.

Also, I wonder about creating two instances of the "bno" object with the same name but different addresses. Try creating bno28 and bno29 instead.

1 Like

Thanks for the suggestion. I have tried around alot now and unfortunately none of my attempts work. When I do a system rest (at any place in the program) both sensors return wrong values. Actually, the first sensor shows the same constant values as the second sensor (see previous post for the values). I also tried to instantiate two classes (one for each address) in the global scope, before the setup and loop routines, but no success.

I really think of buying a multiplexer now.

When I do a system rest (at any place in the program) both sensors return wrong values.

Then something is wrong with the code. In my autonomous robot, a BNO055 "system reset" is performed at bootup and the pre-calculated calibration vectors for the installation are written. After that, put the BNO055 into the appropriate run mode, and it works quite well.

Hi everyone,
Were you able to solve the problem in the end? I see that a solution was proposed, but I haven't understood if that actually worked in the end.

1 Like