sparkfun / SparkFun_BNO080_Arduino_Library

An Arduino Library for the BNO080 IMU combination triple axis accelerometer/gyro/magnetometer packaged with an ARM Cortex M0+ running powerful algorithms.
Other
77 stars 62 forks source link

How to correctly query several types of information at a given rate, and know 1) which / 2) when ALL information types have been updated? #70

Closed jerabaul29 closed 3 years ago

jerabaul29 commented 3 years ago

I end up in situations where I need to query several streams of information at the same time. For example, both quaternion orientation and acceleration, to get acceleration in an absolute (East North Up) frame of reference, see some of the other discussions I have had today (in particular #65 ).

For this, I need to enable several streams, something like:

  bno080_imu.enableAccelerometer(imu_output_period_millis);
  bno080_imu.enableRotationVector(imu_output_period_millis);

However, I meet problems when using the way of checking for incoming data presented in the examples:

  if (bno080_imu.dataAvailable() == true){
      GRAB AND DO WORK
  }

Indeed:

So my questions are:

jerabaul29 commented 3 years ago

PS: could you provide an estimate of how long providing something like this may take? I have a hard deadline for developing a BNO080-based solution, with only a few days left. If it is too short for you to push something I will come up with a "hacky user-side solution", but would prefer to have something a bit clean :) .

jerabaul29 commented 3 years ago

To illustrate this issue, a small script (that I run on Artemis RedBoard):

#include "Arduino.h"
#include <Wire.h>
#include "SparkFun_BNO080_Arduino_Library.h"

BNO080 bno080_imu;

//------------------------------------------------------------------------
// some parameters
constexpr unsigned long imu_output_period_millis = 100;

//------------------------------------------------------------------------
void setup() {
  Serial.begin(230400);
  delay(10);
  Serial.println();
  Serial.println("---------- booted ----------");
  delay(10);

  Wire.begin();
  delay(50);

  Wire.setClock(400000);
  delay(50);

  bno080_imu.begin();
  delay(50);
  bno080_imu.enableDebugging(Serial);
  delay(50);

  bno080_imu.enableAccelerometer(imu_output_period_millis);
  bno080_imu.enableMagnetometer(imu_output_period_millis);
  bno080_imu.enableGyro(imu_output_period_millis);
  bno080_imu.enableRotationVector(imu_output_period_millis);
  delay(5000);

  Serial.println(F("sensor set up, start measuring"));
  Serial.println(F("the first measurements may be a bit off, the filter needs time to converge"));
}

//------------------------------------------------------------------------
void loop() {
  if (bno080_imu.dataAvailable() == true){
    Serial.println();
    Serial.print(F("ma: "));  // millis arrival
    Serial.println(millis());
  }
}

100 ms ie 10Hz output should be very much ok, far under what the datasheet mentions (should be possible to get down to 10ms i.e. 100 Hz on all these outputs according to Table 6-14 of the datasheet if I understand well).

However, the timing I get as output looks very confusing to me, see for example this small sample:

ma: 7324

ma: 7325

ma: 7344

ma: 7407

ma: 7409

ma: 7424

ma: 7425

ma: 7467

ma: 7506

ma: 7525

ma: 7526

ma: 7529

ma: 7592

ma: 7607

ma: 7624

ma: 7625

How should I understand that?

jerabaul29 commented 3 years ago

Looking at the equivalent library examples but from Adafruit (though I have the Sparkfun version of it):

https://github.com/adafruit/Adafruit_BNO08x/blob/master/examples/more_reports/more_reports.ino

They do have a way to see which kind of data just arrived:

https://github.com/adafruit/Adafruit_BNO08x/blob/51cd984ff220868f1f11b89201d356bce1f4b3b1/examples/more_reports/more_reports.ino#L147

As everything should be the same from a connection / sensor point of view, I may try their library :) .

jerabaul29 commented 3 years ago

Just FYI: I have got the SF Artemis + SF BNO080 on Qwiic to work with the Adafruit library, just for playing around. For those interested, the recipe is:

https://github.com/jerabaul29/Artemis_MbedOS_recipes/blob/main/recipes/recipe_IMU_BNO_Adafruit/recipe_IMU_BNO_Adafruit.ino

My conclusions so far by looking a bit at the code and outputs:

