 # 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(" ");
}

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();
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();

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 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 -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

(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();
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
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.

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%