IMU BNO055

Hello,

I am working on a motorcycle data logger project and I would like add the acquisition of the BNO055 IMU data (angle orientation, angle rate and acceleration). I have several sensors with different sample rate:
-hall Effect sensor associates to an interrupt routine (high speed -> 1000Hz).
-IMU and steering encoder 100 Hz
-GPS 20 Hz

I am currently working on the IMU independently (keeping in mind that I have to include the code in the main data logger sketch) and I am having several problems. My sketch is based on one of the examples from the BNO055 library. I have just added the acquisition of the accelerometer and the gyroscope data.

The sketch is the following:

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

/* Set the delay between fresh samples */
const int periodIMU=1000;
unsigned long previousTimeIMU=0;
unsigned long currentTime=0;

#define BNO055_SAMPLERATE_DELAY_MS (periodIMU)

Adafruit_BNO055 bno = Adafruit_BNO055();

//------------------------------------------------------------------------------------------------//
void setup(void)
{
  Serial.begin(115200);
  Serial.println("BNO055 Data Test"); 
  Serial.println("");

  /* Initialise the sensor */
  if(!bno.begin())
  {
    Serial.print("No BNO055 detected ... Check your wiring or I2C ADDR!");  // There was a problem detecting the BNO055 ... check your connections
    while(1);
  }

  delay(1);
  
  int8_t temp = bno.getTemp();   // Display current temperature 
  Serial.print("Current Temperature: ");
  Serial.print(temp);
  Serial.println(" C");
  Serial.println("");

  bno.setExtCrystalUse(true);

  Serial.println("Calibration status values: 0=uncalibrated, 3=fully calibrated");

  // Display column headers 
  Serial.print("\t\t");
  Serial.print("Position");
  Serial.print("\t\t\t");
  Serial.print("Angular velocity");
  Serial.print("\t\t\t\t");
  Serial.print("Acceleration");
  Serial.print("\t\t\t\t");
  Serial.println("Calibration");

  // Display column sub-headers 
  Serial.print("Time ");
  Serial.print("\t\t");
  Serial.print("Roll; Pitch; Yaw");
  Serial.print("\t\t");
  Serial.print("Roll rate; Pitch rate; Yaw rate");
  Serial.print(" \t\t");
  Serial.print("Accel X, Accel Y, Accel Z");
  Serial.print("\t\t");
  Serial.println("Sys; Gyro; Accel; Mag");

}

The main problem is the calibration process. Considering a 1Hz sample rate I obtain the following results on the serial monitor:

BNO055 Data Test

Current Temperature: 24 C

Calibration status values: 0=uncalibrated, 3=fully calibrated
		Position			Angular velocity				Acceleration				Calibration
Time 		Roll; Pitch; Yaw		Roll rate; Pitch rate; Yaw rate 		Accel X, Accel Y, Accel Z		Sys; Gyro; Accel; Mag
1000		359.94; 0.69; -4.00		-0.00; -0.00; 0.00 				0.13; 0.69; 9.63			0; 0; 0; 0
2000		359.94; 0.69; -4.00		0.00; 0.00; -0.00 				0.12; 0.70; 9.63			2; 3; 0; 0
3000		359.94; 0.69; -4.00		-0.00; 0.00; -0.00 				0.12; 0.67; 9.66			2; 3; 0; 0
4000		359.94; 0.69; -4.00		0.00; 0.00; 0.00 				0.11; 0.68; 9.62			2; 3; 0; 0
5000		359.94; 0.69; -4.00		-0.00; 0.00; 0.00 				0.12; 0.71; 9.64			2; 3; 0; 0
6000		9.31; 22.75; -5.88		0.50; -2.23; -0.66 				6.31; -0.16; 9.09			0; 3; 0; 0
7000		30.06; 43.19; 13.75		-0.86; -1.96; 0.17 				6.88; -2.36; 6.68			0; 3; 0; 1
8000		10.19; 24.81; -19.19		-0.36; 0.60; -0.11 				6.25; 2.74; 8.89			0; 3; 0; 2
9000		7.44; 45.75; -40.31		0.12; -0.64; -0.69 				7.18; 4.03; 4.91			0; 3; 0; 2
10000		16.12; 38.50; -97.44		-0.25; 0.40; 0.18 				5.56; 6.91; -1.34			0; 3; 0; 2
11000		8.63; 33.94; -29.06		-0.94; 0.60; 0.37 				5.09; 4.32; 6.31			0; 3; 0; 2
12000		357.31; 42.25; -11.13		-0.36; -1.12; 0.61 				5.76; 3.82; 6.14			0; 3; 0; 2
13000		154.25; 51.81; -51.63		0.18; -0.07; -1.11 				7.69; 3.76; 3.37			0; 3; 0; 3
14000		183.38; 21.00; -58.19		-0.09; 0.79; -1.13 				3.12; 6.75; 4.28			1; 3; 0; 3
15000		167.50; 29.44; -1.50		-1.56; 0.36; 0.86 				3.66; -0.13; 7.70			0; 3; 0; 3
16000		168.88; 26.12; 53.88		-0.27; 0.04; -0.22 				3.98; -7.51; 4.68			0; 3; 0; 3
17000		191.81; 21.75; -10.63		1.57; 1.50; -0.35 				3.11; 1.58; 8.48			0; 3; 0; 3
18000		185.13; 73.37; -16.62		-0.44; -1.34; -0.50 				9.05; 1.69; 2.22			0; 3; 0; 3
19000		191.75; 51.25; -26.12		1.30; 2.69; -0.60 				8.37; 1.12; 6.52			0; 3; 0; 3
20000		203.81; 4.75; -20.81		-0.26; -0.20; 0.15 				1.91; 6.57; 12.18			0; 3; 0; 3

