0

BNO055 Woes
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

BNO055 Woes

by srogers316 on Tue Mar 07, 2017 4:07 pm

I had a BNO055 breakout board working perfectly under I2c, but my design for use originally consisted of a 25 foot coiled phone cable to carry the I2C signals from the controller to the location that was being monitored by the DNO055 (actually a violin). The hard lesson learned was that the I2c signals do not traverse distance well. I went about modifying the circuit by setting up my BNO055 to work on serial. This also failed miserably because the BNO555 stopped responding to commands. I later discovered that the reason the serial failed was because the level shifting transistor (Q2) on the BNO055 breakout board had become partially disconected from the board and had broken into two pieces, with one piece completely missing. I do not know how this happened. It could have been a poor solder connection on the level shifter chip, or it could have been that the transistor was cracked or knocked off the board when the board itself was being fastened with 2-56 hardware screws. This hardware size is the smallest size commonly available to me, but it does appear that the nut that fits a 2-56 screw might not clear the level shifting transistor for the SCL signal.

At first, I felt that the board was a goner because I cannot solder that small, and even if I could, I didn't have the correct part.

Coincident with these developments, it was decided to change the design such that a local small controller would run the BNO055 and transmit the information in a wireless fashion to a remote monitor using the nRF24L01 wireless units. A Feather M0 Basic Proto was selected to be the local controller, with an attached LIPO battery, a BNO0055 board, and an nRF24L01 board. In the build of these units I discovered the missing level shifting transistor on the BNO055 board. Since the Feather M0 Basic Proto is a 3.3V device, I felt that I could do without the level shifting transistor if I shorted from Source to Drain using the pads on the BHO055 for the SCL Q2 level shifter. Also, because the Feather M0 Basic Proto is a 3.3 V unit, I opted to power the BNO055 from the 3Vo pin rather than the Vin pin. The information I have in powering the BNO055 in a 3.3V environment does not indicate whether to use the Vin or the 3Vo pins as the power source for the BNO055 board. however, I deduced that I should use the 3Vo pin for powering the BNO055 board in a 3.3V environment.

So I made the shorting repair I made, which I have documented in the attached PDF schematic. The schematic shows the original circuit, as I had expected to use it, and the repaired circuit, as I am attempting to use it. I attempted to operate the board with the shorting repair and the new power requirements, i.e., no 5V at Vin. For the most part, this worked. I got past the check for the BNO055 part (which requires I2C commands), and I was able to make several readings of the BNO055 board when it was sitting in one orientation. The values seemed appropriate for that orientation. As soon as I moved the BNO055 orientation from its startup position, the program locked up. I debugged this problem further to attempt to determine where the program stopped, and I found that after the first actual move of the board, the program gets locked up in the method following method:

Serial.println("Getting referenceAngles");
gReferenceAngles = gIMU.getVector(Adafruit_BNO055::VECTOR_EULER);
Serial.println("Got referenceAngles");

The debugger shows "Getting referenceAngles" as the last message before the lockup. I conclude that there is a problem with the BNO055's or the Feather M0's capacity to complete the I2C bus transaction to get the reference angles vector. This method works for quite a few iterations, at least until the BNO055 is moved and then must send new data for the new orientation.

I am concerned that there is a timing problem between SCL and SDA due to the missing level shifter for the SCL as compared with the SDA signal.

I wonder what to do. Should I:
1. Short the other level shifting transistor, Q1, so that SDA and SCL signals have the same relative electrical paths and timing?
2. Adjust the speed of the wire transfer down to a lower level?
3. Just give up on this damaged BNO055 board and order a new one?

I'm looking for some hints and suggestions here.
Attachments
BNO055 Repair.pdf
(47.54 KiB) Downloaded 74 times

srogers316
 
Posts: 39
Joined: Thu Jan 12, 2017 12:29 am

Re: BNO055 Woes

by srogers316 on Wed Mar 08, 2017 1:31 am

Here is the debug trace from the serial monitor for the problem I am experiencing:
The TICK lines are happening every 2 seconds. Each cycle gets the battery voltage, and the pitch and roll of the BNO055, and the calibration status of the BNO055.

The first TICK cycle shows that the BNO055 is not calibrated. TICK cycles 2- 62 show that the BNO055 is calibrated. The Pitch and Roll being reported are when the BNO055 and the Feather are stationary and rotated approx 180 degrees. This is because I need to push the reset button for programming. So I see a pitch of 177.37 degrees and a roll of less than 1 degree, which is very appropriate for the orientation of the BNO055 sensor. For TICKS 2-58, (representing 112 seconds of operation), the I2C communication with the BNO055 is working.

At TICK 59 I start to move the sensor. The readings start changing for pitch and roll until TICK 63. At TICK 63, the program reports "getting referenceAngles" but never returns from the call.

// Here is the call with the debugging code:
Serial.println("Getting referenceAngles");
gReferenceAngles = gIMU.getVector(Adafruit_BNO055::VECTOR_EULER);
Serial.println("Got referenceAngles");


