hatt0002 Posted February 13, 2015 Report Share Posted February 13, 2015 Hi, I am currently doing a project in which I need to capture the acceleration of a pivoted rotating wooden beam. From the acceleration, I need to determine the velocity. I am using Jeff's teapot sketch with the mpu6050 and I have managed to also include the acceleration in the teapotPacket to print acceleration in processing. I know that velocity is the first integral of acceleration. Such integral can be expressed as:v = u + AT, where v is the current velocity, u is the velocity before, A is the acceleration and T is a time interval.This is my code for the velocities in the three directions with sampling time of 1ms: vX = uX + (AX)*0.001; //vX = current velocity in the X direction, uX = velocity in the previous iteration, AX = acceleration in the x direc uX = vX; //setting the current velocity as the previous velocity vY = uY + (AY)*0.001; uY = vY; vZ = uZ + (AZ)*0.001; uZ = vZ; If I move the sensor say in the x direction, acceleration in the x direction increases and when I stop the sensor, acceleration becomes negative and converges to zero, as expected. The velocity seems to be calculated and printed right when increasing from zero to a particular value. Now my problem is, that when I stop moving the sensor, velocity does not go back to zero when the sensor is stationary, but it decreases by a small amount only (say it stops decreasing at 0.5m/s. This gets worse when the sensor is moved faster. It seems like the acceleration is read more than the deceleration (decreasing acceleration) and therefore, less negative values for acceleration are captured. Can anybody help me?Thanks, Hatt Samellanak, Ekbergdub and Johnnydofs 3 Quote Link to comment Share on other sites More sharing options...
Kuba Posted February 19, 2015 Report Share Posted February 19, 2015 Unfortunately you cannot do much about it. It is a well known issue. A quote from wikipedia http://en.wikipedia.org/wiki/Inertial_navigation_system: All inertial navigation systems suffer from integration drift: small errors in the measurement of acceleration and angular velocity are integrated into progressively larger errors in velocity, which are compounded into still greater errors in position. You can find also useful information in this talk: Especially parts starting at 18:40 (single integration) and 23:40 (double integration). Quote Link to comment Share on other sites More sharing options...
hatt0002 Posted February 19, 2015 Author Report Share Posted February 19, 2015 Hi Kuba, Thankyou for your reply. I have done the following. I am saving the current acceleration, current velocity and previous velocity in arrays as follows; float [] AccX = new float[time]; //array for the current acceleration after sampling float [] AccY = new float[time]; float [] AccZ = new float[time]; float [] vXn = new float[time]; //array for the current velocity after integration float [] vYn = new float[time]; float [] vZn = new float[time]; float AccXn; //float for the current acceleration float AccYn; float AccZn; float v2XR; //float for the resulting velocity float v2YR; float v2ZR; float v2XP; //float for the previous velocity float v2YP; float v2ZP; float time = millis(); if(millis() % 1 == 0) //sampling at 1KHz { for(int n = 1; n<time; n++) //filling the arrays { AccX[n] = ActualAccelX2; //filling an array with current values of acceleration after sampling AccY[n] = ActualAccelY2; AccZ[n] = ActualAccelZ2; AccXn = AccX[n]; //saving the current vaue of the acceleration array as float for the integration AccYn = AccY[n]; AccZn = AccZ[n]; vXn[n] = vXn[n-1] + (AccX[n])*0.001; //integration v2XR = (vXn[n]); //saving the current resultant velocity as a float u2XP = vXn[n-1]; //saving the previous velocity as a float vYn[n] = vYn[n-1] + (AccY[n])*0.001; v2YR = (vYn[n]); u2YP = vYn[n-1]; vZn[n] = vZn[n-1] + (AccZ[n])*0.001; v2ZR = (vZn[n]); u2ZP = vZn[n-1]; } } This returns exactly what I want. When I move the sensor, acceleration increases and so the velocity. When I stop moving the motor, velocity decreases to zero exactly. However, after I saw the video you posted, I am confused whether I am taking the good approach or not. The results returned looks good after doing some reverse engineering with a calculator (shown in the attached screenshot). Please can you verify whether I am right or wrong? Thanks in advance, Hatt Quote Link to comment Share on other sites More sharing options...
Kuba Posted February 20, 2015 Report Share Posted February 20, 2015 Your code is very strange. The easiest way to do the integration is this: float velocity = 0; float currAccel; float prevAccel = 0; unsigned long prevTime = millis(); unsigned long currTime; void loop() { //other stuff //refresh currAccel currTime = millis(); velocity += (currAccel + prevAccel)/2*(currTime - prevTime)/1000; //1000 added to get the same units prevAccel = currAccel; prevTime = currTime; } But this will give you a "drift problem". The results won't be even close to good.That are my results. Sensor was not moving during data integration. As you can see the velocity is growing despite the fact that MPU was stationary. Quote Link to comment Share on other sites More sharing options...
hatt0002 Posted February 20, 2015 Author Report Share Posted February 20, 2015 I have tried something similar to your code earlier and I have noticed the velocity drift. In my latest code, I have the actual acceleration which is the acceleration minus gravity component rounded to 1 decimal place using nfc() multiplied by 9.81 to get real acceleration as follows; String AccelX2i = nfc(AccelX2, 1); //This rounds up the acceleration to 1 decimal place and therefore I will always get the same absolute value during acceleration and decelleration, thus perfect cancellation gravity2i[0] = nfc(gravity2[0], 1); //similar to previous line ActualAccelX2=(float(AccelX2i)-float(gravity2i[0]))*9.81; //this gives me the real acceleration By these three lines of code, I know I am reducing the accuracy of acceleration, but I am also eliminating the drift. Then I am sampling the ActualAccelX2 data and store it in an array whose size increases with time. Also I am creating another array for the velocity; float [] AccX = new float[time]; //array for the current acceleration after sampling float [] vXn2 = new float[time]; //array for the current velocity if(millis() % 1 == 0) //sampling at 1KHz { for(int n = 1; n<time; n++) { AccX2[n] = ActualAccelX2; //filling the array with the current accel vXn2[n] = vXn2[n-1] + (AccX2[n])*0.001; //vX2[n] is the current velocity, vX2[n-1] is the previous velocity and AccX2[n] is the current accel } } This returns exactly what I need, but I am not sure if it is giving the correct values or not. If it is correct, then the drift is eliminated since the velocity always converges to zero when the sensor is stationary and increases as I start moving the sensor.Thanks, Hatt. sidhulinux 1 Quote Link to comment Share on other sites More sharing options...
hedgehog_info Posted March 11, 2015 Report Share Posted March 11, 2015 hatt0002, I'm a newbie to the MPU6050 but was hoping you could elaborate on your code. Are you using AccelX2 as the true raw values from the accelerometer? nfc, is this a custom function I wasn't able to find anything about it gravity2, is this just gravity? If you would be so kind to explain a little more in detail about where the variables are coming from and what that first block of code is doing. I'm trying to get velocity which doesn't need to be super accurate and trying to figure RPM of my accelerometer that is spinning. Quote Link to comment Share on other sites More sharing options...
alex8toh Posted November 16, 2015 Report Share Posted November 16, 2015 yes, what is the nfc() function ? // do the integral thing ax = (float(aaWorld.x)/16384)*G; // convert to cm / s ay = (float(aaWorld.y)/16384)*G; Serial.print(ax); Serial.print("\t"); Serial.println(ay); vx = prevVx + ((prevAx+ax)/2)*dt; vy = prevVy + ((prevAy+ay)/2)*dt; prevPx = prevPx + ((prevVx+vx)/2)*dt; prevPy = prevPy + ((prevVy+vy)/2)*dt; prevVx = vx; prevVy = vy; prevAx = ax; prevAy = ay; I'm experiencing the drifting problem. Please advise ! Quote Link to comment Share on other sites More sharing options...
eron93br Posted November 17, 2015 Report Share Posted November 17, 2015 Hey alex8toh, are you using which code? Are you experiecing the driting problem with the code given by hatt0002? I need to do the same thing for a senior design project. Get the velocity from this MPU6050 sensor. Quote Link to comment Share on other sites More sharing options...
rookie Posted November 5, 2016 Report Share Posted November 5, 2016 Hello I am using MPU 5060 sensor to measure the speed of my car. I can get the acceleration values using the OUTPUT_READABLE_REALACCEL function in the MPU6050_DMP6 which gives out 3 axis acceleration. I am not sure how can use acceleration data to calculate the speed. I would appreciate any help. Quote Link to comment Share on other sites More sharing options...
Muon Nguyen Posted April 3, 2017 Report Share Posted April 3, 2017 hi, I think you can refer this video for this: Quote Link to comment Share on other sites More sharing options...
Unique Posted April 5, 2017 Report Share Posted April 5, 2017 The accelerometer's bias error is a very well-known problem. To fix it, just read its values for, say, 10 seconds. Calculate the average of the 10-second signal. This value is the bias value of your accelerometer. Before you calculate the velocity of the movement, subtract the bias error from the accelerometer's values. This should give you a cleaner velocity profile. Quote Link to comment Share on other sites More sharing options...
dicky Posted July 27, 2018 Report Share Posted July 27, 2018 hello everyone, i have a project using an adxl345 for measure vibration velocity. i had read any references about that said is possible. but i am beginner at arduino. i dont know how to get velocity data with accelerometer. can you guys help me. thanks anyway. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.