Sparkfun BNO080 - Teensy 3.6 >> 4.0

Status
Not open for further replies.

ckmiauto

Member
I'm trying to use Sparkfun's library for the BNO080 IMU on a Teensy 4.0. I'm able to run the example on a Teensy 3.6, but it does not run on a 4.0.

I've read the thread on the BNO055, and tried adding some delays in the start sequence. It did not resolve the problem.

On the 4.0, if I build with the I2C scanner, it identifies the unit address correctly at 0x4B.

From investigation, I don't think it is getting through the 'begin' routine of the Sparkfun Library.

The interface to the 080 is different than the 055, but the I2C interface problem seems similar.

The Teensy initially sends a 'Reset' packet. The 080 responds with an 'Advertisement' response.

The library is set up to read/dump this data, and end in a ready state. I don't think it makes it through the read stage. I haven't yet been able to tear up the code enough to instrument it to figure out exactly where.

I've attached the code below of the example Accelerometer interface code.

Any help, or directions to investigate next, would be greatly appreciated!

Code:
#include <Wire.h>

#include "SparkFun_BNO080_Arduino_Library.h"
BNO080 myIMU;

void setup()
{
  Serial.begin(9600);
  Serial.println();
  Serial.println("BNO080 Read Example");

  Wire.begin();

  myIMU.begin();

  Wire.setClock(400000); //Increase I2C data rate to 400kHz

  myIMU.enableAccelerometer(50); //Send data update every 50ms

  Serial.println(F("Accelerometer enabled"));
  Serial.println(F("Output in form x, y, z, in m/s^2"));
}

void loop()
{
  //Look for reports from the IMU
  if (myIMU.dataAvailable() == true)
  {
    float x = myIMU.getAccelX();
    float y = myIMU.getAccelY();
    float z = myIMU.getAccelZ();

    Serial.print(x, 2);
    Serial.print(F(","));
    Serial.print(y, 2);
    Serial.print(F(","));
    Serial.print(z, 2);
    Serial.print(F(","));

    Serial.println();
  }
}


https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library
 
Looking at : sparkfun.com/tutorials/qwiic-vr-imu-bno080-hookup-guide

It shows this code ordering:
Code:
Wire.begin(); //Begin the I2C bus
Wire.setClock(400000); //Increase I2C data rate to 400kHz

[B]// delay(1000);[/B] // perhaps add this here uncommented to allow IMU to power up and be ready.

myIMU.begin();
myIMU.enableRotationVector(50); //Send data update every 50ms

If shows bool return value for .begin, also a void enableDebugging(Stream &debugPort = Serial); that might give feedback?

Does adding delay(1000) then softReset() after begin - or Wire.setclock() change anything?
 
I did experiment with adding a delay between the Wire begin, and IMU begin. It did not work. I also experimented with adding additional delay between 'receivePacket' calls in the softReset() function. This did not work either.

Capturing the IMU.begin output; it consistently returns false. Thanks for the good pointer on debug. It looks fairly easy to copy/paste around in the library to look at the outcome of other vars.

I had some success with the 'PrintPacket' example. This enables the debug you mention. It produced a bunch of 'I2C timeout', then a line describing a 279 byte packet which I assume was the advertising packet. It seemed to hang at that point, and did not seem to take the command to enable the accelerometer.

I plan to spend some more time with the library this evening. I plan to instrument the receivePacket function to understand what succeeds/fails. My sense is the open loop 'advertisement' message is behaving unexpectedly. It's strange the sequence works on the 3.6, and not on the 4.0 as these all seem to be pretty vanilla Wire commands. There is also a comment in the code about double resets if 'moving too quickly', so the BNO080 interface may be odd as well.

Thanks for your help. I'll share what I find.
 
Know this is going to sound obvious - but did you to change wire.setClock to 100000? Just as a test. Also are you using the latest Teensyduino 1.48 - Paul did put some fixes in for the issue with wire when we were using the BNO055
 
Thanks for the suggestion. Will definitely try that; I have not yet. I have tried with the speed command omitted, and it did not fix it.

I am running 1.48. After reading the 055 thread I made sure.

Beneath all layers of function calls under IMU.begin, the code seems to hang at a very low level. The Teensy sends a one byte packet for reset, then does four sequential 'read' commands to get the 4 bytes of meta for the 'advertisement' packet. Based on my prior posts, I think the reset is successful. It's the timing of the response packet that seems weird and unrecoverable. I'll poke again at it tonight; it could be getting farther than I think.

I didn't fully understand the changes made for the push to 1.48, that's why I thought I'd bring it up here. Especially since the same code runs on 3.6 and not 4.0.
 
maybe try increasing counter limit in waitForSPI() in sparkfun driver.

could also experiment with running T4 @120mhz (IDE config option)
 
I think I've exhausted all the permutations of delays/I2C speed/CPU mhz... with the driver as it stands. Slowing down or delaying does not resolve the issue.