So the best solution is still to me if you could produce an output indicating which kind of packet has been received :) . May have a look at it myself tonight.

PaulZC commented 3 years ago

Hi JR, If you have the time to look at this - and send us a pull request - we will be very happy to merge it. So long as it maintains backward compatibility. We try to help users and respond to their requests as quickly as we can, but we do have finite resources and it may be a long time before we are able to look at this. You are - I believe - the only person to have asked for this feature. The quickest way forward for you - for now - will be to use the Adafruit library. Best wishes, Paul

jerabaul29 commented 3 years ago

I perfectly understand limited resources :) .

Ok, I will look a bit into the code and see if I can find a simple way to get this done :) . I let you know :) .

jerabaul29 commented 3 years ago

PS: I got some help on the Adafruit library repo, it is actually possible there to set the update rate too. I have limited time for developing my device, so may rather use their library for now and come back to this later.

jerabaul29 commented 3 years ago

@PaulZC excellent news: there is a simple fix :) .

Basically the isAvailable method is too coarse in which information it reports as discussed here (reports only that a packet has arrived, not what kind of packet), but it is just a thin wrapper around a function that does exactly what is needed: getReadings(). See:

https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/blob/a0316a0616edb29b4007dcce59d8e98c9e51f6c1/src/SparkFun_BNO080_Arduino_Library.cpp#L171-L176

vs

https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/blob/a0316a0616edb29b4007dcce59d8e98c9e51f6c1/src/SparkFun_BNO080_Arduino_Library.cpp#L178

which wraps:

https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/blob/a0316a0616edb29b4007dcce59d8e98c9e51f6c1/src/SparkFun_BNO080_Arduino_Library.cpp#L264

which returns the code we need. Also, the comments may be slightly misleading: these functions only parse 1 packet at a time, i.e. we get fine granularity about what data has come in, which is great :) .

So the trick is just to use getReadings(), and to check for the return code to know which data has arrived :) .

jerabaul29 commented 3 years ago

As a note, with this, my SF-code and quaternion-based recipe here: https://github.com/jerabaul29/Artemis_MbedOS_recipes/blob/main/recipes/recipe_IMU_quaternions/recipe_IMU_quaternions.ino seems to now work fine:

received data at ms: 190959 | type: gyro
received data at ms: 190961 | type: quat
received data at ms: 190963 | type: mag
received data at ms: 191072 | type: accel

millis start analysis: 191131
accel: -1.0859, 0.3008, 9.8594, pres: U | gyro: -0.0020, -0.0078, 0.0000, pres: U | mag: 11.1250, -12.8125, -26.5000, pres: M | quat: -0.0494, 0.0298, 0.9550, 0.2910, pres: H, 0.2175
quat: scal = 0.29 | vect = [ -0.05, 0.03, 0.95 ]
quat norm: 1.00
accel IMU frame of ref norm: 9.92
accel ENU frame of ref norm: 9.92
accel ENU: vect = [ -0.03, -0.00, 9.92 ]
IMU X-dir in ENU frame: vect = [ -0.83, 0.55, -0.11 ]
millis end: 191137 | analysis + print duration: 6

Truly in a hurry now, but when I am back from the ice (middle of March) we should discuss:

jerabaul29 commented 3 years ago

So feel free to either close, or keep open as a reminder that we may consider some addition to the examples and providing a few extra functionalities (maybe as an example too?).

PaulZC commented 3 years ago

Hi JR, This is good stuff - thank you. I'm very happy to leave this open until you have time to work on pull request. All the best, Paul

PaulZC commented 3 years ago

Hi JR, I think this issue has gone stale? Please do send us a separate Pull Request if you have the time. Best wishes, Paul

jerabaul29 commented 3 years ago

Yes, sorry, too much to do at work lately. It is on my todo list, but not sure when I will have time to fix it.

jerabaul29 commented 3 years ago

@PaulZC no pull request yet but what I have had time to do finally this WE is to clean a bit of my quaternion code and try to make it available as a standalone header-library that should be easy to use from Arduino. See: https://github.com/jerabaul29/kiss_clang_3d_utils . Given this library it should be a single function call to take care of the change of coordinates. I will try to find time for that next WE ^^ :) .

PaulZC commented 3 years ago

Thanks JR - best wishes, Paul