It is almost impossible to get simultaneously calibration of the 3 sensors (accelerometer, gyroscope and magnetometer) and of the system. I don’t understand why?
Taking into account the fact that the IMU will be installed under the seat on motorcycle, I think it is important to calibrate it before the driving scenario but I don’t know if it is necessary to calibrate each time the main loop is repeated?

The second problem is the refresh time. Consider that after having set the BNO055_SAMPLERATE_DELAY_MS () to 100 Hz the data are exactly available every 10 ms. Keeping only the view of the currenTime data to avoid long repeated serial.print() function. It takes around 1 seconds to reach the sample rate without delay. I would appreciate help to solve the problem.

Current Temperature: 23 C

Calibration status values: 0=uncalibrated, 3=fully calibrated
		Position			Angular velocity				Acceleration				Calibration
Time 		Roll; Pitch; Yaw		Roll rate; Pitch rate; Yaw rate 		Accel X, Accel Y, Accel Z		Sys; Gyro; Accel; Mag
596		
600		
604		
607		
611		
614		
618		
621		
625		
629		
632		
636		
640		
644		
647		
651		
654		
658		
661		
665		
669		
672		
676		
679		
684		
687		
691		
694		
698		
701		
705		
709		
712		
716		
719		
723		
727		
731		
734		
738		
741		
745		
749		
752		
756		
759		
763		
766		
771		
774		
778		
781		
785		
789		
792		
796		
799		
803		
806		
811		
814		
818		
821		
825		
829		
832		
836		
839		
844		
847		
851		
856		
860		
867		
872		
878		
883		
889		
897		
903		
910		
915		
921		
926		
930		
936		
942		
947		
952		
958		
962		
966		
971		
977		
982		
988		
992		
998		
1002		
1009		
1013		
1020		
1030		
1040		
1050		
1060		
1070		
1080		
1090		
1100		
1110		
1120		
1130		
1140		
1150		
1160		
1170		
1180		
1190		
1200		
1210		
1220		
1230		 …

I hope find someone experienced with this IMU.

Any advice of the global syntax of my sketch is welcomed.

Thank you,
Pm

I can't help with the calibration, but regarding the delay, you should probably call Serial.flush() at the end of setup to make sure the printing interrupts don't interfere with the timing.

You should probably use the F macro for printing double-quoted strings:

    Serial.print( F("Time ") );

On the 8-bit AVRs, the memory architecture requires the compiler to load string constants into RAM. This can eat up the available RAM pretty quickly. You can force the strings to be stored in (and used from) the FLASH memory by using the F macro. An overloaded print function knows how to print from FLASH instead of RAM. Most libraries overload both the RAM (i.e., char *) and FLASH (const __FlashStringHelper *) methods.

Also, C/C++ concatenates adjacent double-quoted strings for you, so you can use :

   Serial.println( F(
    "Time "
    "\t\t"
    "Roll; Pitch; Yaw"
    "\t\t"
    "Roll rate; Pitch rate; Yaw rate"
    " \t\t"
    "Accel X, Accel Y, Accel Z"
    "\t\t"
    "Sys; Gyro; Accel; Mag") );

