Go Down

Topic: Guide to gyro and accelerometer with Arduino including Kalman filtering (Read 313 times) previous topic - next topic

beltran

hey Fabio!
sei fortissimo! :D grazie una cifra! :)

thanks a lot for providing the freeIMU library and hardware for the community

I was about to send you an email asking the following 2 questions.
- do you sell the freeIMU boards as well? I know sparkfun has a similar board but I was wandering how much would it cost to buy it off of you directly

- do you think that the IMU can be done on the lower level version without magnetometers?? Solving the yaw missing piece somehow and the drifting problem? From your thesis it seems possible, but on the discussions we've been having on this forum post it seems as there are some drifting problems or some information (yaw) which cannot be obtained.

grazie ancora / thanks a lot
ciao
b.






Fabio Varesano

Quote

I was about to send you an email asking the following 2 questions.
- do you sell the freeIMU boards as well? I know sparkfun has a similar board but I was wandering how much would it cost to buy it off of you directly


Yes, that's possible some time. I may have some spare prototypes. Please discuss this privately (mail me: fvaresano at yahoo dot it) as I don't want to pollute the thread with commercial stuff.

Quote

- do you think that the IMU can be done on the lower level version without magnetometers?? Solving the yaw missing piece somehow and the drifting problem? From your thesis it seems possible, but on the discussions we've been having on this forum post it seems as there are some drifting problems or some information (yaw) which cannot be obtained.


You can compute the orientation of an IMU (gyro+accelerometer) but you will have always small drifting on the yaw. You need a magnetometer to fix the yaw drifting.

These days, there is the very good HMC5883L magnetometer which costs about $2 raw, so, with such a  small increase in price, I wouldn't buy an IMU without a magnetometer.

Nex2k12

Thanks Fabio for a very useful thread. I've never implemented a software filter like this before and it's very interesting.

I have run into a problem in my project, though. When I move the x-axis from 180 to 0 degrees, and don't change the y-axis, the measured complimentary angle for y also changes due to the rotation about the y-axis.

This makes sense, since it rotates around the y-axis when the angle of x is changed. (See the complimentary filter formula) but obviously isn't desireable for a smooth tilt measurement.

Here's a processing screenshot. You can see the x-axis (red) spiking up and down from 90 degrees when the y-axis tilt is changed from 0-180 degrees and back.



Any ideas how to get around this?

I find that increasing the weight from 0.98 to 0.95 amplifies the problem, while decreasing from 0.98 allows noise to corrupt the measurement.

Is this just a side affect or is there a solution?

Fabio Varesano


Nex2k12

I'm using the complimentary filter, like yours, but I'm using I2C sensors so the code is a bit different.
Code: [Select]
void gyroRead(float vals[])
{
  //First data register
  int regAddress = 0x1D;
 
  int x, y, z;

  byte buffer[6];
  readFrom(addrGyro, regAddress, 6, buffer);

  vals[0] = (int)(((((int)buffer[0]) << 8) | buffer[1])/14.375);   
  vals[1] = (int)(((((int)buffer[2])<< 8) | buffer[3])/14.375);
  vals[2] = (int)(((((int)buffer[4]) << 8) | buffer[5])/14.375);

  vals[0] *= (-1);
  vals[2] *= (-1);

}

Code: [Select]
{
  //First data register
  int regAddress = 0x32;
 
  byte buffer[6];
  readFrom(addrAccel, regAddress, 6, buffer);
 
  vals[0] = ((((int)buffer[1]) << 8) | buffer[0]);
  vals[1] = ((((int)buffer[3])<< 8) | buffer[2]);
  vals[2] = ((((int)buffer[5]) << 8) | buffer[4]);
 
  vals[0] /= xAccSens;
  vals[1] /= yAccSens;
  vals[2] /= zAccSens;

  vals[0] *= (-1);
  vals[2] *= (-1);


}

Code: [Select]
void kalman(float accelVals[2], float gyroRate[2], float compAngle[2])
{
 //Vector for tilt from accelerometer only
 float r = sqrt((pow(accelVals[0], 2) + pow(accelVals[1], 2) + pow(accelVals[2], 2)));
 
 //Angles from x,y,z axis to R
 vectorAngle[0] = acos(accelVals[0]/r) * (180/pi);
 vectorAngle[1] = acos(accelVals[1]/r) * (180/pi);

 deltatime = millis()-time;
 time = millis();

 //Computed angle using accelerometer data and gyroscope rate of change.
 compAngle[0] = (0.98*(compAngle[0]+(gyroRate[0]*deltatime/1000)))+(0.02*(vectorAngle[0]));
 compAngle[1] = (0.98*(compAngle[1]+(gyroRate[1]*deltatime/1000)))+(0.02*(vectorAngle[1]));
}


accelVals array stores the x and y acceleration in g's
gyroRate is the x and y rotation in degrees/sec
vectorAngle is the angle between the axis and the R vector

I was thinking it may have something to do with the frequency of the loop. When I increase the frequency, the problem is not as severe. Unfortunately there is only so fast I can make it.

I've tried various values for the weighted average. There isn't really much margin for change from what I can see before bad things start happening.


Another idea I just had....I may be doing some funny things with the sign (positive/negative) of various angles and rates. I will look into this.

I'm not sure if I'm missing something here or not.

Go Up