QuaternionYawPitchRoll issue for BNO08X Sensor

Hey!

So I recently got a new sensor, the BNO08X Sensor, and did I2C connections on this sensor to run a QuaternionYawPitchRoll example provided by Adafruit. However, even after doing the connections on a breadboard listed by Adafruit (Overview | Adafruit 9-DOF Orientation IMU Fusion Breakout - BNO085 | Adafruit Learning System) along with pulling up the correct program, I am not able to retrieve data as it says "I2C address not found" along with "Failed to find BNO08X chip". I thought something would be wrong with my sensor, so I purchased another one and it also said "I2C address not found" and "Failed to find BNO08X chip". Clearly, I know I am doing something wrong, but I am not able to figure it out. Can someone help me, please?

Here are some details:

  1. I am using an Arduino Due Board
  2. I've used the connections listed in this documentation: Overview | Adafruit 9-DOF Orientation IMU Fusion Breakout - BNO085 | Adafruit Learning System
  3. I am using Adafruit_BNO08x Library

Here is the code provided by this library that I am using:

#include <Arduino.h>
// This demo explores two reports (SH2_ARVR_STABILIZED_RV and SH2_GYRO_INTEGRATED_RV) both can be used to give 
// quartenion and euler (yaw, pitch roll) angles.  Toggle the FAST_MODE define to see other report.  
// Note sensorValue.status gives calibration accuracy (which improves over time)
#include <Adafruit_BNO08x.h>

// For SPI mode, we need a CS pin
// #define BNO08X_CS 10
// #define BNO08X_INT 9


// #define FAST_MODE

// For SPI mode, we also need a RESET 
//#define BNO08X_RESET 5
// but not for I2C or UART
#define BNO08X_RESET -1

struct euler_t {
  float yaw;
  float pitch;
  float roll;
} ypr;

Adafruit_BNO08x  bno08x(BNO08X_RESET);
sh2_SensorValue_t sensorValue;

#ifdef FAST_MODE
  // Top frequency is reported to be 1000Hz (but freq is somewhat variable)
  sh2_SensorId_t reportType = SH2_GYRO_INTEGRATED_RV;
  long reportIntervalUs = 2000;
#else
  // Top frequency is about 250Hz but this report is more accurate
  sh2_SensorId_t reportType = SH2_ARVR_STABILIZED_RV;
  long reportIntervalUs = 5000;
#endif
void setReports(sh2_SensorId_t reportType, long report_interval) {
  Serial.println("Setting desired reports");
  if (! bno08x.enableReport(reportType, report_interval)) {
    Serial.println("Could not enable stabilized remote vector");
  }
}

void setup(void) {

  Serial.begin(115200);
  while (!Serial) delay(10);     // will pause Zero, Leonardo, etc until serial console opens

  Serial.println("Adafruit BNO08x test!");

  // Try to initialize!
  if (!bno08x.begin_I2C()) {
  //if (!bno08x.begin_UART(&Serial1)) {  // Requires a device with > 300 byte UART buffer!
  //if (!bno08x.begin_SPI(BNO08X_CS, BNO08X_INT)) {
    Serial.println("Failed to find BNO08x chip");
    while (1) { delay(10); }
  }
  Serial.println("BNO08x Found!");


  setReports(reportType, reportIntervalUs);

  Serial.println("Reading events");
  delay(100);
}

void quaternionToEuler(float qr, float qi, float qj, float qk, euler_t* ypr, bool degrees = false) {

    float sqr = sq(qr);
    float sqi = sq(qi);
    float sqj = sq(qj);
    float sqk = sq(qk);

    ypr->yaw = atan2(2.0 * (qi * qj + qk * qr), (sqi - sqj - sqk + sqr));
    ypr->pitch = asin(-2.0 * (qi * qk - qj * qr) / (sqi + sqj + sqk + sqr));
    ypr->roll = atan2(2.0 * (qj * qk + qi * qr), (-sqi - sqj + sqk + sqr));

    if (degrees) {
      ypr->yaw *= RAD_TO_DEG;
      ypr->pitch *= RAD_TO_DEG;
      ypr->roll *= RAD_TO_DEG;
    }
}