############### DEBUG LOG ###############################

TICK
Getting battery Voltage
#1 NOCAL VBAT: 3.87 PITCH: 0.00 ROLL: 0.00
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#2 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#3 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#4 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#5 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#6 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#7 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#8 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#9 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#10 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#11 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#12 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#13 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#14 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#15 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#16 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#17 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#18 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#19 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#20 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#21 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#22 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#23 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#24 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#25 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#26 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#27 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#28 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#29 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#30 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#31 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#32 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#33 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#34 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#35 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#36 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#37 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#38 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#39 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#40 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#41 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#42 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#43 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#44 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#45 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#46 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#47 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#48 CALOK VBAT: 3.87 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#49 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#50 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#51 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#52 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#53 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#54 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#55 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#56 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#57 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#58 CALOK VBAT: 3.88 PITCH: 177.37 ROLL: 0.75
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#59 CALOK VBAT: 3.89 PITCH: 177.31 ROLL: 0.69
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#60 CALOK VBAT: 3.88 PITCH: 177.31 ROLL: 0.69
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#61 CALOK VBAT: 3.88 PITCH: 177.31 ROLL: 0.69
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#62 CALOK VBAT: 3.88 PITCH: -169.56 ROLL: 1.00
TICK
Getting battery Voltage
Getting referenceAngles
Got referenceAngles
#63 CALOK VBAT: 3.88 PITCH: -171.12 ROLL: 1.00
TICK
Getting battery Voltage
Getting referenceAngles

srogers316
 
Posts: 39
Joined: Thu Jan 12, 2017 12:29 am

Re: BNO055 Woes

by adafruit_support_mike on Sat Mar 11, 2017 5:10 am

Could you post a photo showing the BNO055 please? Let's make sure the connections are doing what you expect.

adafruit_support_mike
 
Posts: 57089
Joined: Thu Feb 11, 2010 2:51 pm

Re: BNO055 Woes

by srogers316 on Wed Mar 15, 2017 4:05 am

Sorry to delay this response, but in my area we had a windstorm and I was without power and internet for 5 days.

Attached is photo showing the BNO055 breakout board. I would like to insure you that I am getting communication with the board, and that I am reading several hundred cycles of angular data from the board. It all works well until I move the assembly the board is fastened to. After I move the board, I get perhaps one or two reads of the new angle information with changed data before the BNO055 locks up in the method that reads data (getVector()).

I want to point out that the BNO055 breakout board IS DAMAGED. I don't know how it happened, but the level shifting transistor for the SCL signal was somehow pulled off the board, or was not securely soldered down to it. I went through a long series of posts about not being able to get the unit to work in either I2C or serial mode before I discovered that the level shifting chip was missing. I made a change to the design that involved changing to a Feather (3.3v) board, so I felt that I could salvage the board by shorting the level shifter transistor pads on SCL from drain to source because I no longer need level shifting. So now the board is running by 3.3v power fed into the 3Vo connector, and the SCL and SDA signals are 3.3v. The SDA signal is still level shifted, or is at least still using the level shifting transistor for SDA. I assume that with no pullups on the 5V side of the SDA signal that the SDA signal is still working correctly, but there is a possibility that I should also short out the level shifter transistor for SDA.

Also, there is no clear instruction as to how to connect the board for power if you are using it with a 3.3V controller. Should I connect 3.3V to the 5V power input instead of 5V (which I do not have) and take pot luck on what ever voltage is output by the voltage regulator?
Attachments
BNO055 Breakout Board.pdf
(139.91 KiB) Downloaded 74 times

srogers316
 
Posts: 39
Joined: Thu Jan 12, 2017 12:29 am

Re: BNO055 Woes

by srogers316 on Fri Mar 17, 2017 1:23 pm

OK, I looked at the information about the BNO055 breakout board, and it does say that the Vcc pin is used for 3.3 or 5v input. So, I think what this means for me is that I am not running the board with the 10K pullups on the SDA line. Because my board is damaged, and I have shorted the Missing SCL level shifting transistor from source to drain, I am getting a pullup on the SCL line from the 3.3V internal supply that I am providing. But for the SDA signal line, I don't think there is a pullup bacaus I am providing no power to The Vcc pin.

I will connect the 3.3V from the feather to the Vcc input to see what happens and retest. I really don't have the option to change the BNO055 breakout right now because it is OUT OF STOCK.

srogers316
 
Posts: 39
Joined: Thu Jan 12, 2017 12:29 am

Re: BNO055 Woes

by adafruit_support_mike on Mon Mar 20, 2017 12:55 am

The I2C pull-ups on the BNO055 side of the level-shifting circuit are connected to the same supply rail as the BNO055, so the SDA pull-up on the 5v side of the connection you've bridged should be irrelevant.

Please post a photo of the board. We can only debug hardware based on the information we have, and the physical state of the connections is important.

adafruit_support_mike
 
Posts: 57089
Joined: Thu Feb 11, 2010 2:51 pm