I was able to find that bytes and the packet header seem to be producing values. The values seem strange (packet size too large) from the first pull from the 080. Where the code seems to hang is that subsequent I2C available calls result in no bytes available, but the driver seems to think it still has bytes to pull. This results in 'I2C timeout'. This seems like a general process fail, poor init strategy, or even just failure to clear vars. However, the question still remains why the strategy works on 3.6 and not 4.0?

All these layers/branches in the driver are too confusing for quick resolution. My next step is to generate a sketch with only the low level commands. I'll try to run on both 3.6 and 4.0 to see if there is some sort of differential pollution of what's arriving. I'll share the code and results.

Insights, advice, opinions still welcome...
 
Can you try it reconnected to WIRE1 pins 16/17 instead of 19/18 ?

Only recent i2c done here was ssd1306 but it ran well up to 1MHz from TD 1.48 and 3 MHz with a clock adjustment - on both WIRE and WIRE1.
 
Looking at the i2c commands in the getData and sendPacket functions of the library you might have to modify the code to use beginTransaction and endTransaction commands instead of beginTransmission/endTransmission. Ran into an issue before with this. Don't have a BNO080 to test this out on but if you can't figure out how to modify the code I can do it for you to test when I get home - out right now.
 
More experimentation tonight. There were to many variables managed by the library to extract out commands, so I added more comments and continued to use the library.

Here's what happens on the 4.0:
1. Reset packet is sent (as far as I know)
2. 4 bytes read - data says there are 272 bytes to read
3. proceeds to try to read the data, but I2C times out.

The 3.6 seems to read through all 272 bytes. The 4.0 keeps timeout looping (stuck in while in softReset)

I haven't tested on 16/17 yet. Do I need to call wire with "Wire.begin(1);" in that case?

If you can point me to an example where I can use beginTransaction/endTransaction instead, I can probably tweak the code. From my google search, it seems those commands are SPI specific only? Is there a way they can be called for I2C?

One last point - I should note the pull-ups on the 080 board are only 2.2k. Is it worth it to try with larger resistors?
 
2.2K resistors are about right - if they work on T_3.6 with the same 3.3V

Wire.begin() is wire and Wire1.begin() is for Wire1 and will setup to use the other pins

For SSD1306 display sketch to swap I just added this after the #include's

#define Wire Wire1 // use 2nd i2c bus pins

That won't help if it is a software conflict - but if there was a problem with the wire connections the goal was to rule that out with moving the wires - or fresh pins just in case.
 
Last edited:
Yep you are right - got confused looking at the code on my phone.

I did just order one from Amazon but wont have it until Sunday now.
 
OK - I've generated some more clarity. I extracted all the calls into sequential code.

Here's the sequence
1. Reset packet sent
2. Short delay
3. Request 4 bytes > determine number of bytes available
4. Check for data available (Wire.available)
5. read 32 byte packet
6. repeat step 5 until all data consumed

The Teensy 3.6 makes it through no problem.

The Teensy 4.0 is ok to step 3. It then trys to read the data. The 'available' call fails, and the first 32 byte pull is full of 0xff. It then recovers, and reproduces exactly what the 3.6 captures.

Bottom Line > Connected to the 4.0, the 080 responds 4 good bytes, then 32 corrupt bytes, then recovers. Does not on the 3.6

Of course, I inserted a hack if the header bytes are all 0xff, then blast through and burn the data. Can do the same to ignore a first data available fail. Both shouldn't be a fix...

Anyone have ideas why the 4.0 might cause the 2nd requestFrom call to the I2C buffer to be corrupt, and not the 3.6?

Code:
#include <Wire.h>

TwoWire *_i2cPort;

uint8_t _deviceAddress;

//#include <SparkFun_BNO080_Arduino_Library.h>

//BNO080 IMU;
#define MAX_PACKET_SIZE 128
#define BNO080_DEFAULT_ADDRESS 0x4B
#define I2C_BUFFER_LENGTH 32

uint8_t shtpData[MAX_PACKET_SIZE];
uint8_t sequenceNumber[6] = {0, 0, 0, 0, 0, 0};

bool rslt;

