IMU calculating velocity

I'm using an MPU-9250 with a teensy 4.0 and am using my accelerometer to calculate the velocity of a rocket flight computer (and ideally the height reached any help on this would also be helpful) and i'm having issues.

I'm using the Suvat equation V = u + (a*dt) to calculate the velocity of the computer, however by leaving the computer/sensor upright and not moving the velocity consistently increases whether positive or negative acceleration/velocity making me think that the timing is affecting my calculated velocity as I assume it should stay or fluctuate around 0 m/s when stationary.

Here's the code i'm using

#include <Wire.h>
#include <SD.h>
#include "MPU9250.h"

MPU9250 IMU(Wire,0x68);
File DataFile;

int status;
float acceleration;
float constant;
float ACCX;
uint32_t Time;
float t;
float dt;

void setup() {
  Wire.setSCL(19);
  Wire.setSDA(18);
  Wire.begin();

  Serial.begin(9600);
  delay(1000);
  SD.begin(10);
    if (SD.begin(10))
  {
    Serial.println("SD card is present");
  }
  else
  {
    Serial.println("SD card missing or failure");
    while(1);
  }  if (SD.exists("IMU.txt"))
  {
    Serial.println("Clearing file");
    SD.remove("IMU.txt");
    Serial.print("Done");
    Serial.println(" ");
  }
  
  Serial.println("Accelerometer readings");
    status = IMU.begin();
  if (status < 0) {
    Serial.println("IMU initialization unsuccessful");
    Serial.println("Check IMU wiring or try cycling power");
    Serial.print("Status: ");
    Serial.println(status);
    while(1) {}
  }

//Take 10 g readings and find an average for g
//constant
int j;
constant = 0;
for (j = 0; j<100; j++) { 
    if (j>=0){            
      ACCX = IMU.getAccelX_mss();
      //HH = bmp.readAltitude(SEALEVELPRESSURE_HPA);
      constant = (constant + ACCX);
        }
      }
    constant = constant/(j);
    Serial.print("Average : "); Serial.println(constant, 16);
    delay(500);
    Time = millis();
    
  }
int i=0;
float u = 0;
float V;
float a;
float to = 0;

void loop() {
uint32_t now = (millis()-Time);
uint32_t secs = now / 1000;
uint32_t ms = now - (secs * 1000);
String TimeString;
  
  TimeString = String(secs);
  TimeString = TimeString + ".";
  if (ms < 100) {
    TimeString = TimeString + "0";
  }
  if (ms < 10) {
    TimeString = TimeString + "0";
  }
  TimeString = TimeString + String(ms);
 
  t = TimeString.toFloat();
  IMU.readSensor(),16;
   
   acceleration = IMU.getAccelX_mss(),16;
   a = acceleration - constant;
   Serial.print(TimeString); Serial.print(","); Serial.println(a);
  
   dt = t-to;
   V = u + (a*dt);
   //Flag to show that u is calculating correctly
   Serial.print(V); Serial.print(" m/s");Serial.print(u); Serial.print(" m/s"); Serial.print(" "); Serial.println(dt);
   
   u = V;
   to = t;
    V=0;
/* 
   DataFile = SD.open("IMU.txt", FILE_WRITE);
  
  if (DataFile){
  DataFile.print(t); DataFile.print(",");
  DataFile.println(a);
  DataFile.close();
  }  else 
    {
      Serial.println("error opening IMU.txt");
    }
*/
delay(100);
}

Any help would be appreciated, I know it's most likely poor coding from me but I just can't seem to get my head around it

-Harvey :slight_smile:

That's an unusual construct.

And again.

Yes my IMU has a resolution of 16 digits, I should have removed those parts before I posted the code, nevertheless it works the same :slight_smile:

-Harvey

I assume you mean bits (binary digits).

Maybe you could post your corrected code, so we're not chasing our tails.

My accelerometer is 16 bits, I was just saying it for ease as 9.81... goes to 15 decimal places and 10.12345... goes to 14 decimal places.

The code works with or with the ",16" so any help towards actually solving the issues with my code would be more appreciated thanks

You're using floats (32 bit), not doubles (64 bit)

I’m not sure how that helps my issue
The variable constant is a float and gives me a value to 15 d.p

I understand the code isn’t perfect but this is not the issue I need help with, I need help with calculating the velocity

You're deluded, or you don't understand 32 bit IEEE-754.
Or both.

Could you please only comment meaningful posts that actually contribute something useful to my problem thank you.

Only people that can actually help and understand my problem should be posting advice, not those chasing their own tails over a minor error.

Again thanks -Harvey

On the subject of tail-chasing, I asked to see the corrected code.

Over to you.