Re: BNO055 Woes

by srogers316 on Mon Mar 20, 2017 3:14 am

Mike, I have posted a photo of the board in a pdf file format with callouts as to the wiring and as to the repair that I made on the board. This PDF file is attached to a message that is two or three messages up in this thread. I have now changed the wiring somewhat from the picture, but the change only involves how the positive power is connected to the BNO055 board..

I recently moved the 3.3 V wire from the Feather, previously connected to the 3Vo pin, to the Vcc Pin on the BNO055. I did this because I read in the instructions for the BNO055 that the Vcc pin works with either a 3.3V or a 5V input. This made absolutely no change to the behavior of the circuit. The behavior is all good when I want to read the Euleur angles and BEFORE I start MOVING the device. I get proper readings for the hundreds of reads of the device when it is still and has not been moved. However, when I move the device, I might get zero, one, or maybe two getVector() readings before the Feather board hangs in the call to getVector().

I have a suspicion about what is happening: I think the Feather M0 Basic proto board when running the Wire library for I2C (at least the version I am using) does not correctly handle the SCL clock stretch that the BNO055 is known to need according to comments in the BNO055 library code. I think that the Feather MO board needs some kind of a patch to Wire to allow it to handle the clock stretch. I think that one of the newer releases of the wire.h library on my machine might have this patch.

I am currently using the Wire library that is found in
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src
on my system.

This is the exact same library that I used on the Arduino Leonardo with this very same board WITH ABSOLUTELY NO PROBLEMS (UNTIL I DISCOVERED THE BROKEN LEVEL SHIFTER PART). THE BNO055, WHEN PREVIOUSLY WORKING PROPERLY, WAS WIRED EXACTLY AS IT IS TODAY, EXCEPT FOR THE FACT THAT IT NOW IS WIRED WITH 3.3V TO Vcc AND THE LEONARDO WAS WIRED WITH 5V TO Vcc. The Leonardo NEVER displayed this hang in the program when calling getVector(). I switched from the Leonardo board to the Feather M0 board so that I could get remote operation with battery charging, and 3.3 V operation on the BNO055 (because I discovered the missing level shifter on the SCK line at some point and I no longer had level shifting on SCK). The level shifter part either fell off, or was knocked off when the BNO055 board was mounted with 2-56 hardware to the stack of boards that represent my project (see the PDF file with the picture you previously requested).

To confuse the issue, I have wire.h libraries in three other directories on my machine. I do not know which wire.h file (and associated library) I should include for the Feather M0. I do not even know how to get they system include any other wire.h library other than the one in:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src
which I used with the Leonardo.

Here are the locations of the other three wire.h files and their associated libraries on my system after configuring the system for the Feather M0.
C:\Users\Steve\AppData\Local\Arduino15\packages\adafruit\hardware\samd\1.0.13\libraries\Wire
C:\Users\Steve\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.15\libraries\Wire\src
C:\Users\Steve\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.11\libraries\Wire

I am so desperate to get this working that I have even tried to bit-bang the I2C stuff, but all the bit-bang I2C libraries I have come across seem to have nonexistent or dubious support for clock stretching, and they are not working well.

Should I be using the wire library in the
C:\Users\Steve\AppData\Local\Arduino15\packages\adafruit\hardware\samd\1.0.13\libraries\Wire
directory? If So, how do I get the system to stop using the one in the
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src
directory?

Thanking you in advance for any help you might be able to provide.

srogers316
 
Posts: 39
Joined: Thu Jan 12, 2017 12:29 am

Re: BNO055 Woes

by srogers316 on Mon Mar 20, 2017 3:19 am

Just a quick clarification about the picture posted of the BNO055 board. The callout that states SCK to SCL is in error. Of course, the correct callout should say SCL to SCL. Too many clocks to name. I did not connect the SCK from SPI to the SCL of I2C!!!!!!!!!

srogers316
 
Posts: 39
Joined: Thu Jan 12, 2017 12:29 am

Re: BNO055 Woes

by srogers316 on Mon Mar 20, 2017 4:14 am

Another piece of information in the BNO055 Woes thread. I have resolved which wire library is being loaded. I removed an unnecessary call in my main *.ino program to include <wire.h>.

After recompiling, the only module I have that loads Wire.h is the BNO055 module. When I removed this unnecessary include, my compile output showed that the wire library in use was the wire library from adafruit, apparently installed for the Feather M0:

The wire library was loaded from here:
C:\Users\Steve\AppData\Local\Arduino15\packages\adafruit\hardware\samd\1.0.13\libraries\Wire

It appears that I have loaded the correct wire library. I had high hopes that this would fix the problem. Sadly, it did not. The code behaves now exactly as before, in that it will display angle information until the BNO055 is moved, then it will still fail (hang) in the call to getVector().

Does the BNO055 work at all with the Feather M0 Basic Proto, or does it fail to work? Has it been tested?

Does the hardware I2C supported by Wire.h on the processor in the M0 have the capability of handling I2C clock stretching? I'm beginning to think that it does not.