void setup() {
  
  Serial.begin(9600);
  delay(500);
  Serial.println();
  Serial.println("Begin code");

  Wire.begin();
  Serial.println("Wire begun");
  //delay(1000);
  //Begin
  uint8_t _deviceAddress = BNO080_DEFAULT_ADDRESS; //If provided, store the I2C address from user
  TwoWire &wirePort = Wire;
  _i2cPort = &wirePort;

  //Reset packet
  shtpData[0] = 1;

  //sendPacket
  uint8_t channelNumber = 1;
  uint8_t dataLength = 1;
  uint8_t packetLength = dataLength + 4;
  
  _i2cPort->beginTransmission(_deviceAddress);
  
  _i2cPort->write(packetLength & 0xFF);        //Packet length LSB
  _i2cPort->write(packetLength >> 8);         //Packet length MSB
  _i2cPort->write(channelNumber);           //Channel number
  _i2cPort->write(sequenceNumber[channelNumber]++);
  
  for (uint8_t i = 0; i < dataLength; i++)
  {
      _i2cPort->write(shtpData[i]);
  }
  Serial.println("Reset packet sent");
  
  if (_i2cPort->endTransmission() != 0)
  {
      Serial.println("End Trans Fail");
  }

  delay(1000);
  
  // receivePacket

  _i2cPort->requestFrom((uint8_t)_deviceAddress, (uint8_t)4);

  //waitForI2C

  if (waitForI2C() == true){Serial.println("Header Data available");}
  else{Serial.println("No Header Data available");}

  uint8_t packetLSBr = _i2cPort->read();
  Serial.print("LSB ");
  Serial.println(packetLSBr);
  uint8_t packetMSBr = _i2cPort->read();
  Serial.print("MSB ");
  Serial.println(packetMSBr);
  uint8_t channelNumberr = _i2cPort->read();
  Serial.print("CHN ");
  Serial.println(channelNumberr);
  uint8_t sequenceNumberr = _i2cPort->read(); //Not sure if we need to store this or not
  Serial.print("SQN ");
  Serial.println(sequenceNumberr);

  int16_t dataLengthr = ((uint16_t)packetMSBr << 8 | packetLSBr);
  dataLengthr &= ~(1 << 15); //Clear the MSbit.
  //This bit indicates if this package is a continuation of the last. Ignore it for now.
  //TODO catch this as an error and exit
  if (dataLengthr == 0)
  {
    //Packet is empty
    //return (false); //All done
    Serial.println("packet empty");
  }
  dataLengthr -= 4; //Remove the header bytes from the data count
  Serial.print("DATL ");
  Serial.println(dataLengthr);

  // getData
  uint16_t bytesRemaining = dataLengthr;
  uint16_t dataSpot = 0;
  bool faultpacket = false;
  
  while (bytesRemaining > 0)
  {
    uint16_t numberOfBytesToRead = bytesRemaining;
    if (numberOfBytesToRead > (I2C_BUFFER_LENGTH - 4))
      numberOfBytesToRead = (I2C_BUFFER_LENGTH - 4);
    Serial.print("Bytes to read ");
    Serial.println(numberOfBytesToRead);

    _i2cPort->requestFrom((uint8_t)_deviceAddress, (uint8_t)(numberOfBytesToRead + 4));
     
    if (waitForI2C() == false){
      Serial.println("recv wait for i2c failed");
    }
    else{Serial.println("recv data available");}
    
    //The first four bytes are header bytes and are throw away
    uint8_t scr_a = _i2cPort->read();
    uint8_t scr_b = _i2cPort->read();
    uint8_t scr_c = _i2cPort->read();
    uint8_t scr_d = _i2cPort->read();
    Serial.print("SCR_A ");  // scratch bytes
    Serial.println(scr_a);
    Serial.print("SCR_B ");
    Serial.println(scr_b);
    Serial.print("SCR_C ");
    Serial.println(scr_c);
    Serial.print("SCR_D ");
    Serial.println(scr_d);

    if ((scr_a==0xff)&(scr_b==0xff)&(scr_c==0xff)&(scr_c==0xff))
    {
      faultpacket=true;
    }
    
    for (uint8_t x = 0; x < numberOfBytesToRead; x++)
    {
      uint8_t incoming = _i2cPort->read();
      if (dataSpot < MAX_PACKET_SIZE)
      {
        shtpData[dataSpot++] = incoming; //Store data into the shtpData array
        Serial.print(x);
        Serial.print(" ");
        Serial.println(incoming);
      }
      else
      {
        Serial.print(x);
        Serial.print(" ");
        Serial.println(incoming);
      }  
    }

    if (faultpacket==false){bytesRemaining -= numberOfBytesToRead;}
    else{faultpacket=false;}
    
    Serial.println("bytes read");
  }
}

void loop() {
}

boolean waitForI2C()
{
  for (uint8_t counter = 0; counter < 100; counter++) //Don't got more than 255
  {
    if (_i2cPort->available() > 0)
      return (true);
      
    delay(1);
  }
  
  Serial.println("wait for I2C timeout");
  return (false); 
}
 
I made a slight modification to your sketch to see if it would get through:
Code:
#include <Wire.h>

TwoWire *_i2cPort;

uint8_t _deviceAddress;

//#include <SparkFun_BNO080_Arduino_Library.h>

//BNO080 IMU;
#define MAX_PACKET_SIZE 128
#define BNO080_DEFAULT_ADDRESS 0x4B
#define I2C_BUFFER_LENGTH 32
uint8_t data[32];

uint8_t shtpData[MAX_PACKET_SIZE];
uint8_t sequenceNumber[6] = {0, 0, 0, 0, 0, 0};

bool rslt;

