Skip to content

Commit acad31a

Browse files
committed
Additional debug to help diagnose startup problems
1 parent a0316a0 commit acad31a

File tree

2 files changed

+88
-15
lines changed

2 files changed

+88
-15
lines changed

src/SparkFun_BNO080_Arduino_Library.cpp

+86-13
Original file line numberDiff line numberDiff line change
@@ -956,11 +956,23 @@ void BNO080::softReset(void)
956956

957957
//Read all incoming data and flush it
958958
delay(50);
959+
960+
if (_printDebug == true)
961+
_debugPort->println(F("softReset: first receivePacket"));
962+
959963
while (receivePacket() == true)
960964
; //delay(1);
965+
961966
delay(50);
967+
968+
if (_printDebug == true)
969+
_debugPort->println(F("softReset: second receivePacket"));
970+
962971
while (receivePacket() == true)
963972
; //delay(1);
973+
974+
if (_printDebug == true)
975+
_debugPort->println(F("softReset: complete"));
964976
}
965977

966978
//Set the operating mode to "On"
@@ -1320,11 +1332,13 @@ void BNO080::saveCalibration()
13201332

13211333
//Wait a certain time for incoming I2C bytes before giving up
13221334
//Returns false if failed
1323-
boolean BNO080::waitForI2C()
1335+
//See discussion at: https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/issues/3
1336+
//This function _should_ be unnecessary but communication with the BNO080 stalls without it...
1337+
boolean BNO080::waitForI2C(size_t expectedLength)
13241338
{
13251339
for (uint8_t counter = 0; counter < 100; counter++) //Don't got more than 255
13261340
{
1327-
if (_i2cPort->available() > 0)
1341+
if (_i2cPort->available() >= expectedLength) // Greater than should be impossible...
13281342
return (true);
13291343
delay(1);
13301344
}
@@ -1410,7 +1424,7 @@ boolean BNO080::receivePacket(void)
14101424
else //Do I2C
14111425
{
14121426
_i2cPort->requestFrom((uint8_t)_deviceAddress, (size_t)4); //Ask for four bytes to find out how much data we need to read
1413-
if (waitForI2C() == false)
1427+
if (waitForI2C((size_t)4) == false)
14141428
return (false); //Error
14151429

14161430
//Get the first four bytes, aka the packet header
@@ -1425,13 +1439,27 @@ boolean BNO080::receivePacket(void)
14251439
shtpHeader[2] = channelNumber;
14261440
shtpHeader[3] = sequenceNumber;
14271441

1442+
//After a softReset, the BNO can respond with a 'corrupt' packet where the length is huge
1443+
//and the channelNumber is invalid. Test channelNumber here:
1444+
if (channelNumber > CHANNEL_GYRO)
1445+
{
1446+
if (_printDebug == true)
1447+
{
1448+
_debugPort->print(F("receivePacket (I2C): invalid channelNumber: "));
1449+
_debugPort->println(channelNumber);
1450+
}
1451+
//return (false); <- Error - we should return(false) - but don't as it messes up softReset
1452+
}
1453+
14281454
//Calculate the number of data bytes in this packet
14291455
uint16_t dataLength = (((uint16_t)packetMSB) << 8) | ((uint16_t)packetLSB);
14301456
dataLength &= ~(1 << 15); //Clear the MSbit.
14311457
//This bit indicates if this package is a continuation of the last. Ignore it for now.
14321458
//TODO catch this as an error and exit
14331459

1434-
// if (_printDebug == true)
1460+
// if ((_printDebug == true)
1461+
// //&& (dataLength > 0) // Comment this line to avoid printing when dataLength is zero
1462+
// )
14351463
// {
14361464
// _debugPort->print(F("receivePacket (I2C): dataLength is: "));
14371465
// _debugPort->println(dataLength);
@@ -1444,7 +1472,7 @@ boolean BNO080::receivePacket(void)
14441472
}
14451473
dataLength -= 4; //Remove the header bytes from the data count
14461474

1447-
getData(dataLength);
1475+
getData(dataLength, channelNumber, sequenceNumber);
14481476
}
14491477