I do not see any extra code that I need to enable in Wire to make it work.

srogers316
 
Posts: 39
Joined: Thu Jan 12, 2017 12:29 am

Re: BNO055 Woes

by gammaburst on Mon Mar 20, 2017 10:19 pm

My Feather M0+ WiFi works with BNO055 but just barely. Touching SDA with my finger freezes it until I reset. I tried adding stronger I2C pullups but that didn't help much. This could be a clock-stretching issue. Needs oscilloscope examination but I don't have much time right now.

I connected both Vin and 3vo to +3V. That helps, especially without the external pullups.

Be sure your radio transmitter isn't blasting RF power into the BNO, upsetting it's operation.

I have bit-banging I2C code that works well on everything that I've tried, but it needs to be adapted to each different microcontroller due to software timing delays.
Attachments
IMG_1751a.jpg
Feather M0+ WiFi with BNO055
IMG_1751a.jpg (176.21 KiB) Viewed 1660 times

gammaburst
 
Posts: 412
Joined: Thu Dec 31, 2015 12:06 pm

Re: BNO055 Woes

by srogers316 on Tue Mar 21, 2017 1:17 am

Gammaburst--Thanks so much for responding.

I would love to see your bit-banging I2C code for the M0. Hopefully it handles clock stretching. Would you mind posting that code somewhere? I do not have a scope (other than a Bitscope), but I do have a Salae logic analyzer. It would seem a pain to try to the to the bottom of this with one of these analyzers, but it looks like I might need to do just that.

I have not even tried to bring the radio up in this design, so, currently the radio is non-functional and cannot be the source of my problem. I need good data to transmit, and I just can't get good data yet. This is not to say that the radio will not become a problem, but I hope not.

I do not have a problem getting through all of the setup calls in the BNO055 library. The only calls that have given me problems are getVector() and getQuat(), which are the only other calls I need. I have slightly modified the BNO055 library so that I can construct the BNO055 object with a parameter that sets the BNO055's orientation mode to a slightly different orientation to suit my sensor orientation in the application.

I may need to switch to the Feather 32u4 board, which I think closely parallels the Arduino Leonardo, but at 3.3V levels. I previously had the BNO055 up and running well on an Arduino Leonardo at 5V with no problems with the clock stretching. I think that the 32u4 board's I2C hardware would not give as much, if any problem. But if I can get the bit-bang code that you have developed to work, I could probably just eliminate the problem and use the M0 board.

I do not need great speed from the I2C, so I think bit banging, if it works, would be an acceptable workaround. The purpose of this device is to monitor the angle of a violin fingerboard and the rotational angle (roll) of a violin as an aid to my grandson's Suzuki violin teacher to get students to hold their violins properly and not let the fingerboard dip and not rotate the violin (instead of adjusting the bow angle) for bowing on different strings. I could get by with one measurement per second, which would allow very slow I2C clock speeds if needed. The receiver part of the project gets the angles and alarms when the fingerboard dips more than 15 degrees, or then the violin rolls more that 15 degrees from a set position.

srogers316
 
Posts: 39
Joined: Thu Jan 12, 2017 12:29 am

Re: BNO055 Woes

by gammaburst on Tue Mar 21, 2017 1:47 pm

I tried my bit-banging I2C code (yes it supports clock-stretching), and I'm getting the same problem I had earlier - touching SDA lightly with my finger causes the I2C communication to go sour. Same symptom with totally different code - perplexing. The rise/fall times look ok on my scope. I'm investigating but I don't have much spare time.

Perhaps you and I are seeing different manifestations of the same problem. Try adding external I2C pullup resistors. Try pulling-up just one signal at a time. See if that helps/hurts your symptom. On my setup, adding only SDA pullup helps, adding only SCL pullup hurts.

My bit-banging reads the BNO at 100 Hz and converts the quaternion to Euler with some trig. I'll share my code after I figure out this instability problem. Don't have much time to work on it though.

*** UPDATE ***

I think I see the culprit - it's the BNO's fault. During a clock-stretched multi-byte I2C read transfer, if the data byte's first bit (D7) is 1, then the BNO releases SDA (allowing the pullup to pull it high) only about 120 ns before releasing SCL. The BNO spec says its SDA-to-SCL setup time is 100 ns minimum, so the BNO is giving itself almost no safety margin. If your I2C pullup resistors are slightly imbalanced or wimpy (a common situation), then SCL might rise faster than SDA, violating the BNO timing spec and creating a false I2C START condition, and that causes the BNO to abort the current transfer and begin a new one, resulting is havoc.

Problem occurs easily on my Feather M0+ WiFi with default pullups. Bit-banged I2C doesn't help. Problem also occurs on my Arduino Uno if I deliberately imbalance the pullups.

Recommendation: Install strong pullups. Maybe use a stronger pullup on SDA than SCL. Verify results with oscilloscope.

Just for fun, here's my bit-banged I2C. The various microsecond delays are longer than I wanted. I haven't yet investigated why. Maybe the pin I/O functions are slow. No big deal, it works.

