Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 2 1 2 LastLast
Results 1 to 25 of 48

Thread: Sparkfun BNO080 - Teensy 3.6 >> 4.0

  1. #1
    Junior Member
    Join Date
    Nov 2019
    Posts
    7

    Sparkfun BNO080 - Teensy 3.6 >> 4.0

    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...rduino_Library

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    10,093
    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
    
    // delay(1000); // 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?

  3. #3
    Junior Member
    Join Date
    Nov 2019
    Posts
    7
    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.

  4. #4
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,306
    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

  5. #5
    Junior Member
    Join Date
    Nov 2019
    Posts
    7
    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.

  6. #6
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,238
    maybe try increasing counter limit in waitForSPI() in sparkfun driver.

    could also experiment with running T4 @120mhz (IDE config option)

  7. #7
    Junior Member
    Join Date
    Nov 2019
    Posts
    7
    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...

  8. #8
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    10,093
    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.

  9. #9
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,306
    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.

  10. #10
    Junior Member
    Join Date
    Nov 2019
    Posts
    7
    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?

  11. #11
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    10,093
    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 by defragster; 11-08-2019 at 05:26 AM.

  12. #12
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,306
    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.

  13. #13
    Junior Member
    Join Date
    Nov 2019
    Posts
    7
    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); 
    }

  14. #14
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,306
    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.

  15. #15
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,306
    One more note there is a mbed library as well that would like to go over as well: https://os.mbed.com/users/MultipleMo...s/code/BNO080/

  16. #16
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,729
    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

  17. #17
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,306
    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.

  18. #18
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,306
    @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
    Attached Files Attached Files

  19. #19
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,306
    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();
        delay(50);
      }
    }
    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...
    Attached Files Attached Files
    Last edited by mjs513; 11-11-2019 at 02:53 PM.

  20. #20
    Junior Member
    Join Date
    Nov 2019
    Posts
    7
    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.

  21. #21
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,306
    @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.

  22. #22
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,729
    @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...

  23. #23
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,306
    @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: src.zip

  24. #24
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,306
    @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);
      }

  25. #25
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,729
    @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
    1.788746282000000,1,0x97,0x14,Read,ACK
    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?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •