In my application, I ran through the BNO055 calibration procedure several times, then calculated the average of the 11 16 bit values of the calibration table. The calibration must be done in place, after the BNO055 has been installed in the robot (or whatever you are building).
Upon startup, I just write those values and it works pretty well. I use very simple I2C routines, and so far this has worked flawlessly.
main code:
//predetermined BNO055 calibration constants
int precal[]={-6,3,17,-2,395,112,0,1,0,1000,832}; //averages of 9 in situ calibration runs
I2C_Init();
// check for BNO055 presence
if (0xa0 != (result=I2C_ReadRegister(BNO055_A0,BNO055_WHO_AM_I))) { //check internal device ID
clear();
print(" No BNO");
while(1); //hang here
}
// reset BNO055, in case of soft reboot
I2C_WriteRegister(BNO055_A0, BNO055_SYS_TRIGGER, 0x20); //BNO055 system reset
delay(1000); //required reset delay
// store earlier derived calibration parameters
I2C_WriteCal(BNO055_A0, BNO055_CAL_DATA, (int *)precal);
I2C_WriteRegister(BNO055_A0, BNO055_SYS_TRIGGER, 0x80); //use external 32 kHz crystal.
// set to measurement mode
I2C_WriteRegister(BNO055_A0,BNO055_OPER_MODE,BNO055_OPER_MODE_NDOF);
delay(10); //minimum 7 ms delay
// end of setup. Now,
// get/set default initial heading using compass
Support routines:
// Read a two-byte word, low order first
signed int I2C_ReadWord(unsigned char busAddr, unsigned char deviceRegister) {
unsigned int data = 0;
unsigned char l;
I2C_Start(busAddr); // send device address
I2C_Write(deviceRegister); // set register pointer
I2C_Start(busAddr+READBIT); // restart as a read operation
l = I2C_ReadACK(); // read the register data
data = I2C_ReadNACK(); //read next unsigned char
I2C_Stop(); // stop
return (signed int) ((data<<8)|l);
}
// read 3 int16 values from successive BNO055 registers (using autoincrement)
void I2C_Read3Vectors(unsigned char busAddr, unsigned char deviceRegister, int* vector) {
unsigned int data = 0;
unsigned char l;
I2C_Start(busAddr); // send device address
I2C_Write(deviceRegister); // set register pointer
I2C_Start(busAddr+READBIT); // restart as a read operation
l = I2C_ReadACK(); // read the register data
data = I2C_ReadACK(); //read high byte
*vector++ = ((data<<8)|l); //store X
l = I2C_ReadACK();
data = I2C_ReadACK();
*vector++ = ((data<<8)|l); //store Y
l = I2C_ReadACK();
data = I2C_ReadNACK();
*vector = ((data<<8)|l); //store Z
I2C_Stop();
}
// read out 11 word calibration table
void I2C_ReadCal(unsigned char busAddr, unsigned char deviceRegister, int* vector) {
unsigned int data = 0;
unsigned char i,l;
I2C_Start(busAddr); // send device address
I2C_Write(deviceRegister); // set register pointer
I2C_Start(busAddr+READBIT); // restart as a read operation
for (i=0; i<10; i++) {
l = I2C_ReadACK(); // read low byte register data
data = I2C_ReadACK(); //read high byte
*vector++ = ((data<<8)|l); //store int
}
l = I2C_ReadACK(); // read the last 2 bytes
data = I2C_ReadNACK();
*vector = ((data<<8)|l);
I2C_Stop();
}
// write 11 word calibration table to BNO055
void I2C_WriteCal(unsigned char busAddr, unsigned char deviceRegister, int* vector) {
unsigned char i,l;
I2C_Start(busAddr); // send device address
I2C_Write(deviceRegister); // set register pointer
for (i=0; i<11; i++) {
l = (*vector)&0x00ff; // low byte register data
I2C_Write(l); //write it
l = (*vector)>>8;
I2C_Write(l);
vector++;
}
I2C_Stop();
}
// I2C register definitions for BNO055
// I2C Slave Addresses
#define BNO055_A0 (0x28<<1)
#define BNO055_A1 (0x29<<1)
#define BNO055_CHIP_ID 0xa0
// Register map
#define BNO055_WHO_AM_I 0x00
#define BNO055_SW_ID_L 0x04
#define BNO055_SW_ID_H 0x05
#define BNO055_PAGE_ID 0x07
#define BNO055_ACCEL_DATA 0x08
#define BNO055_MAG_DATA 0x0e
#define BNO055_GYRO_DATA 0x14
#define BNO055_FUSED_EULER 0x1a
#define BNO055_FUSED_QUAT 0x20
#define BNO055_TEMP 0x34
#define BNO055_CALIB_STAT 0x35
#define BNO055_ST_RESULT 0x36
#define BNO055_SYS_STATUS 0x39
#define BNO055_SYS_CLK_STATUS 0x38
#define BNO055_SYS_ERR 0x3a
#define BNO055_UNIT_SEL 0x3b
#define BNO055_OPER_MODE 0x3d
#define BNO055_PWR_MODE 0x3e
#define BNO055_SYS_TRIGGER 0x3f
#define BNO055_AXIS_MAP_CONFIG 0x41
#define BNO055_AXIS_MAP_SIGN 0x42
#define BNO055_CAL_DATA 0x55 //11 16 bit integers, offsets and scale
// Operation modes
#define BNO055_OPER_MODE_CONFIG 0x00
#define BNO055_OPER_MODE_FMC_OFF 0x0b
#define BNO055_OPER_MODE_NDOF 0x0c
// Power modes
#define BNO055_PWR_MODE_NORMAL 0x00