Code: Select all | TOGGLE FULL SIZE
// BNO055 running on Feather M0+ WiFi using crude bit-banged I2C.
//
// Connect Adafruit BNO055 breakout(s) to Feather header pins:
//   BNO055 Vin - Feather 3V
//   BNO055 3vo - Feather 3V
//   BNO055 GND - Feather GND
//   BNO055 SDA - Feather 5 and 2.2K pullup
//   BNO055 SCL - Feather 6 and 3.0K pullup
//   BNO055 RST - Feather 9

#define bbSDA 5     // bit-banged Feather pins
#define bbSCL 6
#define bbRST 9

#define BNO_ADDR 0x28       // BNO I2C address
#define BNO_PERIOD 10       // BNO read interval, milliseconds

#define LO_SDA() do { nsdelay(2500/3); digitalWrite(bbSDA,LOW);  pinMode(bbSDA,OUTPUT); } while (0)  // set SDA low
#define HI_SDA() do { nsdelay(2500/3); pinMode(bbSDA,INPUT);  digitalWrite(bbSDA,HIGH); } while (0)  // set SDA high
#define LO_SCL() do { nsdelay(2500/3); digitalWrite(bbSCL,LOW);  pinMode(bbSCL,OUTPUT); } while (0)  // set SCL low
#define HI_SCL() do { nsdelay(2500/3); pinMode(bbSCL,INPUT);  digitalWrite(bbSCL,HIGH); while (!RD_SCL()); } while (0)  // set SCL high, wait for clock stretching
#define RD_SDA() digitalRead(bbSDA)   // read SDA
#define RD_SCL() digitalRead(bbSCL)   // read SCL
#define LO_RST() do { pinMode(bbRST,OUTPUT);  digitalWrite(bbRST,LOW);  } while (0)
#define HI_RST() do { pinMode(bbRST,OUTPUT);  digitalWrite(bbRST,HIGH); } while (0)

// Some BNO055 Registers Page 0
#define PAGE_ID_0         (0x00+0x07)  // 0x00 Page ID
#define ACC_DATA_X_LSB    (0x00+0x08)  // Acceleration Data X LSB
#define EUL_HEADING_LSB   (0x00+0x1A)  // Euler heading LSB
#define QUA_DATA_W_LSB    (0x00+0x20)  // Quaternion Data W LSB
#define CALIB_STAT        (0x00+0x35)  // SYS Calib Status <7:6>, GYR Calib Status <5:4>, ACC Calib Status <3:2>, MAG Calib Status <1:0>
#define OPR_MODE          (0x00+0x3D)  // 0x1C Operation Mode <3:0>

#define nsdelay(ns) delayMicroseconds((ns) >> 10)

char i2c_repeated_start;

static void start_cond(void)
{
  if (i2c_repeated_start)           // if need to repeat start condition
  {
    HI_SDA();
    HI_SCL();
  }
  LO_SDA();
  LO_SCL();
  i2c_repeated_start = 1;
}

static void write_bit(unsigned char bit)
{
  if (bit)
    HI_SDA();
  else
    LO_SDA();
  HI_SCL();
  LO_SCL();
}

static unsigned char read_bit(void)
{
  unsigned char bit;

  HI_SDA();
  HI_SCL();
  bit = RD_SDA();
  LO_SCL();
  return bit;
}

static void stop_cond(void)
{
  LO_SDA();
  HI_SCL();
  HI_SDA();
  i2c_repeated_start = 0;
}

#define NAK   1
#define START 2
#define STOP  4

static unsigned char i2c_send(unsigned char flags, unsigned char byte)  // allowable flags: START STOP
{
  unsigned char bit;
  unsigned char nak;

  if (flags & START)
    start_cond();
  for (bit=0; bit<8; bit++)
  {
    write_bit(byte & 0x80);
    byte <<= 1;
  }
  nak = read_bit();
  if (flags & STOP)
    stop_cond();
  return nak;
}

static unsigned char i2c_recv(unsigned char flags)  // allowable flags: NAK STOP
{
  unsigned char byte = 0;
  unsigned char bit;

  for (bit=0; bit<8; bit++)
    byte = (byte << 1) | read_bit();
  write_bit(flags & NAK);
  if (flags & STOP)
    stop_cond();
  return byte;
}

static void bno_page(unsigned char reg)  // select page containing specified register
{
  static unsigned char current_page;

  if (!!(reg & 0x80) == current_page)  // if already on correct page
    return;
  current_page = !current_page;
  i2c_send(START,BNO_ADDR*2+0);  // BNO+write
  i2c_send(0, PAGE_ID_0);        // register number
  i2c_send(STOP, current_page);  // write
}

static void bno_write(unsigned char reg, unsigned char data)  // write one BNO register
{
  bno_page(reg);                 // select correct register page
  i2c_send(START,BNO_ADDR*2+0);  // BNO+write
  i2c_send(0, reg & 0x7F);       // register number
  i2c_send(STOP, data);          // write
  nsdelay(2000);                 // ???? idle between writes, tIDLE_wacc_nm
}