void setup() {
  
  Serial.begin(9600);
  delay(500);
  Serial.println();
  Serial.println("Begin code");

  Wire.begin();
  Wire.setClock(100000);
  Serial.println("Wire begun");
  //delay(1000);
  //Begin
  uint8_t _deviceAddress = BNO080_DEFAULT_ADDRESS; //If provided, store the I2C address from user
  TwoWire &wirePort = Wire;
  _i2cPort = &wirePort;

  //Reset packet
  shtpData[0] = 1;

  //sendPacket
  uint8_t channelNumber = 1;
  uint8_t dataLength = 1;
  uint8_t packetLength = dataLength + 4;
  
  _i2cPort->beginTransmission(_deviceAddress);
  
  _i2cPort->write(packetLength & 0xFF);        //Packet length LSB
  _i2cPort->write(packetLength >> 8);         //Packet length MSB
  _i2cPort->write(channelNumber);           //Channel number
  _i2cPort->write(sequenceNumber[channelNumber]++);
  
  for (uint8_t i = 0; i < dataLength; i++)
  {
      _i2cPort->write(shtpData[i]);
  }
  Serial.println("Reset packet sent");
  
  if (_i2cPort->endTransmission() != 0)
  {
      Serial.println("End Trans Fail");
  }

  delay(1000);
  
  // receivePacket

  _i2cPort->requestFrom((uint8_t)_deviceAddress, (uint8_t)4);

  //waitForI2C

  if (waitForI2C() == true){Serial.println("Header Data available");}
  else{Serial.println("No Header Data available");}

  uint8_t packetLSBr = _i2cPort->read();
  Serial.print("LSB ");
  Serial.println(packetLSBr);
  uint8_t packetMSBr = _i2cPort->read();
  Serial.print("MSB ");
  Serial.println(packetMSBr);
  uint8_t channelNumberr = _i2cPort->read();
  Serial.print("CHN ");
  Serial.println(channelNumberr);
  uint8_t sequenceNumberr = _i2cPort->read(); //Not sure if we need to store this or not
  Serial.print("SQN ");
  Serial.println(sequenceNumberr);

  int16_t dataLengthr = ((uint16_t)packetMSBr << 8 | packetLSBr);
  dataLengthr &= ~(1 << 15); //Clear the MSbit.
  //This bit indicates if this package is a continuation of the last. Ignore it for now.
  //TODO catch this as an error and exit
  if (dataLengthr == 0)
  {
    //Packet is empty
    //return (false); //All done
    Serial.println("packet empty");
  }
  dataLengthr -= 4; //Remove the header bytes from the data count
  Serial.print("DATL ");
  Serial.println(dataLengthr);

  // getData
  uint16_t bytesRemaining = dataLengthr;
  uint16_t dataSpot = 0;
  bool faultpacket = false;
  
  while (bytesRemaining > 0)
  {
    uint16_t numberOfBytesToRead = bytesRemaining;
    if (numberOfBytesToRead > (I2C_BUFFER_LENGTH - 4))
      numberOfBytesToRead = (I2C_BUFFER_LENGTH - 4);
    Serial.print("Bytes to read ");
    Serial.println(numberOfBytesToRead);

    _i2cPort->requestFrom((uint8_t)_deviceAddress, (uint8_t)(numberOfBytesToRead + 4));

    for(int j = 0; j<(numberOfBytesToRead + 4); j++) {
      data[j]=_i2cPort->read();
      delay(1);
    }
    for(int j = 0; j<(numberOfBytesToRead + 4); j++) {
      Serial.println(data[j]);
    }

    if (waitForI2C() == false){
      Serial.println("recv wait for i2c failed");
    }
    else{Serial.println("recv data available");}
    
    //The first four bytes are header bytes and are throw away
    uint8_t scr_a = data[0];
    uint8_t scr_b = data[1];
    uint8_t scr_c = data[2];
    uint8_t scr_d = data[3];
    Serial.print("SCR_A ");  // scratch bytes
    Serial.println(scr_a);
    Serial.print("SCR_B ");
    Serial.println(scr_b);
    Serial.print("SCR_C ");
    Serial.println(scr_c);
    Serial.print("SCR_D ");
    Serial.println(scr_d);

    if ((scr_a==0xff)&(scr_b==0xff)&(scr_c==0xff)&(scr_c==0xff))
    {
      faultpacket=true;
    }
    
    for (uint8_t x = 4; x < numberOfBytesToRead; x++)
    {
      //uint8_t incoming = _i2cPort->read();
      if (dataSpot < MAX_PACKET_SIZE)
      {
        shtpData[dataSpot++] = data[x]; //Store data into the shtpData array
        Serial.print(x);
        Serial.print(" ");
        Serial.println(data[x]);
      }
      else
      {
        Serial.print(x);
        Serial.print(" ");
        Serial.println(data[x]);
      }  
    }

    if (faultpacket==false){bytesRemaining -= numberOfBytesToRead;}
    else{faultpacket=false;}
    
    Serial.println("bytes read");
  }
}

void loop() {
}

