Open DaudiGabriel opened 4 years ago
Hi @DaudiGabriel , Just an update to let you know that we are investigating this issue. I can replicate your issue using a SparkFun RedBoard (ATmega328P) and the following code:
#include <SPI.h>
#include "SparkFun_BNO080_Arduino_Library.h"
BNO080 myIMU;
//These pins can be any GPIO
byte imuCSPin = 10;
byte imuWAKPin = 9;
byte imuINTPin = 8;
byte imuRSTPin = 7;
unsigned long startTime; //Used for calc'ing Hz
long measurements = 0; //Used for calc'ing Hz
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println("BNO080 SPI Read Example");
myIMU.enableDebugging(Serial); //Pipe debug messages to Serial port
if(myIMU.beginSPI(imuCSPin, imuWAKPin, imuINTPin, imuRSTPin) == false)
{
Serial.println("BNO080 over SPI not detected. Are you sure you have all 6 connections? Freezing...");
while(1);
}
//You can also call begin with SPI clock speed and SPI port hardware
//myIMU.beginSPI(imuCSPin, imuWAKPin, imuINTPin, imuRSTPin, 1000000);
//myIMU.beginSPI(imuCSPin, imuWAKPin, imuINTPin, imuRSTPin, 1000000, SPI1);
//The IMU is now connected over SPI
//Please see the other examples for library functions that you can call
myIMU.enableRotationVector(10); //Send data update every 10ms
Serial.println(F("Rotation vector enabled"));
Serial.println(F("Output in form i, j, k, real, accuracy"));
startTime = millis();
}
void loop()
{
Serial.println("Doing other things");
delay(6); //You can do many other things. We spend most of our time printing and delaying.
//Look for reports from the IMU
if (myIMU.dataAvailable() == true)
{
float quatI = myIMU.getQuatI();
float quatJ = myIMU.getQuatJ();
float quatK = myIMU.getQuatK();
float quatReal = myIMU.getQuatReal();
float quatRadianAccuracy = myIMU.getQuatRadianAccuracy();
measurements++;
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.print((float)measurements / ((millis() - startTime) / 1000.0), 2);
Serial.print(F("Hz"));
Serial.println();
}
}
If I decrease the delay inside the loop to 5ms, the code works as expected. With the delay set to 6ms, the updates freeze after 1 or 2 seconds. I will keep investigating! Best wishes, Paul
I’m starting to understand this. If we set the enableRotationVector interval to 40ms or more, the BNO080 does not seem to care if we take more than 40ms to acknowledge the interrupt and read the data. If we set the interval to less than that, then it seems we MUST respond to the INT within one interval otherwise the BNO080 freezes. More investigation tomorrow...
The datasheet for the BNO080, in section 1.3.4.2, mentions that it may be necessary to wake the chip when communicating with it using SPI.
https://cdn.sparkfun.com/assets/1/3/4/5/9/BNO080_Datasheet_v1.3.pdf
I suspect that during the case that the loop is slower then the update rate that the chip puts itself to sleep. I have yet to discover a way to flat out disable this sleep method from the very beginning.
I do have some code though that I believe should wake the chip
For the .h file
void wake(); // Wake sensor up
For the .cpp file
void BNO080::wake() {
digitalWrite(_wake, LOW); // Begin Wake operation
if (_i2cPort == NULL) {
bool chipSelect = false;
for (int counter = 0; counter < 300; counter++)
{
if (digitalRead(_int) == LOW) {
digitalWrite(_cs, LOW);
chipSelect = true;
}
if (chipSelect && (digitalRead(_int) == HIGH)) {
break;
}
//if (_printDebug == true)
// _debugPort->println(F("SPI Wait"));
}
if (_printDebug == true && !chipSelect)
_debugPort->println(F("SPI INT timeout on wake"));
}
digitalWrite(_cs, HIGH);
digitalWrite(_wake, HIGH);
}
I attempted to use implement the above code with a smart waker system in my Arduino Sketch. However I have seen limited success. There is either an issue with the code above or my smart waker.
Also note to the original poster. I'm the Factorem guy who reported a similar issue in the Sparkfun forums. I thought I was done with the issue back then but looks like I have ran into it again. Just happened to be doing some searching on the web when I ran into your post on the pjrc forums. Noticed your post linked back to my original post on the issue and I felt compelled to give any assistance I could.
I spent today testing and can't seem to wake the chip back up. There is probably an issue with the wake code I provided. Will attempt to look into this again tomorrow.
Hi @FidencioYzaguirreIII ,
Thank you for your comments - they are very useful.
In the following plot: the purple trace is the SPI CS; the yellow trace is the INT signal. At the center of the trace, the BNO080 pulls INT low briefly but then it goes high again - returning to a voltage which is not quite as high as normal. The high state will cause dataAvailable
to return false.
My assumption was that a buffer was filling up, causing the BNO080 to go into some kind of error state. But sleep is a good explanation too. Except I cannot explain why the chip would go to sleep so soon after an SPI transfer?
I've attempted contacting CEVA, they now own Hillcrest Labs, to see if there is a way to disable the sleep function. If I get a response I will be sure to post about it. Also thank you for the oscilloscope data.
Thank you @FidencioYzaguirreIII & @DaudiGabriel , We have contacted Hillcrest Labs too. I will come back to you if they are able to offer any more advice. At the moment, our advice has to be: if you set the the Rotation Vector Report Interval to 10ms, you need to make sure that you are able to read it at that rate. Delaying the read on every second report seems to be acceptable, but delaying the read on every report does cause the SPI interface to lock up. We don't believe the BNO080 is going to sleep, an internal buffer filling up seems more likely. Best wishes, Paul
Found out the datasheet I was looking at was out of date.
Current Version https://www.ceva-dsp.com/wp-content/uploads/2019/10/BNO080_085-Datasheet.pdf
Turns out that there is a watchdog timer on the BNO080 that resets the sensor.
The BNO085 on the other hand will timeout and retry the operation. (Hint to Sparkfun make a BNO085 module) The BNO085 is suppose to be backwards compatible with the BNO080. The changes are for new software libraries.
Thanks all for the effort so far. At least I know now that I was not to stupid to connect the sensor the right way and that it is a sensor problem!
I am curious whether this problem also occurs when using I2C with the interrupt pin, but unfortunately I have no time to test this right now...
@DaudiGabriel I believe the issue will not occur on I2C from what I gather from the datasheet. Only issue will be dealing with the a speed bottleneck since SPI is faster then I2C.
We are now in contact with CEVA about this. More updates to follow soon!
We now understand more about what is happening to the chip. Being slow to read the SPI data does appear to be filling an internal buffer and causes the chip to perform a reset (“Initialize (unsolicited)”). At the moment, our advice is still: if you set the the Rotation Vector Report Interval to 10ms, you need to make sure that you are able to read it at that rate.
Hi @DaudiGabriel & @FidencioYzaguirreIII , CEVA have come back with more information about this issue. It is normal behavior for the BNO080 and is documented in section 1.2.4.1 of the datasheet:
printPacket
reveals this:
Header: 17 00 03 10 Body: FB 2B FF FF FF 05 10 01 00 7E 03 B5 04 48 DC C8 34 81 10 Length:23 Channel:Sensor-report
Header: 17 00 03 11 Body: FB 15 00 00 00 05 11 01 00 7F 03 B5 04 47 DC C7 34 83 10 Length:23 Channel:Sensor-report
Header: 17 00 03 12 Body: FB 17 00 00 00 05 12 01 00 7F 03 B5 04 48 DC C7 34 83 10 Length:23 Channel:Sensor-report
Header: 17 00 03 13 Body: FB D0 FF FF FF 05 13 01 00 7F 03 B6 04 47 DC C7 34 84 10 Length:23 Channel:Sensor-report
Header: 17 00 03 14 Body: FB 80 FF FF FF 05 14 01 00 80 03 B6 04 47 DC C7 34 86 10 Length:23 Channel:Sensor-report
Header: 17 00 03 15 Body: FB 7C FF FF FF 05 15 01 00 80 03 B6 04 48 DC C7 34 87 10 Length:23 Channel:Sensor-report
Header: 14 01 00 00 Body: 00 01 04 00 00 00 00 80 06 31 2E 30 2E 30 00 02 Length:276 Channel:Command
Header: 14 00 02 00 Body: F1 00 84 00 00 00 01 00 00 00 00 00 00 00 00 00 Length:20 Channel:Control
Header: 05 00 01 00 Body: 01 Length:5 Channel:Executable
The penultimate Control Channel packet (length 20 (4 + 16)) is a command response (0xF1) for command 0x84 which is “Initialize (unsolicited)”. The ultimate Executable Channel packet (length 5 (4 + 1)) is a “reset complete” (0x01).
This issue is now resolved - but I am going to leave it open and mark it as sticky to help future users with the same issue. Thank you again for your help on this. Best wishes, Paul
Subject of the issue
If the main loop evaluation time in an Arduino sketch is slightly larger than the update rate of the sensor, the Sensor will not report any updates via SPI any more. Not sure, whether this is a library problem or whether there is some internal (inside the BNO080) buffer overflow, which stops the sensor from working properly.
Your workbench
Steps to reproduce
Slightly modified version of SPI example "Example1-RotationVector"
//These pins can be any GPIO byte imuCSPin = 10; byte imuWAKPin = 14; byte imuINTPin = 16; byte imuRSTPin = 15;
unsigned long startTime; //Used for calc'ing Hz long measurements = 0; //Used for calc'ing Hz
void setup() { Serial.begin(115200); Serial.println(); Serial.println("BNO080 SPI Read Example");
if(myIMU.beginSPI(imuCSPin, imuWAKPin, imuINTPin, imuRSTPin) == false) { Serial.println("BNO080 over SPI not detected. Are you sure you have all 6 connections? Freezing..."); while(1); }
myIMU.enableRotationVector(10); //Send data update every 10ms
startTime = millis(); }
void loop() { Serial.println("Doing other things"); delay(9); //You can do many other things. We spend most of our time printing and delaying.
//Look for reports from the IMU if (myIMU.dataAvailable() == true) { measurements++;
} }
Expected behavior
Measurements over SPI should still be available
Actual behavior
Can not read any data from sensor