Go Down

### Topic: Difficuly getting difference of MPU6050 values over time (Read 367 times)previous topic - next topic

#### eezJerome

##### Apr 18, 2019, 03:06 pm
Hello

So in a nutshell, I want to find the change of the raw values from my MPU6050 over some amount of sample time. I thought of applying a simple difference formula (x2 - x1, etc) but for some reason I am not getting anything useful. In more detail, the values I am working with are float type

Would love any help I can get

Code: [Select]
`// here i have previously declared values "realacc"// basically the raw values are converted to m/s2int sampletime = 50;void accel_getDelta() {  currenttime = millis();  float x1 = realaccx;  float y1 = realaccy;  float z1 = realaccz;  if (currenttime - prevtime > sampletime) {    float x2 = realaccx;    float y2 = realaccy;    float z2 = realaccz;    Serial.print(x2 - x1); Serial.print("\t  ");    Serial.print(y2 - y1); Serial.print("\t  ");    Serial.print(z2 - z1); Serial.print("\t");    Serial.println(" ");    prevtime = currenttime;  }}`

#### pylon

#1
##### Apr 18, 2019, 05:38 pm
First: post complete code!

I hope you see that in your code fragment you should get more or less an output of 0 because the time difference between the two measurements is only a few microseconds.

#### Idahowalker

#2
##### Apr 18, 2019, 06:27 pmLast Edit: Apr 18, 2019, 06:32 pm by Idahowalker
You are using which board?

from that code snippet, use micros() instead of millis().

I use an ESP32, the measurements and calculations take less then a mS, with interrupts on, I frequently get new triggers in less then a mS. Using mS that would give times of 0. Times of 0 in the MahonyQuaternionUpdate calculations, give wild fluctuations of data.

I use
Code: [Select]
` TimeNow = micros()/1000000.0f;        deltat = ( TimeNow - TimePast);` at the beginning of the loop but after a confirmed data read.

At the end of the code, I use
Code: [Select]
`TimePast = TimeNow;`

The variables are initialized with
Code: [Select]
`  float TimePast = micros()/1000000.0f;  float TimeNow = micros()/1000000.0f;`

#### eezJerome

#3
##### Apr 19, 2019, 10:25 am
First: post complete code!

I hope you see that in your code fragment you should get more or less an output of 0 because the time difference between the two measurements is only a few microseconds.
You are very right -- all I get is zero after zero. It's cool how you knew that

My code is messy but here:

Code: [Select]
`#include <I2Cdev.h>#include <MPU6050.h>// declaring sensor moduleMPU6050 mpu;// defining vars for raw valuesconst float g = 9.80665;int16_trawaccx, rawaccy, rawaccz,         rawgyrx, rawgyry, rawgyrz;floattime, prevtime, currenttime;int i;float pi = 180 / 3.141592654;//acceleration conversion factor; raw_value / 1671 = m/s2 valueconst int convraw = 1671;floatrealaccx, realaccy, realaccz;void setup() {  Wire.begin();  Serial.begin(115200);  mpu.initialize();  //  51  -40 -19 -4280  -3452 1475  mpu.setXGyroOffset(51); //this was at 220  mpu.setYGyroOffset(40); //76  mpu.setZGyroOffset(-19); //-85  //these are ones I put  mpu.setXAccelOffset(-4280);  mpu.setYAccelOffset(-3452);  mpu.setZAccelOffset(1475);  mpu.setDLPFMode(MPU6050_DLPF_BW_42); // 42hz digital low pass filter}void loop() {  mpu.getMotion6(&rawaccx, &rawaccy, &rawaccz, &rawgyrx, &rawgyry, &rawgyrz);  getaccel(rawaccx, rawaccy, rawaccz);  // just to print this function  getgyr(rawgyrx, rawgyry, rawgyrz);  //  Serial.print(realaccx); Serial.print(" \t");//  Serial.print(realaccy); Serial.print("      \t");//  Serial.print(realaccz); Serial.print("      \t"); //  accel_getDelta();}// converts raw accelerometer data to m/s/sfloat getaccel(float x, float y, float z) {  realaccx = x / convraw;  realaccy = y / convraw;  realaccz = z / convraw;}}int sampletime = 50; // arbitrary sample time value; was initially at 10 float accel_getDelta() {  currenttime = millis();  float x1 = realaccx;  float y1 = realaccy;  float z1 = realaccz;  if (currenttime - prevtime > sampletime) {    float x2 = realaccx;    float y2 = realaccy;    float z2 = realaccz;          Serial.print(x2 - x1); Serial.print("\t  ");      Serial.print(y2 - y1); Serial.print("\t  ");      Serial.print(z2 - z1); Serial.print("\t");      Serial.println(" ");  prevtime = currenttime;  }`