//static unsigned char bno_read(unsigned char reg)  // read one BNO register
//{
//  bno_page(reg);                 // select correct register page
//  i2c_send(START,BNO_ADDR*2+0);  // BNO+write
//  i2c_send(0, reg & 0x7F);       // register number
//  i2c_send(START,BNO_ADDR*2+1);  // BNO+read
//  return i2c_recv(NAK+STOP);     // read
//}

static void bno_read_multi(unsigned char reg, int n, unsigned char *buf)  // read multiple BNO registers, doesn't support crossing register page boundary
{
  if (!n)
    return;
  bno_page(reg);                 // select correct register page
  i2c_send(START,BNO_ADDR*2+0);  // BNO+write
  i2c_send(0, reg & 0x7F);       // first register number
  i2c_send(START,BNO_ADDR*2+1);  // BNO+read
  while (n--)
    *buf++ = i2c_recv(n ? 0 : NAK+STOP);  // read
}

void setup(void)
{
  Serial.begin(115200);

  Serial.println("Resetting BNO055...");
  HI_SDA();
  HI_SCL();
  LO_RST();                     // reset BNO055
  delay(1);
  HI_RST();
  delay(800);                   // ample time for BNO055 to boot

  Serial.println("Setting BNO055 mode...");
  bno_write(OPR_MODE, 0x0C);    // request NDOF mode
  delay(10);                    // wait for BNO055 to switch modes

  Serial.println("Reading BNO055 data...");
}

void loop(void)
{
  struct
  {
    int16_t acc_x, acc_y, acc_z;
    int16_t mag_x, mag_y, mag_z;
    int16_t gyr_x, gyr_y, gyr_z;
    int16_t eul_heading, eul_roll, eul_pitch;
    int16_t qua_w, qua_x, qua_y, qua_z;
    int16_t lia_x, lia_y, lia_z;
    int16_t grv_x, grv_y, grv_z;
    int8_t  temp;
    uint8_t calib_stat;
  } s;

//bno_read_multi(ACC_DATA_X_LSB,  sizeof s, (uint8_t*)&s);              // read registers ACC_DATA_X_LSB through CALIB_STAT into struct
//bno_read_multi(EUL_HEADING_LSB, 6,        (uint8_t*)&s.eul_heading);  // read registers EUL_HEADING_LSB through EUL_PITCH_MSB into struct
  bno_read_multi(QUA_DATA_W_LSB,  8,        (uint8_t*)&s.qua_w);        // read registers QUA_DATA_W_LSB through QUA_DATA_Z_MSB into struct
  bno_read_multi(CALIB_STAT,      1,        (uint8_t*)&s.calib_stat);   // read register  CALIB_STAT into struct

  // convert quaternion to Euler, because BNO055 Euler data is broken
  float qw =  s.qua_w;  // convert BNO axes to aerospace axes
  float qx =  s.qua_y;
  float qy =  s.qua_x;
  float qz = -s.qua_z;
  float norm = 1.0 / sqrt(qw*qw + qx*qx + qy*qy + qz*qz);
  qw *= norm;  // normalize quaternion
  qx *= norm;
  qy *= norm;
  qz *= norm;
  float heading = 180/M_PI * atan2(qw*qz + qx*qy, 0.5 - qy*qy - qz*qz);
  float roll    = 180/M_PI * atan2(qw*qx + qy*qz, 0.5 - qx*qx - qy*qy);
  float pitch   = 180/M_PI * asin(2 * (qw*qy - qx*qz));

  Serial.print("Orientation: ");
  Serial.print(heading);
  Serial.print(" ");
  Serial.print(roll);
  Serial.print(" ");
  Serial.println(pitch);
  Serial.print("Calibration: ");
  Serial.print((s.calib_stat >> 6) & 3);
  Serial.print(" ");
  Serial.print((s.calib_stat >> 4) & 3);
  Serial.print(" ");
  Serial.print((s.calib_stat >> 2) & 3);
  Serial.print(" ");
  Serial.println((s.calib_stat >> 0) & 3);

  static unsigned long waituntil;
  unsigned long now = millis();
  if ((unsigned long)(waituntil - now) > 2000)  // if timer is out of sync
    waituntil = now;
  delay(waituntil - now);
  waituntil += BNO_PERIOD;
}
Attachments
IMG_1754a.jpg
Feather M0+ WiFi with BNO055 using bit-banged I2C
IMG_1754a.jpg (169.46 KiB) Viewed 1625 times

gammaburst
 
Posts: 412
Joined: Thu Dec 31, 2015 12:06 pm

Re: BNO055 Woes

by srogers316 on Sat Mar 25, 2017 5:19 am

Thank you so much for the tip and for the code. I'll put it to use tomorrow.
When you say that I should use strong pullups, what does that mean?