boolean waitForI2C()
{
  for (uint8_t counter = 0; counter < 100; counter++) //Don't got more than 255
  {
    if (_i2cPort->available() > 0)
      return (true);
      
    delay(1);
  }
  
  Serial.println("wait for I2C timeout");
  return (false); 
}
This is what I managed to get from the BNO080:
Code:
Begin code
Wire begun
Reset packet sent
Header Data available
LSB 20
MSB 1
CHN 0
SQN 0
DATL 272
Bytes to read 28
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
wait for I2C timeout
recv wait for i2c failed
SCR_A 255
SCR_B 255
SCR_C 255
SCR_D 255
4 255
5 255
6 255
7 255
8 255
9 255
10 255
11 255
12 255
13 255
14 255
15 255
16 255
17 255
18 255
19 255
20 255
21 255
22 255
23 255
24 255
25 255
26 255
27 255
bytes read
Bytes to read 28
20
1
0
0
0
1
4
0
0
0
0
128
6
49
46
48
46
48
0
2
2
0
1
3
2
255
127
4
2
0
1
5
wait for I2C timeout
recv wait for i2c failed
SCR_A 20
SCR_B 1
SCR_C 0
SCR_D 0
4 0
5 1
6 4
7 0
8 0
9 0
10 0
11 128
12 6
13 49
14 46
15 48
16 46
17 48
18 0
19 2
20 2
21 0
22 1
23 3
24 2
25 255
26 127
27 4
bytes read
Bytes to read 28
248
128
0
1
2
255
127
8
5
83
72
84
80
0
6
1
0
9
8
99
111
110
116
114
111
108
0
1
4
1
0
0
wait for I2C timeout
recv wait for i2c failed
SCR_A 248
SCR_B 128
SCR_C 0
SCR_D 1
4 2
5 255
6 127
7 8
8 5
9 83
10 72
11 84
12 80
13 0
14 6
15 1
16 0
17 9
18 8
19 99
20 111
21 110
22 116
23 114
24 111
25 108
26 0
27 1
bytes read
Bytes to read 28
220
128
0
2
0
8
11
101
120
101
99
117
116
97
98
108
101
0
6
1
1
9
7
100
101
118
105
99
101
0
1
4
wait for I2C timeout
recv wait for i2c failed
SCR_A 220
SCR_B 128
SCR_C 0
SCR_D 2
4 0
5 8
6 11
7 101
8 120
9 101
10 99
11 117
12 116
13 97
14 98
15 108
16 101
17 0
18 6
19 1
20 1
21 9
22 7
23 100
24 101
25 118
26 105
27 99
bytes read
Bytes to read 28
192
128
0
3
2
0
0
0
8
10
115
101
110
115
111
114
104
117
98
0
6
1
2
9
8
99
111
110
116
114
111
108
wait for I2C timeout
recv wait for i2c failed
SCR_A 192
SCR_B 128
SCR_C 0
SCR_D 3
4 2
5 0
6 0
7 0
8 8
9 10
10 115
11 101
12 110
13 115
14 111
15 114
16 104
17 117
18 98
19 0
20 6
21 1
22 2
23 9
24 8
25 99
26 111
27 110
bytes read
Bytes to read 28
164
128
0
4
0
6
1
3
9
12
105
110
112
117
116
78
111
114
109
97
108
0
7
1
4
9
10
105
110
112
117
116
wait for I2C timeout
recv wait for i2c failed
SCR_A 164
SCR_B 128
SCR_C 0
SCR_D 4
4 0
5 6
6 1
7 3
8 9
9 12
10 105
11 110
12 112
13 117
14 116
15 78
16 111
17 114
18 109
19 97
20 108
21 0
22 7
23 1
24 4
25 9
26 10
27 105
bytes read
Bytes to read 28
136
128
0
5
87
97
107
101
0
6
1
5
9
12
105
110
112
117
116
71
121
114
111
82
118
0
128
6
49
46
49
46
wait for I2C timeout
recv wait for i2c failed
SCR_A 136
SCR_B 128
SCR_C 0
SCR_D 5
4 87
5 97
6 107
7 101
8 0
9 6
10 1
11 5
12 9
13 12
14 105
15 110
16 112
17 117
18 116
19 71
20 121
21 114
22 111
23 82
24 118
25 0
26 128
27 6
bytes read
Bytes to read 28
108
128
0
6
48
0
129
100
248
16
245
4
243
16
241
16
251
5
250
5
252
17
239
2
1
10
2
10
3
10
4
10
wait for I2C timeout
recv wait for i2c failed
SCR_A 108
SCR_B 128
SCR_C 0
SCR_D 6
4 48
5 0
6 129
7 100
8 248
9 16
10 245
11 4
12 243
13 16
14 241
15 16
16 251
17 5
18 250
19 5
20 252
21 17
22 239
23 2
24 1
25 10
26 2
27 10
bytes read
Bytes to read 28
80
128
0
7
5
14
6
10
7
16
8
12
9
14
10
8
11
8
12
6
13
6
14
6
15
16
16
5
17
12
18
6
wait for I2C timeout
recv wait for i2c failed
SCR_A 80
SCR_B 128
SCR_C 0
SCR_D 7
4 5
5 14
6 6
7 10
8 7
9 16
10 8
11 12
12 9
13 14
14 10
15 8
16 11
17 8
18 12
19 6
20 13
21 6
22 14
23 6
24 15
25 16
26 16
27 5
bytes read
Bytes to read 28
52
128
0
8
19
6
20
16
21
16
22
16
23
0
24
8
25
6
26
0
27
0
28
6
29
0
30
16
31
0
32
0
wait for I2C timeout
recv wait for i2c failed
SCR_A 52
SCR_B 128
SCR_C 0
SCR_D 8
4 19
5 6
6 20
7 16
8 21
9 16
10 22
11 16
12 23
13 0
14 24
15 8
16 25
17 6
18 26
19 0
20 27
21 0
22 28
23 6
24 29
25 0
26 30
27 16
bytes read
Bytes to read 20
24
128
0
9
33
0
34
0
35
0
36
0
37
0
38
0
39
0
40
14
41
12
42
14
wait for I2C timeout
recv wait for i2c failed
SCR_A 24
SCR_B 128
SCR_C 0
SCR_D 9
4 33
5 0
6 34
7 0
8 35
9 0
10 36
11 0
12 37
13 0
14 38
15 0
16 39
17 0
18 40
19 14
bytes read
Not sure if this is what you were expecting or not. I need to go through the Spec to really sort it out.
 
