BNO055 via i2C

MetaWear RPro
MetaWear Android SDK: 2.3.0
MetaWear Firmware: 1.1.0
OnePlus Two running Android v5.1.1

I am trying to connect to an Adafruit BNO055 breakout board (https://www.adafruit.com/product/2472) through the i2c interface.  I am also able to compare the readings from an Arduino using the Adafruit library (https://github.com/adafruit/Adafruit_BNO055).

I am accessing the i2cModule via a routeData chain and using the timerModule to poll.  Here is a sample of pulling the first 7 bytes from the BNO board from the Arduino and the MetaWear API:

Arduino  readLen(buffer, 0x00, 7): A0, FB, 32, 0F, 11, 03, 15
Android readData(40, 0x00, 7, 69): a0, fb, 32, 0f, 11, 03, 15

Following the examples, the Arduino queries the 0x00 register to ensure that 0xA0 is returned.  Both are able to query this address just fine.

According to the Adafruit_BNO055.h, I should be able to query 6 bytes from 0x1A to receive the Euler data registers.  However this does not returning anything on the MetaWear:

Arduino  readLen(buffer, 0x1A, 6): 80, 16, F9, FF, DE, FF
Android readData(40, 0x1A, 6, 69): 00, 00, 00, 00, 00, 00

I have stripped down the Arduino sketch to simply reading those registers (so removing the bno.begin call, bno.enable) and I'm receiving the data just fine.  I am not sure how else to proceed

Comments

  • As a follow up on my previous post, I have translated the bno.begin() method from the Arduino library to the i2cModule.  I can continue to read the first seven address locations without a problem.

    Is there an address restriction enforced on the MetaWear i2c interface?  For example to only address at 3 bits?  I do not receive any values for addresses above 0x07.

    Are there any other restrictions enforced through the MetaWear i2c interface?
  • No, you can use addresses above 0x07.  For example, if you are using a MetaWear R, then you would use address 0x1c to communicate with the accelerometer and address 0xd to read the WHO_AM_I register.

    Which GPIO pins are you using to connect the MetaWear to the BNO055?

    The RPro boards also use a Bosch chip, BMI160.  Though given the results of your initial read, it does not appear you are reading the BMI160 chip instead of the BNO055.
  • Hi @seamus

    I ran some tests with an oscilloscope and confirmed a successful read of addresses higher than 0x07 via the I2C module.

    It is also worth nothing that if an external chip does not respond to a device address, the I2C module will return a null packet -- the six 0x00 bytes are definitely being read out over the I2C bus from something.

    Working with other Bosch sensors the data registers are normally 0x00 at reset.  My gut instinct is that one of the init commands that starts the sensors may be getting ignored, missed, or rejected somehow.

    Maybe when you removed the code from .begin() on the Arduino, the BNO055 was not power cycled to reset it to the default state -- that could explain why it was returning data without an init or enable procedure.

    My next steps would be to add a delay between all the commands in the init procedure to be sure everything is getting through.  At least on the BMI160, you can only send one write command every 450us while it is in the sleep state.  Or, depending how you have everything wired up, maybe the Arduino init could be run, and then the MetaWear could try reading those registers over the same bus.
  • edited January 2016
    Eric,

    Thank you for your reply.  I have the BNO055 board wired to the i2c interface:

    BNO055 <-> RPro
    VIN <-> 11
    GND <-> 4
    SDA <-> 5
    SCL <-> 6

    I am connecting to address 0x28 (40) which is the same address when connecting via the Arduino.  The first 7 registers match between communication from the Arduino and the RPro so I can only assume that the RPro is connecting to the BNO055.
  • Matt,

    Thank you for your reply and verifying communications with an oscilloscope.

    As part of the Arduino translation to i2cModule, I implemented the delays using Thread.sleep(ms).  All delays in the Arduino code are in ms.  However there are some writes that do not have a delay so I have since added delays between every i2cModule.write command.

    I have tried delays of 10, 30, 50, and 800 and I still receive nulls.  The only write command that has a larger delay of 2000ms is the BNO reset command: i2cModule.writeData(40, 0x3F, Array(0x20.toByte))  And I have tried delays of 500, 1000, 2000, 5000 and 10000.

    I have separate prototype boards for the Arduino and the RPro so I have been moving the BNO055 board between the two.  I will try wiring the Arduino and RPro i2c lines (and ground) to a breadboard and then initialise the BNO from the Arduino and then try reading from the RPro.
  • Hi Matt,

    Here is my initialisation code with the Arduino code as comments:

    //    BNO055_OPR_MODE_ADDR = 0X3D   
    //    OPERATION_MODE_CONFIG = 0X00
    //    void Adafruit_BNO055::setMode(adafruit_bno055_opmode_t mode)
    //    {
    //      _mode = mode;
    //      write8(BNO055_OPR_MODE_ADDR, _mode);
    //      delay(30);
    //    }

    // setMode(OPERATION_MODE_CONFIG);
    i2cModule.writeData(40, 0x3D, Array(0.toByte))
    Thread.sleep(delay)

    //    /* Reset */
    //    BNO055_SYS_TRIGGER_ADDR = 0X3F
    //    write8(BNO055_SYS_TRIGGER_ADDR, 0x20);
    //    while (read8(BNO055_CHIP_ID_ADDR) != BNO055_ID)
    //    {
    //      delay(10);
    //    }
    //    delay(50)
    i2cModule.writeData(40, 0x3F, Array(0x20.toByte))
    Thread.sleep(5000)

    //    /* Set to normal power mode */
    //    BNO055_PWR_MODE_ADDR = 0X3E   
    //    POWER_MODE_NORMAL = 0X00
    //    write8(BNO055_PWR_MODE_ADDR, POWER_MODE_NORMAL);
    //    delay(10);
    //

    i2cModule.writeData(40, 0x3E, Array(0.toByte))
    Thread.sleep(delay)

    //    BNO055_PAGE_ID_ADDR = 0X07   
    //    write8(BNO055_PAGE_ID_ADDR, 0);
    i2cModule.writeData(40, 0x07, Array(0.toByte))
    Thread.sleep(delay)

    //    BNO055_SYS_TRIGGER_ADDR = 0X3F   
    //    write8(BNO055_SYS_TRIGGER_ADDR, 0x0);
    //    delay(10);
    i2cModule.writeData(40, 0x3F, Array(0.toByte))
    Thread.sleep(delay)

    //    setMode(mode);
    //    delay(20);
    i2cModule.writeData(40, 0x3D, Array(0.toByte))
    Thread.sleep(delay)

  • @seamus : For test purposes I would advise a minimum delay of 100-200 ms.  Delays less than 40-50ms in the Android thread may still result in BLE commands being issued in the same connection period, which would undo the delay.  That being said, if you tried 800ms, then any delay related issue would have been covered.

    Looking at the code snippet, I think maybe there is an issue with the last command issued:
    //    setMode(mode);
    //    delay(20);
    i2cModule.writeData(40, 0x3D, Array(0.toByte))
    Thread.sleep(delay)

    In the Arduino code, that mode variable is being passed in from somewhere outside the C++ class, maybe from the main thread.  Passing "0" will keep the device in the config mode rather than a running mode.  Here is the config struct, maybe one of these options will help:

    typedef enum {
      OPERATION_MODE_CONFIG                                   = 0X00,
      OPERATION_MODE_ACCONLY                                  = 0X01,
      OPERATION_MODE_MAGONLY                                  = 0X02,
      OPERATION_MODE_GYRONLY                                  = 0X03,
      OPERATION_MODE_ACCMAG                                   = 0X04,
      OPERATION_MODE_ACCGYRO                                  = 0X05,
      OPERATION_MODE_MAGGYRO                                  = 0X06,
      OPERATION_MODE_AMG                                      = 0X07,
      OPERATION_MODE_IMUPLUS                                  = 0X08,
      OPERATION_MODE_COMPASS                                  = 0X09,
      OPERATION_MODE_M4G                                      = 0X0A,
      OPERATION_MODE_NDOF_FMC_OFF                             = 0X0B,
      OPERATION_MODE_NDOF                                     = 0X0C
    } adafruit_bno055_opmode_t;
  • Looks like they are using OPERATION_MODE_NDOF by default in their class header:
    bool begin ( adafruit_bno055_opmode_t mode = OPERATION_MODE_NDOF );
  • Thank you, Matt!!

    The logs are full of Euler data!  I assumed that the default mode was 0x00 from this comment on line 71 of the begin() method:

    /* Switch to config mode (just in case since this is the default) */
    https://github.com/adafruit/Adafruit_BNO055/blob/master/Adafruit_BNO055.cpp#L71

    The sample Arduino code simply called .begin() without passing a default mode.  I never thought to look at the header definition.

    Thank you again Matt!
  • @seamus : No problem.  

    Hmm, yeah they must have meant to say "isn't" in that comment.  My C++ is a bit rusty, so I was not even aware you could overload member functions like that.

    Cheers.
This discussion has been closed.