On the SDA line, I have the original 10K pullup on the micro-facing side of the level shifter. On the SCL line, I have
essentially 2 10K pullups in parallel (equal to 5K, i guess), because I shorted out the missing level shifter transistor.

What value would you recommend for the SDA and SCL pullups in my case with the damaged SCL input?

By a strong pullup, I'm guessing that you would want a less resistive path to 3.3V.

I am guessing that when I shorted the missing level shifting transistor on the SCL input line, there are some differences in the
propagations or rise time seen by the BNO055 between SDA and SCL that might be dignificant, and that would be different than that seen if the level shifting chip were in place. Also, I'm wondering where you are putting these pullup resistors. My concern is that the actual signal seen by the BNO055 is on the other side of the level shifter transistors on the breakout board. So are you putting the pullups inboard of the level shifters on the BNO055 breakout board, or outboard of the level shifters.

I'm thinking that when it is all said and done, if it is possible to run the BNO055 reliably from the Feather M0 boards, one may have to short both level shifters so that there is a correct picture of what is going on at the BNO055 chip itself, rather than upstream, on the drivers.

I have been working with a Saleae clone logic analyzer to watch the signals, and I'm seeing some really funky stuff. It is almost like one of two things is happening that I don't understand. When looking at traces while I'm trying to read data, I am seeing the data line SDA stuck low, as if the BNO055 is holding the line low or has left the line low. Also, I'm seeing that that when the init routine in the adafruit library does a reset, it takes a really long time for the BNO055 to start responding again, Something like 400 uS. In that time the code is trying to read the chip ID (0x0A) as a way to insure that the unit has come back to life after a reset. This is creating a lot of NAKed packets trying to read the chipID after a reset. There is one place in init where this polling of the chip is done when an reset takes place, but there is another location in the init code wheere this does not happen and I think the code gets turned loose to work when the I2C is not responding after init. So that is wierd. In any case, I'm anxious to get the code running with the bitbanged I2C code you sent. I've looked all over and I can't find any other good I2C library that supports clock stretching.

I know that at some point in the code to implement clock stretching, you have to look at the clock line as an input, when it is really an output. Is it possible on the M0 to do a digital read on an output pin to get the state of the output pin, and to be able to see the actual value of the signal on the pin, and not what the output register thinks it should be. From what I read about the chip on the M0, that is possible if the input is enabled at a register level in the M0 on a particular port and bit. What I am trying to be able to do is to read the SCL pin without changing it from an output to an input, if you get my drift, because I think that going from an output to an input and then back in the wrong order without regard to what might be on the output of the chip might cause a glitch on the line, which you wouldn't want.

srogers316
 
Posts: 39
Joined: Thu Jan 12, 2017 12:29 am

Re: BNO055 Woes

by gammaburst on Sat Mar 25, 2017 8:39 am

Engineering slang, sorry. By "strong" I mean lower resistance, able to pass more current, pull up more quickly. The pullup resistor's job is to quickly charge up the unavoidable unwanted capacitance on the I2C bus. Lower resistance is good, providing faster rise-time, but also consuming more power.

I used 2.2K on SDA and 3.0K on SCL (see photo). I selected relatively low and unequal values to workaround the BNO problem described in my previous message. The minimum recommended resistance for a 3.3V I2C bus is somewhere around 1K. Power consumption increases as the resistance decreases.

Your description of clock stretching sounds correct. Each time the controller (Feather) releases SCL (allowing it to be pulled high), it waits until SCL actually goes high (in case the slave is holding it low "clock stretching"). My bit-banging code waits for SCL with this statement: "while (!RD_SCL());" My Feather appears to support clock stretching just fine, at least for the BNO055, so no need for bit banging or other software fixes. I'm guessing your Feather is good too.

My startup code pulses RST to reset the BNO, then waits 800 ms for the BNO to boot, then writes NDOF to the operating mode register, then waits 10 ms for that to take effect, then begins reading fusion data every 10 ms. I don't use Adafruit's libraries.

By the way, if you plan to tilt the BNO more than about 20 degrees, beware the Euler outputs begin distorting. The quaternion is fine.

gammaburst
 
Posts: 412
Joined: Thu Dec 31, 2015 12:06 pm

Re: BNO055 Woes

by srogers316 on Sat Mar 25, 2017 5:53 pm

I have started into your bit-bang code. My rule is to try to understand the code before using it, especially if I am hoping it will solve mysterious problems.

