@@ -956,11 +956,23 @@ void BNO080::softReset(void)
956
956
957
957
// Read all incoming data and flush it
958
958
delay (50 );
959
+
960
+ if (_printDebug == true )
961
+ _debugPort->println (F (" softReset: first receivePacket" ));
962
+
959
963
while (receivePacket () == true )
960
964
; // delay(1);
965
+
961
966
delay (50 );
967
+
968
+ if (_printDebug == true )
969
+ _debugPort->println (F (" softReset: second receivePacket" ));
970
+
962
971
while (receivePacket () == true )
963
972
; // delay(1);
973
+
974
+ if (_printDebug == true )
975
+ _debugPort->println (F (" softReset: complete" ));
964
976
}
965
977
966
978
// Set the operating mode to "On"
@@ -1320,11 +1332,13 @@ void BNO080::saveCalibration()
1320
1332
1321
1333
// Wait a certain time for incoming I2C bytes before giving up
1322
1334
// 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)
1324
1338
{
1325
1339
for (uint8_t counter = 0 ; counter < 100 ; counter++) // Don't got more than 255
1326
1340
{
1327
- if (_i2cPort->available () > 0 )
1341
+ if (_i2cPort->available () >= expectedLength) // Greater than should be impossible...
1328
1342
return (true );
1329
1343
delay (1 );
1330
1344
}
@@ -1410,7 +1424,7 @@ boolean BNO080::receivePacket(void)
1410
1424
else // Do I2C
1411
1425
{
1412
1426
_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 )
1414
1428
return (false ); // Error
1415
1429
1416
1430
// Get the first four bytes, aka the packet header
@@ -1425,13 +1439,27 @@ boolean BNO080::receivePacket(void)
1425
1439
shtpHeader[2 ] = channelNumber;
1426
1440
shtpHeader[3 ] = sequenceNumber;
1427
1441
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
+
1428
1454
// Calculate the number of data bytes in this packet
1429
1455
uint16_t dataLength = (((uint16_t )packetMSB) << 8 ) | ((uint16_t )packetLSB);
1430
1456
dataLength &= ~(1 << 15 ); // Clear the MSbit.
1431
1457
// This bit indicates if this package is a continuation of the last. Ignore it for now.
1432
1458
// TODO catch this as an error and exit
1433
1459
1434
- // if (_printDebug == true)
1460
+ // if ((_printDebug == true)
1461
+ // //&& (dataLength > 0) // Comment this line to avoid printing when dataLength is zero
1462
+ // )
1435
1463
// {
1436
1464
// _debugPort->print(F("receivePacket (I2C): dataLength is: "));
1437
1465
// _debugPort->println(dataLength);
@@ -1444,7 +1472,7 @@ boolean BNO080::receivePacket(void)
1444
1472
}
1445
1473
dataLength -= 4 ; // Remove the header bytes from the data count
1446
1474
1447
- getData (dataLength);
1475
+ getData (dataLength, channelNumber, sequenceNumber );
1448
1476
}
1449
1477
1450
1478
return (true ); // We're done!
@@ -1453,10 +1481,14 @@ boolean BNO080::receivePacket(void)
1453
1481
// Sends multiple requests to sensor until all data bytes are received from sensor
1454
1482
// The shtpData buffer has max capacity of MAX_PACKET_SIZE. Any bytes over this amount will be lost.
1455
1483
// 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)
1457
1487
{
1458
1488
uint16_t dataSpot = 0 ; // Start at the beginning of shtpData array
1459
1489
1490
+ uint8_t expectedSequenceNumber = sequenceNumber + 1 ; // The expected sequence number for error checking
1491
+
1460
1492
// Setup a series of chunked 32 byte reads
1461
1493
while (bytesRemaining > 0 )
1462
1494
{
@@ -1465,14 +1497,54 @@ boolean BNO080::getData(uint16_t bytesRemaining)
1465
1497
numberOfBytesToRead = (I2C_BUFFER_LENGTH - 4 );
1466
1498
1467
1499
_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
1470
1514
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
+ }
1476
1548
1477
1549
for (uint8_t x = 0 ; x < numberOfBytesToRead; x++)
1478
1550
{
@@ -1487,6 +1559,7 @@ boolean BNO080::getData(uint16_t bytesRemaining)
1487
1559
}
1488
1560
}
1489
1561
1562
+ expectedSequenceNumber++;
1490
1563
bytesRemaining -= numberOfBytesToRead;
1491
1564
}
1492
1565
return (true ); // Done!
0 commit comments