Mine won't get here until Wednesday ;)
Needed to pick up a few more Qwiic things to try out once I build a board with connectors
 
That Qwiic is beginning to grow on me. I picked up one of the qwiic to dupont connector and works nice. As for the BNO080. Think I got it working. Not sure if its a problem with I2c or the how I2c works with the BNO080. After some minor reading of the 3 manuals for the BNO080 and adding some delays I did get it working:
Code:
BNO080 Read Example
sendPacket complete
I2C timeout
Softreset complete
Raw MEMS readings enabled
Output is: (accel) x y z (gyro) x y z (mag) x y z
0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	171	438	-395	
0	0	0	0	0	0	148	456	-407	
0	0	0	0	0	0	148	456	-407	
928	-1360	3536	0	0	0	148	456	-407	
928	-1360	3536	0	0	0	148	456	-407	
912	-1360	3536	0	0	0	148	456	-407	
912	-1360	3536	0	0	0	148	456	-407	
912	-1360	3536	0	0	0	166	444	-388	
912	-1360	3536	0	0	0	166	444	-388	
912	-1360	3536	-36	8	5	166	444	-388	
912	-1360	3536	-36	8	5	171	426	-370	
912	-1376	3520	-36	8	5	171	426	-370	
912	-1376	3520	-21	0	2	171	426	-370	
912	-1376	3520	-21	0	2	171	432	-388	
912	-1376	3520	-1	-9	0	171	432	-388	
912	-1376	3536	-1	-9	0	171	432	-388	
912	-1376	3536	-1	-9	0	171	450	-382	
912	-1376	3536	-1	-9	0	171	450	-382	
912	-1376	3536	-5	15	3	171	450	-382	
912	-1376	3536	-5	15	3	171	450	-382	
912	-1376	3536	-2	-9	0	171	450	-382	
912	-1376	3536	-2	-9	0	171	450	-382	
912	-1376	3536	-2	-9	0	160	438	-389	
912	-1376	3536	-2	-9	0	160	438	-389	
912	-1376	3536	-6	7	-1	160	438	-389	
912	-1376	3536	-6	7	-1	160	438	-389
Want to clean up the mess I made with the lib then I will post the updates. And before any one asks yes the data changes when I move the sensor around.
 
@KurtE and others
Attached is the updated .CPP file for the library. I just tested some of the other example sketches and the only one I am able to get to work is the rawdata one as shown in the previous post. In going through some of the documents wondering is this could be a problem:
The master device generally drives the clock. However, if the slave device requires additional time to respond it can force the clock low, only releasing the line when it is prepared to deliver more data. The master device MUST support clock stretching
 

Attachments

  • SparkFun_BNO080_Arduino_Library.zip
    9.7 KB · Views: 628
Morning All
Think last post on this until @KurtE gets one and tries it out. I did one more update tightening the delayMicroseconds in the sendpacket and receivepacket funtions and raw data sketch still works with no issue. I was able to get the other sketches running but found I had to add a delay(50) in the test for dataavailble. Example in the Quanternion sketch, this works:
Code:
/*
  Using the BNO080 IMU
  By: Nathan Seidle
  SparkFun Electronics
  Date: December 21st, 2017
  License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).

  Feel like supporting our work? Buy a board from SparkFun!
  https://www.sparkfun.com/products/14586

  This example shows how to output the timestamp for each reading.

  It takes about 1ms at 400kHz I2C to read a record from the sensor, but we are polling the sensor continually
  between updates from the sensor. Use the interrupt pin on the BNO080 breakout to avoid polling.

  Hardware Connections:
  Attach the Qwiic Shield to your Arduino/Photon/ESP32 or other
  Plug the sensor onto the shield
  Serial.print it out at 9600 baud to serial monitor.
*/