14501478
return (true); //We're done!
@@ -1453,10 +1481,14 @@ boolean BNO080::receivePacket(void)
14531481
//Sends multiple requests to sensor until all data bytes are received from sensor
14541482
//The shtpData buffer has max capacity of MAX_PACKET_SIZE. Any bytes over this amount will be lost.
14551483
//Arduino I2C read limit is 32 bytes. Header is 4 bytes, so max data we can read per interation is 28 bytes
1456-
boolean BNO080::getData(uint16_t bytesRemaining)
1484+
//Notes: getData is public and some users may be calling it directly? Unlikely, but even so...
1485+
// For backward compatibility, channelNumber and sequenceNumber will both default to 255 - instead of being mandatory
1486+
boolean BNO080::getData(uint16_t bytesRemaining, uint8_t channelNumber, uint8_t sequenceNumber)
14571487
{
14581488
uint16_t dataSpot = 0; //Start at the beginning of shtpData array
14591489

1490+
uint8_t expectedSequenceNumber = sequenceNumber + 1; // The expected sequence number for error checking
1491+
14601492
//Setup a series of chunked 32 byte reads
14611493
while (bytesRemaining > 0)
14621494
{
@@ -1465,14 +1497,54 @@ boolean BNO080::getData(uint16_t bytesRemaining)
14651497
numberOfBytesToRead = (I2C_BUFFER_LENGTH - 4);
14661498

14671499
_i2cPort->requestFrom((uint8_t)_deviceAddress, (size_t)(numberOfBytesToRead + 4));
1468-
if (waitForI2C() == false)
1469-
return (0); //Error
1500+
if (waitForI2C((size_t)(numberOfBytesToRead + 4)) == false)
1501+
return (false); //Error
1502+
1503+
//The first four bytes are header bytes and are throw away but lets use then for error checking
1504+
uint8_t packetLSB = _i2cPort->read();
1505+
uint8_t packetMSB = _i2cPort->read();
1506+
uint8_t thisChannelNumber = _i2cPort->read();
1507+
uint8_t thisSequenceNumber = _i2cPort->read();
1508+
1509+
//Calculate the number of data bytes in this packet
1510+
uint16_t dataLength = (((uint16_t)packetMSB) << 8) | ((uint16_t)packetLSB);
1511+
dataLength &= ~(1 << 15); //Clear the MSbit.
1512+
//This bit indicates if this package is a continuation of the last. Ignore it for now.
1513+
//TODO catch this as an error and exit
14701514

1471-
//The first four bytes are header bytes and are throw away
1472-
_i2cPort->read();
1473-
_i2cPort->read();
1474-
_i2cPort->read();
1475-
_i2cPort->read();
1515+
if (dataLength != (bytesRemaining + 4)) // Compensate for 4 header bytes
1516+
{
1517+
if (_printDebug == true)
1518+
{
1519+
_debugPort->print(F("getData: expected dataLength: "));
1520+
_debugPort->print(bytesRemaining);
1521+
_debugPort->print(F(" got: "));
1522+
_debugPort->println(dataLength);
1523+
}
1524+
//return (false); //Error
1525+
}
1526+
1527+
if (channelNumber != 255)// For backward compatibility channelNumber defaults to 255
1528+
{
1529+
if (thisChannelNumber != channelNumber)
1530+
{
1531+
if (_printDebug == true)
1532+
{
1533+
_debugPort->print(F("getData: unexpected channelNumber: "));
1534+
_debugPort->println(channelNumber);
1535+
}
1536+
//return (false); //Error
1537+
}
1538+
if (thisSequenceNumber != expectedSequenceNumber)
1539+
{
1540+
if (_printDebug == true)
1541+
{
1542+
_debugPort->print(F("getData: unexpected sequenceNumber: "));
1543+
_debugPort->println(sequenceNumber);
1544+
}
1545+
//return (false); //Error
1546+
}
1547+
}
14761548

14771549
for (uint8_t x = 0; x < numberOfBytesToRead; x++)
14781550
{
@@ -1487,6 +1559,7 @@ boolean BNO080::getData(uint16_t bytesRemaining)
14871559
}
14881560
}
14891561

1562+
expectedSequenceNumber++;
14901563
bytesRemaining -= numberOfBytesToRead;
14911564
}
14921565
return (true); //Done!

src/SparkFun_BNO080_Arduino_Library.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,10 @@ class BNO080
137137

138138
float qToFloat(int16_t fixedPointValue, uint8_t qPoint); //Given a Q value, converts fixed point floating to regular floating point number
139139

140-
boolean waitForI2C(); //Delay based polling for I2C traffic
140+
boolean waitForI2C(size_t expectedLength = 1); //Delay based polling for I2C traffic
141141
boolean waitForSPI(); //Delay based polling for INT pin to go low
142142
boolean receivePacket(void);
143-
boolean getData(uint16_t bytesRemaining); //Given a number of bytes, send the requests in I2C_BUFFER_LENGTH chunks
143+
boolean getData(uint16_t bytesRemaining, uint8_t channelNumber = 255, uint8_t sequenceNumber = 255); //Given a number of bytes, send the requests in I2C_BUFFER_LENGTH chunks
144144
boolean sendPacket(uint8_t channelNumber, uint8_t dataLength);
145145
void printPacket(void); //Prints the current shtp header and data packets
146146
void printHeader(void); //Prints the current shtp header (only)

0 commit comments

Comments
 (0)