void quaternionToEulerRV(sh2_RotationVectorWAcc_t* rotational_vector, euler_t* ypr, bool degrees = false) {
    quaternionToEuler(rotational_vector->real, rotational_vector->i, rotational_vector->j, rotational_vector->k, ypr, degrees);
}

void quaternionToEulerGI(sh2_GyroIntegratedRV_t* rotational_vector, euler_t* ypr, bool degrees = false) {
    quaternionToEuler(rotational_vector->real, rotational_vector->i, rotational_vector->j, rotational_vector->k, ypr, degrees);
}

void loop() {

  if (bno08x.wasReset()) {
    Serial.print("sensor was reset ");
    setReports(reportType, reportIntervalUs);
  }
  
  if (bno08x.getSensorEvent(&sensorValue)) {
    // in this demo only one report type will be received depending on FAST_MODE define (above)
    switch (sensorValue.sensorId) {
      case SH2_ARVR_STABILIZED_RV:
        quaternionToEulerRV(&sensorValue.un.arvrStabilizedRV, &ypr, true);
      case SH2_GYRO_INTEGRATED_RV:
        // faster (more noise?)
        quaternionToEulerGI(&sensorValue.un.gyroIntegratedRV, &ypr, true);
        break;
    }
    static long last = 0;
    long now = micros();
    Serial.print(now - last);             Serial.print("\t");
    last = now;
    Serial.print(sensorValue.status);     Serial.print("\t");  // This is accuracy in the range of 0 to 3
    Serial.print(ypr.yaw);                Serial.print("\t");
    Serial.print(ypr.pitch);              Serial.print("\t");
    Serial.println(ypr.roll);
  }

}

The default I2C address for the BNO08x is 0x4A which is what the library uses as default.

The address can be switched to 0x4B by pulling the DI pin high to VCC ➜ may be your module is using 0x4B?

Have you tried running an I2C scan?

Hm interesting No I haven't ran an I2C scan. How do you do an I2C scan?

there are codes online like @robtillaart multispeed I2C Scanner

I have a question, so what will the I2C scan return as a result?

Update: I scanned and found that my address is 0x4B. However, my sensor does not have a DI pin. This is because I didn't buy the sensor from Adafruit, and it's a purple-colored sensor I am using. Is there a way to still switch the address? Let me upload a picture to show how the sensor looks:

@J-M-L Ignore my last message, I think I figured it out. I edited the header file of the library. Let me test to see if it retrieves data now.

Great - that was likely your issue.

The pin might be just hardwired on your module. Changing the library is one way to do it but if one day you download an update of the library or install a new PC then your code will go back to the default.

Double check the library example and .h file, the function call you have in the setup()

does accept as a parameter the I2C address

That’s where you should pass your address as the first parameter (don’t pass anything else, there are also default values there that are OK).

Thanks @J-M-L. I might need your help on another issue I just encountered. Now my I2C is displaying data, but I want to try using SPI for faster data. So I made the connections as listed in this link (except with DI being connected as MOSI): Overview | Adafruit 9-DOF Orientation IMU Fusion Breakout - BNO085 | Adafruit Learning System, but I am encountering the same issue as I2C where it says "Failed to find BNO08X". Do you have an idea of how this can be the issue?

Here are my connections by the way (Left shows Sensor/Breadboard Connection, Right shows Arduino Connection):
VCC -> VCC (as shown in the image below)
GND -> GND (as shown in the image below)
SCL -> SCK (as shown in the image below)
SDA -> MISO (as shown in the image below)
AD0 (Or DI in Adafruit's Case) -> MOSI (as shown in the image below)
CS -> D10
INT -> D9
RST -> D5
PS0 -> High Setting (refer to link above)
PS1 -> High Setting (refer to link above)
Note: The High settings are set by how I wire it to the breadboard
image

The same issue occurs with UART as well. If someone can assist me with UART or SPI, that would be great!

does your module have level shifting circuitry to adjust to 5V?

for example for UART more, Adafruit uses 3.3V for Vin

I don't know if I can adjust to 5V. But I think 3.3V

But you connect to 5V

My apologies, I am getting confused here.
UPDATE: Apologies for the confusion, the sensor is 2.4-3.6V, so its 3.3V only. But I am very lost with the connections because I can't find the datasheet for the sensor.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.