#include <Wire.h>

#include "SparkFun_BNO080_Arduino_Library.h"
BNO080 myIMU;

void setup()
{
  Serial.begin(9600);
  Serial.println();
  Serial.println("BNO080 Read Example");

  Wire.begin();

  myIMU.begin();
  Wire.setClock(400000); //Increase I2C data rate to 400kHz

  myIMU.enableRotationVector(50); //Send data update every 50ms

  Serial.println(F("Rotation vector enabled"));
  Serial.println(F("Output in form time, i, j, k, real, accuracy"));
}

void loop()
{
  //Look for reports from the IMU
  if (myIMU.dataAvailable() == true)
  {
    unsigned long timeStamp = myIMU.getTimeStamp();
    float quatI = myIMU.getQuatI();
    float quatJ = myIMU.getQuatJ();
    float quatK = myIMU.getQuatK();
    float quatReal = myIMU.getQuatReal();
    float quatRadianAccuracy = myIMU.getQuatRadianAccuracy();

    Serial.print(timeStamp);
    Serial.print(F(","));
    Serial.print(quatI, 2);
    Serial.print(F(","));
    Serial.print(quatJ, 2);
    Serial.print(F(","));
    Serial.print(quatK, 2);
    Serial.print(F(","));
    Serial.print(quatReal, 2);
    Serial.print(F(","));
    Serial.print(quatRadianAccuracy, 2);
    Serial.print(F(","));
    Serial.println();
    [COLOR="#FF0000"]delay(50);[/COLOR]
  }
}
Then I will get output:
Code:
BNO080 Read Example
sendPacket complete
Softreset complete
Rotation vector enabled
Output in form time, i, j, k, real, accuracy
0,0.00,0.00,0.00,0.00,0.00,
0,0.00,0.00,0.00,0.00,0.00,
0,0.00,0.00,0.00,0.00,0.00,
21,-0.17,-0.25,-0.86,0.40,0.07,
21,-0.17,-0.25,-0.86,0.40,0.06,
23,-0.17,-0.25,-0.86,0.40,0.05,
25,-0.17,-0.25,-0.86,0.40,0.05,
21,-0.17,-0.25,-0.86,0.40,0.05,
23,-0.17,-0.25,-0.86,0.40,0.04,
23,-0.17,-0.25,-0.86,0.41,0.04,
21,-0.17,-0.25,-0.86,0.41,0.04,
21,-0.17,-0.25,-0.86,0.41,0.04,

EDIT: OOPS - forgot the attachment...
 

Attachments

  • SparkFun_BNO080_Arduino_Library.zip
    9.7 KB · Views: 199
Last edited:
Wow! Many thanks for continuing to dig in on this. I had to keep my project going with an MPU-9250 over the weekend. Working to keep my options open as the BNO080 has many advantages.

I think you are on the right track with the quote in your earlier post. I think it's key that four good bytes arrive, and then 'dataavailable' fails.

I'll take a look at and try your code. I'm an interfacing hack, so it's unclear to me whether the solution is to find a way to reject the occasional 'dataavailable' fail and 0xFF packet, or wait to see if there is a solution for the low level.
 
@ckmiauto
What I put together was a kludge to see where the problems could be. They changes resolve the SYMPTOMS but not the underlining issue. The issue I think lies in the interface itself within the BNO080 and what I would call timing issues like I mentioned in post #18. I am not an I2C expert so just guessing here.
 
@mjs513 and @ckmiauto - Thought I would take a look as I now have one plugged into my T4 (with T3.6 foot print via FRDM), with QWIIC connector.

And the Wire Scanner program is finding it, so it looks like maybe I did not screw up the soldering.

So then I installed the Sparkfun BNO080 library (using Arduino library manager)... And tried the Example1-RotationVector and sure enough:
Code:
BNO080 not detected at default I2C address. Check your jumpers and the hookup guide. Freezing...

Next up - try bringing in part(or all) of @mjs513 changes - Right now doing quick compare of changes as not sure all of them are for fixing this, versus maybe library manager installed slightly different version... So maybe next step is to see what is up on github...
Forked - down loaded - compared the same... So will remove the arduino library download version...

Note: I am also not an expert in I2C, but will attempt to play some...

EDIT: I tried with all of the changes and it sill appears to not work...

Of course it could still be my Setup...
 
@KurtE

I downloaded directly from the Sparkfun GitHub for the repository. Start with sample sketch: Example 15-RawReadings.ino. That seemed to work for me right away after my changes. Just to make sure you have the right version of my mods: View attachment src.zip
 
@Kurte

Oops - forgot something. In the Sketch itself you may need to put a delay(50); in the imu.availiable (see post 19):
Code:
  if (myIMU.dataAvailable() == true)
  {
    float quatI = myIMU.getQuatI();
    float quatJ = myIMU.getQuatJ();
    float quatK = myIMU.getQuatK();
    float quatReal = myIMU.getQuatReal();
    float quatRadianAccuracy = myIMU.getQuatRadianAccuracy();

    Serial.print(quatI, 2);
    Serial.print(F(","));
    Serial.print(quatJ, 2);
    Serial.print(F(","));
    Serial.print(quatK, 2);
    Serial.print(F(","));
    Serial.print(quatReal, 2);
    Serial.print(F(","));
    Serial.print(quatRadianAccuracy, 2);
    Serial.print(F(","));
    Serial.println();

   delay(50);
  }
 
