Reading the BNO055 9 DOF Absolute Orienation IMU Fusion Breakout board

Buzby

Senior Member
If you place the module flat on a table and rotate it a bit clockwise every few seconds until you have gone a full 360 degrees, the following code should give you an idea of what the heading readings mean ...
Hi Lance,

Your code should do that, but it assumes the BNO orientation is 'normal' to start with.

We don't know what the orientation of the chip is relative to the board, or the orientation of the board relative to the 'real world'.

I just wish I had one on my desk, it would be running it ten minutes !.

Cheers,

Buzby
 

Gramps

Senior Member
you deleted the write $0C to register $3D
After we begin seeing good numbers I cleaned up all my experiments in the editor and accidentally erased it.
A long day ahead of us. hopefully we can work on this again this weekend.
Thank you gentlemen for your awesome help with this project!
 

Gramps

Senior Member
you deleted the write $0C to register $3D.
Restored line and sensor is sending;
When rotating the sensor 360 * clockwise the B10 values go from 0 to 22.
When B11 is tipped forward and backwards, the values run from 0 to 255.

Next
Loaded Buzby's code:
Sensor not responding

23985
 

inglewoodpete

Senior Member
After we begin seeing good numbers I cleaned up all my experiments in the editor and accidentally erased it.
A long day ahead of us. hopefully we can work on this again this weekend.
Thank you gentlemen for your awesome help with this project!
A suggestion on version control.
  • When working on any project but especially a big or involved one, start with a filename (like) MyProject-v1.bas.
  • After you reach a milestone, like getting a new feature to work, first save the file and then do a "Save As" to a new file name (like) MyProject-v2.bas
  • Do your new development on the new file.
That way, if something gets inadvertently deleted, you can always refer back to the previous version/s.
 

Buzby

Senior Member
="Gramps, post: 333320, member: 73607"]
When rotating the sensor 360 * clockwise the B10 values go from 0 to 22.
When B11 is tipped forward and backwards, the values run from 0 to 255.
Looking at individual bytes is not going to tell you anything useful, you need to look at words.

Loaded Buzby's code:
Sensor not responding
What does 'sensor not responding' mean ?.

Does it mean no comms, or does it mean no values ?

What does the terminal display show ?

Please send a picture of the terminal output, not a picture of the code. My code will tell via the terminal if comms has failed.
 
Last edited:

Buzby

Senior Member
I think the necessary initialization code is included, however here is the screen shot:
The 'necessary initialization code' are the lines with 'hi2csetup' and 'i2cout' instructions.

Both these lines need to be before the 'pause 1000'.
 

lbenson

Senior Member
When rotating the sensor 360 * clockwise the B10 values go from 0 to 22.
When B11 is tipped forward and backwards, the values run from 0 to 255.
Not wishing to belabor the point already made repeatedly, but heading (yaw), pitch, and roll are WORD values (word values may range from 0 to 65535 but your reading will not go the full range for this device), not BYTE values which may range from 0 to 255.

Buzby says (following the documentation) that these values (at $1A, $1C, $1E) represent "Euler Angles", of which I, in my math-deficient experience, had never heard. You might look them up in Wikipedia.

To me, the best way to gain an understanding would be to first see how the heading readings map to something we're all familiar with--compass readings. If you use the code I provided (with your initialization code), and place the module on a table surface, can you determine what its reading is for North, South, East, West? What range of WORD values do you see (SERTXD(#w5," ")) as you rotate 360 degrees?

If as you rotate the readings make no sense (that is, they go up and down through 360 degrees instead of gradually going either only up or down through the whole rotation), it means that the order of the bytes in the HI2CIN statement is wrong, and you need to try HI2CIN $1A,(b11,b10) instead of HI2CIN $1A,(b10,b11). If your finding of b10 values between 0 and 22 is correct, then that is the high-order byte, and your actual WORD readings are going to be between 0 and (22*256)+255, or 0 to 5887. (BUT, according the the data sheet, "Heading / Yaw: 0° to 360° (turning clockwise increases values)", so the Euler Angles, unless fractional, should go from 0 to 359.)

But it's possible that my understanding is completely wrong. In order to check anything, it's necessary to see what the actual 2-byte heading readings are as you rotate the module on a flat surface through 360 degrees. Post the SERTXD output and your code (not a screen shot and within [ code] and [ /code] tags).

Also from the datasheet:
Roll: -90° to +90° (increasing with increasing inclination)
Pitch: +180° to -180° (turning clockwise decreases values)
 
Last edited:

Buzby

Senior Member
Hi Lance,

I too was unaware of exactly what Euler angles were until I read up on them, and then it became simple !. They are the three angles that correspond to Roll, Pitch, and Yaw. Each goes 0' to 360' as the device is rotated around each axis.