You are using which board?

from that code snippet, use micros() instead of millis().

I use an ESP32, the measurements and calculations take less then a mS, with interrupts on, I frequently get new triggers in less then a mS. Using mS that would give times of 0. Times of 0 in the MahonyQuaternionUpdate calculations, give wild fluctuations of data.

I use
Code: [Select]
` TimeNow = micros()/1000000.0f;        deltat = ( TimeNow - TimePast);` at the beginning of the loop but after a confirmed data read.

At the end of the code, I use
Code: [Select]
`TimePast = TimeNow;`

The variables are initialized with
Code: [Select]
`  float TimePast = micros()/1000000.0f;  float TimeNow = micros()/1000000.0f;`

I use Arduino Nano, and wow this seems very helpful. I'll implement this and report results.

#### eezJerome

#4
##### Apr 19, 2019, 11:21 amLast Edit: Apr 19, 2019, 12:01 pm by eezJerome
Alright so I implemented the micros() idea but I'm still getting a string of zeroes.

Here's how I did it; it's the same code as above except for this excerpt
Code: [Select]
` int sampletime = 5000; // changed to be for micros()float accel_getDelta() {  currenttime = micros()/1000000.0f;  float x1 = realaccx;  float y1 = realaccy;  float z1 = realaccz;  float deltat = (currenttime - prevtime);  // I really think the issue is in this if() statement; something doesnt seem right...  if (deltat > sampletime) {    Serial.print(realaccx - x1); Serial.print("\t  ");    Serial.print(realaccy - y1); Serial.print("\t  ");    Serial.print(realaccz - z1); Serial.print("\t  ");    Serial.println(currenttime); Serial.print("\t");    Serial.println(" ");    prevtime = currenttime;  }}`

#### Idahowalker

#5
##### Apr 19, 2019, 04:50 pm
Look at how to use millis() for timing and you should be able to see your issue.

#### jremington

#6
##### Apr 19, 2019, 05:15 pmLast Edit: Apr 19, 2019, 06:49 pm by jremington
Quote
it's the same code as above except for this excerpt
Same mistake. You read the acceleration, then read it again a microsecond later and print the difference.

Try something like this instead (but you REALLY SHOULD use long integer variables with millis() or micros()).

Code: [Select]
`float accel_getDelta() {  static float x1=0, y1=0, z1=0;  currenttime = micros()/1000000.0f;  float deltat = (currenttime - prevtime);  if (deltat > sampletime) {    prevtime = currenttime;    Serial.print(realaccx - x1); Serial.print("\t  ");    Serial.print(realaccy - y1); Serial.print("\t  ");    Serial.print(realaccz - z1); Serial.print("\t  ");    Serial.println(currenttime); Serial.print("\t");    Serial.println(" ");    x1 = realaccx;    y1 = realaccy;    z1 = realaccz;  }}`

Study this Blink without Delay tutorial.

#### eezJerome

#7
##### Apr 21, 2019, 11:31 pm
Same mistake. You read the acceleration, then read it again a microsecond later and print the difference.

Try something like this instead (but you REALLY SHOULD use long integer variables with millis() or micros()).

Code: [Select]
`float accel_getDelta() {  static float x1=0, y1=0, z1=0;  currenttime = micros()/1000000.0f;  float deltat = (currenttime - prevtime);  if (deltat > sampletime) {    prevtime = currenttime;    Serial.print(realaccx - x1); Serial.print("\t  ");    Serial.print(realaccy - y1); Serial.print("\t  ");    Serial.print(realaccz - z1); Serial.print("\t  ");    Serial.println(currenttime); Serial.print("\t");    Serial.println(" ");    x1 = realaccx;    y1 = realaccy;    z1 = realaccz;  }}`

Study this Blink without Delay tutorial.
I apologize for the late reply; I've been busy with other things. Thank you for the help, but this time there's nothing getting printed. The code provided by jremington does not print anything to the monitor.

For the time being I'll take the time to read over the tutorial as well as other related sources/codes.