@mjs513 ...

At times I get responses, if I cold startup, other times, like download program again it looks like it hangs>
Code:
BNO080 Read Example
sendPacket complete
Softreset complete
Raw MEMS readings enabled
Output is: (accel) x y z (gyro) x y z (mag) x y z

I captured it with LA and output a CSV file:
Code:
Time [s],Packet ID,Address,Data,Read/Write,ACK/NAK
0.557318336000000,0,0x96,0x05,Write,ACK
0.557408332000000,0,0x96,0x00,Write,ACK
0.557498332000000,0,0x96,0x01,Write,ACK
0.557588332000000,0,0x96,0x00,Write,ACK
0.557678332000000,0,0x96,0x01,Write,ACK
0.608586148000000,,0x97,,Read,NAK
0.610681814000000,,0x96,,Write,NAK
0.610789484000000,,0x97,,Read,NAK
0.618875222000000,,0x96,,Write,NAK
0.626700596000000,,0x96,,Write,NAK
0.634525928000000,,0x96,,Write,NAK
0.642351302000000,,0x96,,Write,NAK
0.650176716000000,,0x96,,Write,NAK
0.658002132000000,,0x96,,Write,NAK
0.658030056000000,,0x97,,Read,NAK

That was it
And then I hit the program button, to program it again and then...

Code:
BNO080 Read Example
sendPacket complete
Softreset complete
Raw MEMS readings enabled
Output is: (accel) x y z (gyro) x y z (mag) x y z
0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	320	-604	-640	
0	0	0	0	0	0	320	-604	-640	
-2528	240	3248	0	0	0	320	-604	-640	
-2528	240	3248	0	0	0	320	-604	-640	
-2528	240	3248	0	0	0	320	-604	-640	
-2528	240	3248	0	0	0	320	-604	-640	
-2528	240	3248	-2	-8	0	320	-604	-640	
-2528	240	3248	-2	-8	0	331	-640	-628	
-2528	240	3248	-2	-8	0	331	-640	-628	
-2528	240	3248	-2	-8	0	331	-640	-628	
...
And as expected, lots more data...
Code:
Time [s],Packet ID,Address,Data,Read/Write,ACK/NAK
1.737349030000000,0,0x96,0x05,Write,ACK
1.737439862000000,0,0x96,0x00,Write,ACK
1.737529860000000,0,0x96,0x01,Write,ACK
1.737620528000000,0,0x96,0x00,Write,ACK
1.737710528000000,0,0x96,0x01,Write,ACK
[COLOR="#FF0000"]1.788746282000000,1,0x97,0x14,Read,ACK[/COLOR]
1.789063144000000,,0x50,,Write,NAK
1.891058724000000,,0x50,,Write,NAK
1.891260646000000,4,0x97,0x14,Read,ACK
1.891350646000000,4,0x97,0x01,Read,ACK
1.891444578000000,4,0x97,0x00,Read,ACK
1.891534562000000,4,0x97,0x00,Read,NAK
1.891914570000000,5,0x97,0x14,Read,ACK
1.892004560000000,5,0x97,0x81,Read,ACK
1.892094562000000,5,0x97,0x00,Read,ACK
1.892184562000000,5,0x97,0x01,Read,ACK
1.892274562000000,5,0x97,0x00,Read,ACK
1.892364562000000,5,0x97,0x01,Read,ACK
1.892456594000000,5,0x97,0x04,Read,ACK
1.892546562000000,5,0x97,0x00,Read,ACK
1.892636562000000,5,0x97,0x00,Read,ACK
1.892726562000000,5,0x97,0x00,Read,ACK
1.892816562000000,5,0x97,0x00,Read,ACK
1.892906560000000,5,0x97,0x80,Read,ACK
1.892996562000000,5,0x97,0x06,Read,ACK
1.893086562000000,5,0x97,0x31,Read,ACK
1.893176562000000,5,0x97,0x2E,Read,ACK
1.893266562000000,5,0x97,0x30,Read,ACK
1.893605714000000,5,0x97,0x2E,Read,ACK
1.893697904000000,5,0x97,0x30,Read,ACK
1.893787894000000,5,0x97,0x00,Read,ACK
1.893877894000000,5,0x97,0x02,Read,ACK
1.893967894000000,5,0x97,0x02,Read,ACK
1.894057894000000,5,0x97,0x00,Read,ACK
1.894147894000000,5,0x97,0x01,Read,ACK
1.894237892000000,5,0x97,0x03,Read,ACK
1.894327894000000,5,0x97,0x02,Read,ACK
...

Now to figure out differences?
 
Status
Not open for further replies.
Back
Top