I have a couple of questions if you don't mind.

  1. I've noted that you connected the Reset line of the BNO055 breakout and that you use that input to do a hardware reset of the BNO055.

    The Adafruit library does not use the Reset line, but it does reset the BNO055 in a couple of different ways using a software call. For this reason, I'd like to avoid hooking up a reset line because it can be done in I2C. Do you see a problem with that?

    See the information below about the Adafruit begin() method.

  2. I see that you have a macro called nsdelay() (which I assume means nanosecond delay).

    #define nsdelay(ns) delayMicroseconds((ns) >> 10)

    I want to understand this macro. It appears to convert a numeric nanosecond delay into an equivalent microsecond delay. I see that a call to the macro is used in five places in the code.

    #define LO_SDA() do { nsdelay(2500/3); digitalWrite(bbSDA,LOW); pinMode(bbSDA,OUTPUT); } while (0) // set SDA low
    #define HI_SDA() do { nsdelay(2500/3); pinMode(bbSDA,INPUT); digitalWrite(bbSDA,HIGH); } while (0) // set SDA high
    #define LO_SCL() do { nsdelay(2500/3); digitalWrite(bbSCL,LOW); pinMode(bbSCL,OUTPUT); } while (0) // set SCL low
    #define HI_SCL() do { nsdelay(2500/3); pinMode(bbSCL,INPUT); digitalWrite(bbSCL,HIGH); while (!RD_SCL()); } while (0) // set SCL high, wait for clock stretching
    nsdelay(2000); // ???? idle between writes, tIDLE_wacc_nm

    I am concerned about the fact that the macro uses bit shifting as a method to calculate microseconds from nanoseconds. I assume that this use of bit shifting is for speed, i.e., to eliminate the need for a mathematical division. But what is really happening in that the nanosecond value is divided by 1024 rather than 1000 because of the bit shifting. This also means that the calls from the LO_SDA(), HI_SDA(), LO_SCL() and HI_SCL macros all resolve to a call to delayMicroseconds() withn a 0 parameter value. This occurs because 2500/3 = 833, and 833<<10 resolves to 0.

    Also the call to nsdelay(2000) resolves to delayMicroseconds(1) instead of delayMicroseconds(2).

    Perhaps, for these small values of nanoseconds, the call to delayMicroseconds with a 0 (or 1) parameter value suffices for the delay, given the latency of the call itself. Were you aware of this in your design?

ABOUT THE ADAFRUIT BEGIN METHOD (BNO055 SETUP)

The call to Adafruit_BNO055.begin() method does the following on the I2C bus:

  1. Verifies that the chip is a BNO055 chip by reading address 0x00 (BNO055_CHIP_ID_ADDR) of the chip and looking for an 0xA0.

  2. Sets the operation mode of the BNO055 to OPERATION_MODE_CONFIG by writing to address 0x3D (BNO055_OPR_MODE_ADDR) a value of 0x00.

    OPERATION_MODE_CONFIG is the default mode after Power On Reset, RESET, or writing SYS_TRIGGER with RST_SYS = 1.

  3. Triggers a reset of the BNO055 by writing an 0x20 to address 0x3F (BNO055_SYS_TRIGGER_ADDR).

    *** From the Datasheet***
    The sensor features a power-on reset (POR), initializing the register map with the default values and starting in CONFIG mode. The POR is executed at every power on and can also be triggered either by applying a low signal to the nRESET pin for at least 20ns or by setting the RST_SYS bit in the SYS_TRIGGER register.


    A value of 0x20 represents setting only the RST_SYS bit.

  4. Waits for the BNO055 to recover from the reset by continually polling the BNO055 chip by reading reading address 0x00 (BNO055_CHIP_ID_ADDR) of the chip and looking for an 0xA0.

    It turns out that about 430us is required after a reset before the BNO055 starts communicating again on the I2C bus. The observed mode of non-comminication is by a NAK to read and write addresses.

  5. Sets the BNO055's power mode to normal by writing a 0x00 (POWER_MODE_NORMAL) to address 0x3E BNO055_PWR_MODE_ADDR.

    POWER_MODE_NORMAL is the startup default.

  6. Sets the axis map configuration to the requested remapping of the axes by writing the remapping value to address 0x41 (BNO055_AXIS_MAP_CONFIG_ADDR).

    Note, I may have added step 6 to the Adafruit code to remap the axes to the juxtaposition of the BNO055 breakout board axes to my physical hardware. But the code might have existed just to set the default mapping as well, I can't remember. I can't use the default mapping.

  7. Sets the axis map numerical sign to the requested mapping of the axes by writing the remapping value to address 0x42 (BNO055_AXIS_MAP_SIGN_ADDR)

    Note, I may have added step 7 to the Adafruit code to remap the axes to the juxtaposition of the BNO055 breakout board axes to my physical hardware. But the code might have existed just to set the default mapping as well, I can't remember. I can't use the default mapping.

  8. Writes a value of 0x00 to the 0x3F (BNO055_SYS_TRIGGER_ADDR)

    This action clears the RST_SYS bit of the SYS_TRIGGER register (set above) and also insures no self test operation, no external clock usage, and no pending interrupts. It seems that the SYS_TRIGGER done here also requires about 430us for the BNO055 to wake up after it's issued.

  9. Sets the operation mode of the BNO055 to typically NDOF, 0x0C (OPERATION_MODE_NDOF), by writing to address 0x3D (BNO055_OPR_MODE_ADDR).

srogers316
 
Posts: 39
Joined: Thu Jan 12, 2017 12:29 am

Please be positive and constructive with your questions and comments.