(What's not meaningful about you not understanding 32 bit floats?)

Sorry if I wasn't clear or didn't explain myself clearly - the code as it is works. No compiler errors/messages, no clear and obvious mistakes from me (Hopefully).

The code works, with or without the ",16". Remove them if you want when you copy the code, it literally makes no difference to the issue that I am having. If you would like to further "fix" the issue of me not understanding 32 bit floats, feel open to create a new discussion elsewhere but for now I need help with calculating the velocity of my IMU.

Please don't comment any more unhelpful comments unless it is directly helping my issue with the velocity.
thanks - Harvey

How about telling us more about the libraries you're using?

(I can write lots of code that won't give error messages or warnings, but won't do what they look like they ought to)

#include <Wire.h>
#include <SD.h>
#include "MPU9250.h"

Is this not clear?

I know my code doesn't work as it is ought to, that's why I'm on here asking for help.
-Harvey

Could you clarify this condition. Is your sensor stationary?
Can you print out the raw Accelerometer values?
Is stationary an acceleration of 1? (i.e. gravity).

My experience with this type of problem is it is best to remove all calculation and unneeded code and work with the raw numbers and little other code.

No, which is why I asked.

Which "MPU9250.h" ?

int j;
constant = 0;
for (j = 0; j<100; j++) { 
    if (j>=0){            
      ACCX = IMU.getAccelX_mss();
      //HH = bmp.readAltitude(SEALEVELPRESSURE_HPA);
      constant = (constant + ACCX);
        }
      }
    constant = constant/(j);

This is crazy - why the "if (j >= 0)" ?
What is the value of j at the end of the loop?
Why the expectation that 16 decimal places is achievable, or desirable?

@JohnRob
So my sensor starts stationary (Holding it upright in my hand as still as possible, which is not ideal but gets the job done) which takes 100 readings and gives me an average for my calculated "g" as the sensor isn't perfect nor accurate enough to get close to the true value of g.
Here is my raw outputs
{
SD card is present
Accelerometer readings
Average : 9.946030616760253 //This is the "g" that I take away from the accelerometer readings to find delta Acceleration
0.000,0.03
0.00 m/s0.00 m/s 0.00
0.101,0.01
0.00 m/s0.00 m/s 0.10
0.202,0.00
0.00 m/s0.00 m/s 0.10
0.302,0.02
}
The format of the outputs is messy but
{
Time, Acceleration in the x-axis (After "g" is removed)
Current Velocity, Initial Velocity(Previous V), delta T (Just a sanity check to make sure the time periods are the same).
}

I have tried doing some sharp sort of thrusts upwards with the board which creates a change in the readings
{
0.704,6.08 (Time , acceleration)
0.58 m/s-0.03 m/s 0.10 (V, u, dT)
0.805,7.61
1.35 m/s0.58 m/s 0.10
0.905,4.13
1.76 m/s1.35 m/s 0.10
1.006,0.07
1.77 m/s1.76 m/s 0.10
1.107,-11.60
0.60 m/s1.77 m/s 0.10
1.207,-10.72
}
but after I bring the board back to stationary the velocity slowly, and uniformly, increases without any/much disturbance

{
2.615,0.02
-1.54 m/s-1.54 m/s 0.10
2.715,0.04
-1.54 m/s-1.54 m/s 0.10
2.816,0.03
-1.53 m/s-1.54 m/s 0.10
2.917,0.00
-1.53 m/s-1.53 m/s 0.10
3.017,0.02
-1.53 m/s-1.53 m/s 0.10
3.118,0.04
-1.53 m/s-1.53 m/s 0.10
3.218,-0.05
-1.53 m/s-1.53 m/s 0.10
3.319,0.01
-1.53 m/s-1.53 m/s 0.10
3.419,0.03
-1.53 m/s-1.53 m/s 0.10
3.520,0.14
-1.51 m/s-1.53 m/s 0.10
3.620,0.15
-1.50 m/s-1.51 m/s 0.10
3.721,0.04
-1.49 m/s-1.50 m/s 0.10
3.822,0.03
-1.49 m/s-1.49 m/s 0.10
3.922,0.01
-1.49 m/s-1.49 m/s 0.10
4.023,-0.07
-1.50 m/s-1.49 m/s 0.10
4.123,0.03
-1.49 m/s-1.50 m/s 0.10
4.224,0.04
-1.49 m/s-1.49 m/s 0.10
4.324,-0.03
-1.49 m/s-1.49 m/s 0.10
4.425,0.27
-1.46 m/s-1.49 m/s 0.10
}
This was after it was back at stationary

is using 15 d.p too accurate which is causing the change in acceleration and a constant change to the velocity, or is it being rounded which could be altering the calculated velocity.

I used this page as help

Thank you -Harvey

sp. "which takes 100 readings, sums them, then divides by 101" (despite what the comment says)

Yes, because with a 32 bit IEE-754 floating point value you can expect no more than 6 or 7 significant decimals.
(Back-of-a-beermat calculation: 32 bit IEEE-754 has a mantissa of 23 bits. log10 223 = 6.924)

I guess I'm confused how you get "9.946030616760253" from 100 samples of 16 bit numbers (i.e. uint from 0 to 65536)

I think you should capture the RAW accelerometer and do the calculations by hand (or excel etc). This will allow you to see what is going on.

TheMemberFormerlyKnownAsAWOL:
You're deluded, or you don't understand 32 bit IEEE-754.

I think what the poster was trying to say is the precision your input variables does not support that many decimal places.
For instance: I have a sensor that has an accuracy of +/- 1%
I capture 3 readings 3,4,3
Average = 3.33333333333333333333333333333333333333333

But no digit after 2 places (at best) is meaningful because the error of a sensor could be +/- 0.03

I will admit I did not delve into the details of the MPU9350.

@JohnRob
So is it best to keep my recordings to 2 d.p, the sensor offers up to 16 d.p of precision so that's just what did for my program.

I've looked online for the accuracy of the MPU 9250 but couldn't really find much on the data sheets so I'm just going to use 2 d.p for now and test again.

However I do print the variable "constant" to ",16" but I'm not sure to which d.p is used in calculations during the Suvat equation.