That's just one call, and no RAM is used for the constants.

Cheers,
/dev

I have had no problem calibrating the BNO055 by following the directions in the data sheet (start calibration, slowly move the sensor through all possible orientations, etc.).

I did this several different times, then averaged the 11 (integer) results and at startup of the actual application, override the automatic calibration and store those results. (I don't use the Adafruit library; I wrote my own routines).

Bosch does not clearly document what their automatic calibration does, and I've noticed that during a run, the calibration status sometimes drops to less than 3 for some sensors. However, this doesn't seem to affect the navigational accuracy.

Unfortunately the sensors (especially the magnetometer) must be calibrated in place for accurate results. This will be almost impossible when it is mounted on a motorcycle.

Hello,

Thank you for your answers.

@ dev/
I have followed your advices above with what you said me in the speedometer post and it works. I have also changed native serial communication library for the NeoHWserial.
I obtain:

BNO055 Data Test

Current Temperature: 24 C

Calibration status values: 0=uncalibrated, 3=fully calibrated
		Position 			Angular velocity				Acceleration				Calibration
Time 		Roll; Pitch; Yaw		Roll rate; Pitch rate; Yaw rate 		Accel X, Accel Y, Accel Z		Sys; Gyro; Accel; Mag
10000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
20000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
30000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
40000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
50000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
60004		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
70008		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
80004		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
90004		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
100000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
110000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
120000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
130000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
140000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
150000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
160004		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
170000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
180000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
190000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
200000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
210000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
220000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
230004		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
240000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
250000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
260004		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0
270000		0.00; 0.00; 0.00		0.00; 0.00; 0.00 				0.00; 0.00; 0.00			0; 0; 0; 0

@ jremington
So if I understand the best way to proceed in my case is to realize a removable data logger to be able to move it with hands during initialization time. Once initialization is done and the 11 integers are saved, the system will be reinstalled in the motorcycle.
Is it a good way to do?
Is there somewhere I could find your routine?

Regarding the datasheetI see the NDOF or NDOF_ FMC_ OFF data fusion settings which allows to compute orientation from the accelerometer, the gyroscope and the magnetometer data. Does it so important to fully calibrate the magnetometer?

Thank you very much,
Pm

IMU_v5.ino (3.97 KB)

Once initialization is done and the 11 integers are saved, the system will be reinstalled in the motorcycle.
Is it a good way to do?

No.

The magnetic fields and iron in the motorcycle will make the magnetometer readings completely useless. That is why I said it will be almost impossible to calibrate the sensor if mounted on a motorcycle.

Hello,

I am a little bit lost...
I need to acquire the 3 accelerations; the yaw, roll and pitch rate; the roll and the pitch angle. I don't need the heading value. Is there an algorithm to compute orientation only with gyro and accelero?
Or if you have any suggestion for another hardware solution? I have also a Genuino 101 with native accelero and gyro sensors.

Thank you,
Pm

You are fine if you don't need the yaw. It takes some trigonometry to get the roll and pitch angles, described here.

This won't work if you are accelerating, so you do need a complementary or Kalman filter to add the gyro information.

I don't know if the BNO055 orientation algorithm will work properly if the magnetometer is not contributing, but you can always use the raw gyro and accelerometer data.

The best solution would be to use the BNO055 as it was intended, but keep it away from the iron and wiring in the motorcycle -- on a pole, perhaps.

Hello,

Reeding the datasheet of the BNO055 I have seen that it exists the "IMU" data fusion mode which allows to compute orientation with accelero and gyro sensor. I think it will be better for my application because I have to install the IMU near the gravity center, it means under the motorcycle seat not so far from the engine and other iron parts...

I have two IMUs:

The two sensors work with the BNO055 chip but after some researches I have found two different libraries which work for both.
-GitHub - adafruit/Adafruit_BNO055: Unified sensor driver for the Adafruit BNO055 orientation sensor breakout
-brackets-arduino/libraries/NAxesMotion at master · bcmi-labs/brackets-arduino · GitHub

Have you any idea about which library is the best one?

Thank you,
Pm

Hello,

I wish you a Merry Christmas.

I have spent time to read forums, articles, datasheets about IMU, filters, … hoping to find the best solution for my project. But now I am a little bit lost….

Currently I have 2 IMUs:

To summarize my use, it is to acquire on a SD card orientation (I don’t need an accurate heading unlike roll and pitch angle), angular velocity and acceleration on a motorcycle during riding scenarios. The IMU will stay fix under the seat as near as possible of the gravity center.

First I don’t know which of the above IMU is the best.
They have the same chip; they work with the same libraries (Adafruit_BNO055, Nine axis motion) but I have noticed some differences. For example, the 9 axis shield can not go over 90 deg of roll whereas with the same sketch the Adafruit board is able to move between -180 and 180 deg. It is not important in my case because with a 90 deg roll angle I think the rider will have some problem… But maybe there is other important difference that I didn’t remark.

Then considering the IMU fixed how can I properly calibrate the gyro and the accelero?

I have read that quaternions are more accurate to compute absolute orientations. Do you think I should use them? Then post-compute the orientation (I don’t need to know the Euler angles in real time)

There is few information about Bosch data fusion (algorithm, filter, …). So I don’t know if I can trust to the Bosh fusion algorithm or if I have to use raw data and use external filter with Madgwick for example?

In the case where I will use the Bosch one, which fusion modes will be the more appropriate?
I have read in the BNO055 datasheet different possibilities:

Configuration Mode 
*																(Transient Mode)
*				OPERATION_MODE_ACCONLY		0x01			Accelerometer only
*				OPERATION_MODE_MAGONLY		0x02			Magnetometer only
*				OPERATION_MODE_GYRONLY		0x03			Gyroscope only
*				OPERATION_MODE_ACCMAG		0x04			Accelerometer and Magnetometer only
*				OPERATION_MODE_ACCGYRO		0x05			Accelerometer and Gyroscope only
*				OPERATION_MODE_MAGGYRO		0x06			Magnetometer and Gyroscope only
*				OPERATION_MODE_AMG			0x07			Accelerometer, Magnetometer and 
*																Gyroscope (without fusion)
*				OPERATION_MODE_IMUPLUS		0x08			Inertial Measurement Unit 
*																(Accelerometer and Gyroscope 
*																	Sensor Fusion Mode)
*				OPERATION_MODE_COMPASS		0x09			Tilt Compensated Compass 
*																(Accelerometer and Magnetometer 
*																	Sensor Fusion Mode)
*				OPERATION_MODE_M4G			0x0A			Magnetometer and Gyroscope Sensor 
*																Fusion Mode
*				OPERATION_MODE_NDOF_FMC_OFF	0x0B			9 Degrees of Freedom Sensor Fusion 
*																with Fast Magnetometer Calibration Off
*				OPERATION_MODE_NDOF			0x0C			9 Degrees of Freedom Sensor Fusion

Considering that magneto will never be correctly calibrated I think it is better to use OPERATION_MODE_IMUPLUS which compute the data only with gyro and accelero?

Is there some people experienced with the BNO055 who can give their feedbacks?

I would appreciate some help.

Thank you in advance,
Pm

Accelerometer calibration overview: Tutorial: How to calibrate a compass (and accelerometer) with Arduino | Underwater Arduino Data Loggers

The BNO055 uses a quaternion to represent the body orientation, as do essentially all state of the art navigational filters.

You won't be able to do much better than to use the Kalman filter built into the BNO055, but if you want to learn something about how this is done, consult the open source, Arduino-compatible RTIMUlib. This is very involved, high level mathematics.

You can certainly experiment with the different modes of BNO055 operation and decide which works best for you.

The two boards you have use the same BNO055 sensor, so I doubt that there is significant difference between their respective operation, regardless of differences in the documentation.

hello all

i need to extract data from BNO055 breakout board using i2c protocol and for real time interfacing we r suppose to use LABVIEW (FPGA). can anyone help me with this as i don't have any idea how to start my work.

plz. help me or suggest me where from should i start

Hi,

Maybe I can help you with what I have done for my project. What is the global idea of yours?

Have a good day,
Pm

Hello,
my project is basically Non-contact vibration measurement using laser source and 2D PSD.
here we r also using BNO055 to compensate any self vibration generated due to ambient noise.

i have no idea of BNO055, and to extract data (Quaternion form ) from it.

any help will be appreciated

thank u

BNO055 data sheet

Hi,

You have 2 possible libraries for the BNO055:
-BNO055_adafruit
-NaxisMotion

In both libraries you have several examples explaining how to acquire IMU data. You just have to chose which data you want: Euler, Gyro, Accel, Quat...

Have a good day,
Pm