Look at how to use millis() for timing and you should be able to see your issue.
I'll look into proper usage of timing. Thank you

#### eezJerome

#8
##### Apr 21, 2019, 11:57 pm
Alright so I did some reading over and I edited like one line of code from jremington. What I noticed is that removing the part with "1000000.0f" allows me to print my data, and it seems a bit iffy (because when I take raw values the differences are no greater than 0.01 due to filtering, among other things). It pretty much ruins the purpose of taking the change of the acceleration values if it's printing something like 0.3 differences.

Might it be that the decimals are shifted or something?

Here's what I used that "works"

Code: [Select]
`/*............................................*/unsigned long prevtime = 0;int sampletime = 50;long accel_getDelta(){  static long x1=0, y1=0, z1=0;  unsigned long currenttime = micros();//1000000.0f;  float deltat = (currenttime - prevtime);  if (deltat > sampletime){    prevtime = currenttime;        Serial.print(realaccx - x1); Serial.print("\t ");      Serial.print(realaccy - y1); Serial.print("\t ");    Serial.print(realaccz - z1); Serial.print("\t ");    Serial.println(currenttime); Serial.print("\t ");    Serial.println(" ");    x1 = realaccx;    y1 = realaccy;    z1 = realaccz;  }}`

#### jremington

#9
##### Apr 22, 2019, 01:30 amLast Edit: Apr 22, 2019, 01:38 am by jremington
Don't use floats or ints for time! Variables used with millis() and micros() should be unsigned long, including "sampletime".
Code: [Select]
` int sampletime = 50;... unsigned long currenttime = micros(); float deltat = (currenttime - prevtime); if (deltat > sampletime){`

It makes absolutely no sense to print every 50 microseconds, as printing a few characters takes milliseconds.

#### eezJerome

#10
##### Apr 22, 2019, 09:48 am
It makes absolutely no sense to print every 50 microseconds, as printing a few characters takes milliseconds.

Thanks for that note. I guess we've solved my issue. Thank you very much

Additionally, what would be a more appropriate sample time? I would like the lowest possible but anything you guys deem more useful and essentially better is welcome.

However, now i'm curious: is there a resource that can show me the execution time of Arduino? All I know is that since Arduino uses a 16MHz oscillator, that it can perform 16 million tasks a second [?]

#### jremington

#11
##### Apr 22, 2019, 04:50 pmLast Edit: Apr 22, 2019, 04:56 pm by jremington
The MPU6050 data sheet explains the available sample rates. This statement in your code limits the sample rate:
Code: [Select]
`mpu.setDLPFMode(MPU6050_DLPF_BW_42); // 42hz digital low pass filter`

The execution time of the Arduino is not the issue here, but the 16 MHz clock rate is the maximum number of machine instructions per second.

#### Idahowalker

#12
##### Apr 22, 2019, 05:51 pm
Do note, if you decide to use a data filter scheme that integrates time, such as a https://os.mbed.com/users/onehorse/ Sebastian Madgwick's open-source IMU fusion filter. You will want your uS or mS in a float format.

#### eezJerome

#13
##### Apr 23, 2019, 01:43 am
The MPU6050 data sheet explains the available sample rates. This statement in your code limits the sample rate:
Code: [Select]
`mpu.setDLPFMode(MPU6050_DLPF_BW_42); // 42hz digital low pass filter`

The execution time of the Arduino is not the issue here, but the 16 MHz clock rate is the maximum number of machine instructions per second.
Do note, if you decide to use a data filter scheme that integrates time, such as a https://os.mbed.com/users/onehorse/ Sebastian Madgwick's open-source IMU fusion filter. You will want your uS or mS in a float format.
All acknowledged, thank you very much!

Alright, one last question. I read here (http://www.chrobotics.com/library/accel-position-velocity) that even though I can gather data in very small time samples (theoretically), I am limited by the speed of how the serial monitor outputs the data. So basically, I might not really be reading data at a time interval I provided, rather it will be the bounds of the serial monitor I have to compensate for.

Thanks

#### jremington

#14
##### Apr 23, 2019, 04:20 amLast Edit: Apr 23, 2019, 04:20 am by jremington
Quote
I might not really be reading data at a time interval I provided
You need to write the program so that it reads samples at the correct intervals.

This is not a problem if you have read the MPU6050 data sheet carefully, and have set up the sensor appropriately.

Go Up