However, there is a problem with using Euler angles in the full 3D sphere. For example, if an airplane is flying at a constant height, but is pointing vertically up or down, ( pitch +/- 90' ) then the Yaw value ( used as the heading of the airplane ) makes no sense because the airplane is still travelling 'forward'. Apparently, the solution is to use the Quaternions, but I'm still trying to get my head round them !.

For this particular task, especially at this early ( if somewhat drawn out ) stage of development, Euler angles are easier to work with.

Cheers,

Buzby
 

Gramps

Senior Member
That way, if something gets inadvertently deleted, you can always refer back to the previous version/s
Yes that's a good idea thank you!

Looking at individual bytes is not going to tell you anything useful, you need to look at words.
I realize individual bites are not enough and we must have words, but seeing those little numbers moving when I tip this sensor was a big step forward to me!

Please send a picture of the terminal output,
Ok. Working on it
 

Gramps

Senior Member
the lines with 'hi2csetup' and 'i2cout' instructions.
Both these lines need to be before the 'pause 1000'.
Got it. Now changed.

Edit: Terminal output is just 1

Code:
;lbenson's code to read BNO055 sensor

Code:

#Picaxe 28X2
#NO_table
#no_data

    HI2cSetup i2cmaster, $50, i2cslow, i2cbyte; set PICAXE as master and BNO055 slave address
   
main:    hi2cin 0,(b0,b1,b2,b3,b4,b5,b6)    ; read data and debug display   
     hi2cOut $3D, ($0C)
    Pause 1000   
    debug b1
   
do
  hi2cin $1A,(b10,b11)
  if w5 <> w6 then ' if there's a change
    w6=w5
    sertxd(#w5," ")
  endif
loop
/code/
 
Last edited:

Gramps

Senior Member
HI2CIN $1A,(b11,b10) instead of HI2CIN $1A,(b10,b11). If your finding of b10 values between 0 and 22 is correct, then that is the high-order byte, and your actual WORD readings are going to be between 0 and (22*256)+255, or 0 to 5887.
I think this is a typo.
Did you mean to change $1A to $1B?
 

Gramps

Senior Member
Anyway, we changed the address to$1B.
With debug the values in w5,w6,w7 change as we move the sensor.
In SERTXD this is the the result.
23991
 

lbenson

Senior Member
I think this is a typo. Did you mean to change $1A to $1B?
No. According to the data sheet, $1A is the least significant byte (LSB), and $1B is the most significant byte (MSB).

Looks like you are not properly reading the chip. Try putting Buzby's code before the do: loop to check for proper chip ID:
Code:
   ' Read chip ID     
   hi2cin 0,(b0)  
  
   ' Quit if chip ID wrong
   if b0 <> $A0 then : sertxd( "Bad comms !",cr,lf): reset : endif
 

lbenson

Senior Member
Need to see code. Something looks wrong -- b11 should not be 183 if we are looking at degrees * 16.

Use sertxd(#w5," ",#w6," ",#w7,cr,lf) instead of debug so we can see decimal values instead of binary.
 

lbenson

Senior Member
Is your serial terminal baud rate right? Is it more rational with 9600 (sorry, I don't have an X2 handy to test with).

Try putting this before hi2csetup to make sure and for documentation purposes:

pause 2000
sertxd (ppp_filename," ", ppp_datetime,cr,lf)
 

lbenson

Senior Member
Please see post #52
But you said you changed to $1B and added DEBUG. It's helpful to see the exact code with every iteration.

It looks to me as if the Euler angles are 13-bit numbers with 4 bits of resolution to the right of an implied decimal point, so readings should be like 359.1250. I think this will give that if the module is being read properly.

Code:
#Picaxe 28X2
#NO_table
#no_data

pause 2000
sertxd (ppp_filename," ", ppp_datetime,cr,lf)
HI2cSetup i2cmaster, $50, i2cslow, i2cbyte; set PICAXE as master and BNO055 slave address
   
main:
  hi2cin 0,(b0,b1,b2,b3,b4,b5,b6)    ; read data and debug display   
  hi2cOut $3D, ($0C)
  Pause 1000   
 '   debug b1
  ' Read chip ID     
  hi2cin 0,(b0)  
  
  ' Quit if chip ID wrong
  if b0 <> $A0 then : sertxd( "Bad comms !",cr,lf): reset : endif 

do
  hi2cin $1A,(b10,b11)
  if w5 <> w6 then ' if there's a change
    w6=w5
'    sertxd(#w5," ")
    w3=w5/16
    w4=w5//16*625
    if w4=625 then
      sertxd(#w3,".0",#w4," ")
    else
      sertxd(#w3,".",#w4," ")
    endif
  endif
loop
 

Gramps

Senior Member
HI2CIN $1A,(b11,b10) instead of HI2CIN $1A,(b10,b11).
I cannot discern a difference between these two values.
 

Buzby

Senior Member
Hi Gramps,

Now we're getting something we can nearly use !.

The terminal is almost showing what I expected, but I think your baud rate is wrong. Try setting to 9600.

Cheers,

Buzby
 

Buzby

Senior Member
Great !

Now rotate the BNO around each axis, and see how the numbers relate to the angles.

Just play about with it to get a feel for the behaviour.

Don't change code yet.
 

lbenson

Senior Member
I cannot see the difference between Buzby's code and mine with respect to reading the heading from $1A, but try replacing his print line:

sertxd("Y=",#BNO_YAW,9,9,"P=",#BNO_PITCH,9,9,"R=",#BNO_ROLL,cr,lf)

with this:
Code:
    w3=w5/16
    w4=w5//16*625
    if w4=625 then
'      sertxd(#w3,".0",#w4," ")
       sertxd("Y=",#w3,".0",#w4," ",9,9,"P=",#BNO_PITCH,9,9,"R=",#BNO_ROLL,cr,lf)
    else
'      sertxd(#w3,".",#w4," ")
       sertxd("Y=",#w3,".",#w4," ",9,9,"P=",#BNO_PITCH,9,9,"R=",#BNO_ROLL,cr,lf)
    endif
 

Gramps

Senior Member
sertxd("Y=",#BNO_YAW,9,9,"P=",#BNO_PITCH,9,9,"R=",#BNO_ROLL,cr,lf)
Sorry i'm not seeing this line.
Perhaps i'm using the wrong code???

Code:
#Picaxe 28X2
#NO_table
#no_data

pause 2000
sertxd (ppp_filename," ", ppp_datetime,cr,lf)
HI2cSetup i2cmaster, $50, i2cslow, i2cbyte; set PICAXE as master and BNO055 slave address

main:
hi2cin 0,(b0,b1,b2,b3,b4,b5,b6) ; read data and debug display
hi2cOut $3D, ($0C)
Pause 1000
' debug b1
' Read chip ID
hi2cin 0,(b0)

' Quit if chip ID wrong
if b0 <> $A0 then : sertxd( "Bad comms !",cr,lf): reset : endif

do
hi2cin $1A,(b10,b11)
if w5 <> w6 then ' if there's a change
w6=w5
' sertxd(#w5," ")
w3=w5/16
w4=w5//16*625
if w4=625 then
sertxd(#w3,".0",#w4," ")
else
sertxd(#w3,".",#w4," ")
endif
endif
loop
 

Buzby

Senior Member
Gramps,

Save the code below as Buzby_v2 or similar, so you don't overwrite the first code I posted.

Then run it and see the changes. Once we have the values changing as expected we can move onto scalling.

We need to be sure that the BNO is orientated in such a way that the Roll,Pitch, and Yaw match what the code is expecting before we move on.

Code:
#picaxe 28X2
#no_table
#no_data

 symbol BNO_YAW   = w5
 symbol BNO_PITCH = w6
 symbol BNO_ROLL  = w7
 
 symbol P_sgn     = b8
 symbol R_sgn    = b9

 sertxd(cr,lf,ppp_filename," Starting ...",cr,lf)
 pause 1000
   
 ' Setup I2C  
 hi2cSetup i2cmaster, $50, i2cslow, i2cbyte
 
 ' Set BNO active
 hi2cOut $3D, ($0C)

do    
   ' Read chip ID      
   hi2cin 0,(b0)   
   
   ' Quit if chip ID wrong
   if b0 <> $A0 then : sertxd( "Bad comms !",cr,lf): reset : endif
   
   ' Read Euler angles
   hi2cin $1A,(b10,b11)  ' Yaw,        0 to +360
   hi2cin $1C,(b12,b13)  ' Pitch,   -180 to +180
   hi2cin $1E,(b14,b15)  ' Roll,     -90 to +90
   
   ' Convert pitch to +/- value
   if BNO_PITCH > $8000 then
      P_sgn = "-"
    BNO_PITCH = 0 - BNO_PITCH
   else
    P_sgn = "+"
   endif    

   ' Convert roll to +/- value
   if BNO_ROLL > $8000 then
      R_sgn = "-"
    BNO_ROLL = 0 - BNO_ROLL
   else
    R_sgn = "+"
   endif    

   ' Show results
   sertxd("Y=",#BNO_YAW,9,9,"P=",P_sgn,#BNO_PITCH,9,9,"R=",R_sgn,#BNO_ROLL,cr,lf)
   
   pause 200
   
loop
 

Buzby

Senior Member
Great !.

So now if you rotate the BNO flat on the table, Yaw should change.

If you tilt it forward/backward, Pitch should change.

If you tilt it left/right, Roll should change.

Is this what you see ?
 

Gramps

Senior Member
That line is in Buzby's code and the replacement is intended to convert the heading reading to degrees 0-359 with 4 decimal places.
Copied Buzby's code to a new page and replaced your code for
sertxd("Y=",#BNO_YAW,9,9,"P=",#BNO_PITCH,9,9,"R=",#BNO_ROLL,cr,lf)
Results:

23994
 

lbenson

Senior Member
Good results. You may need to increase the PAUSE time in the loop so that you have time to see the rotation, roll, and pitch movements reflected in the readings.
 

Gramps

Senior Member
So now if you rotate the BNO flat on the table, Yaw should change.

If you tilt it forward/backward, Pitch should change.

If you tilt it left/right, Roll should change.

Is this what you see ?
Y is correct but P and R are switched
 
Top