Guide to gyro and accelerometer with Arduino including Kalman filtering

Yes that is correct. You only have to change it, and then it will work.
What he call GAIN is just what I call sensitivity :slight_smile: Just replace sensitivity in my code with the values I provided in the previous post.
RATE is just how fast he wants to read the gyro and accelerometers.

oh so it was 2 ways of calling the same thing ;-). Thanx a lot.
I am gonna give it a try and keep you posted.

Ok, I am using the following values for Gyro and Accel sensitivity parameters
GYRO = 4.45625 ---- > (((14.375/1000) / 3.3) * 1023)
ACCEL = 79.36 ---- > (((256/1000) / 3.3) * 1023)

I took datasheet values (as per your last reply) and applied the formula you described in your article. Did I do it correctly?

I don't know whether I am getting correct results or not.
When IMU is lying horizontally, both X, Y axis reads 0 (with +-5 fluctuations)

  1. Shouldn't I get a steady angle with no fluctuations, bcoz I am already applying filter on it?.
  2. When I tilt it 90 degree along x-axis, I expect x-axis to read 90 degree but it gives 120 (+-5).
  3. When I tilt it around one axis, shouldn't the other axis remain constant? but it's changing too.

I am using Fabio's code to read the I2C sensor and then applying your algorithm to calculate the angle.
Kalman Filter or Complementary Filter, both are giving me more or less the same results.

Any advice?

It is a bit wrong. Your code should look something like this:

gyroYadc = readGyroX; //Read with I2C
gyroYrate = (gyroYadc-gyroZeroY)/14.375;

accYadc = readAccX; //Read with I2C
accYval = (accYadc-accZeroY)/256;

Then just calculate the angles as usual :slight_smile:

Thank you so much Lauszuz,

Finally my angles have started looking like "angles" :wink:

Though I noticed one thing, it takes it a while to get to the correct angle.
E.g. if I tilt the device slowly, all stays good but if i do it slightly faster, the change in values takes place gradually? (roughly 2+ seconds for getting down to 0 degree from 90 degree or vice versa) ... is that normal?

Is that both with the Kalman- and Complementary filter? Mine does that as well, but definitely not that slow.

Ok, so I've read nearly all of this thread and have a couple of questions.

In my understanding, you need 6dof (3accel, 3gyro) to be able to produce two absolute angles. The third angle is not possible to calculate at all? Or reliably due to gyro drift?

So if you add a magnetometer you can get 3 absolute angles?

If I have an ArduiMU (ArduIMU+ V2 (Flat) - DEV-09956 - SparkFun Electronics) (arduino + 3axis gyro + 3axis accel) can I add a manegometer that uses i2c and be able to spit out all the data to a computer? (without needing more analog ins).

Does it matter how many axis' the magnetometer has? (in order to calculate a third absolute angle)

Lastly, if the data is going to end up in a computer (running Max/MSP) is it better to do the math/calculations there rather than on the Arduino? Any benefit to doing the calculations locally on the Arduino?

Lauszus:
Is that both with the Kalman- and Complementary filter?

yup Kalman filter is giving much better results, so I have switched to that now.
One more thing I noticed, the moment X-axis angle starts to approach 90 degree and onwards, Y-axis angle suddenly goes crazy. And same is the case with X-axis angle when Y-axis starts to get near to 90 degree.

Is that due to my IMU or you are experiencing the simillar results with yours?

#kriista
You actually only need a 5DOF to calculate pitch and roll. You can even calculate it with a 4DOF, as you can just calculate the angle using sinus. No the third angle (yaw) is not precise due to gyro drift - but it can be calculate with some kind of filter. You need a magnetometer to calculate the last angle (yaw). Yes you can just use a I2C magnetomer with your board (ArduIMU+ V2 (Flat) - DEV-09956 - SparkFun Electronics). I am pretty sure that you need a 3-axis magnetometer to calculate the last angle - haven't tried it yet, as I do not own a magnetometer.
I your need is very time-critical, then it is better to do the calculation on the computer, as it got a lot more processing power than the Arduino. The good thing about doing it on the Arduino, is that you can easily hook it up to any program, with supports serial communication.

#Kashif
It is because you use 360 resolution. Just uncomment it if you need both angles :slight_smile:

It'd be for a musical performance setting, so latency is definitely undesirable.
I'm gonna try going with just the 6DOF and approximating the 3rd angle to see if that works, and if it doesn't I can add the magnetometer with i2c. I was initially worried that I had used up all my analog ins, so I didn't know this was a way around that.

Okay, please post your work when you are finished :slight_smile: It always nice to see what people come up with!

Will do, though it will be a while as I've not even sorted out the wireless and hardware assembly part....not to mention figuring out the math on the computer side, and then applying it to something meaningful etc...

But yeah, I'll post it.

Lauszus:
#Kashif
It is because you use 360 resolution. Just uncomment it if you need both angles :slight_smile:

uncomment what? I don't have anything commented out :wink: using ur code as-is, the only change i made was to read the I2C

This part: :smiley:

  if(accZval < 0)//360 degrees
  {
    if(accXangle < 0)
    {
      accXangle = -180-accXangle;
    }
    else
    {
      accXangle = 180-accXangle;
    }
    
    if(accYangle < 0)
    {
      accYangle = -180-accYangle;
    }
    else
    {
      accYangle = 180-accYangle;
    }    
  }

That's what I meant, this part is already uncommented. :wink:

@Kashif You have to comment (or delete) that part in order to use both axis without any problems, but it will only measure correctly from 90 to -90

If your filter is laggy, it might be because your gyro and accel signs do not match. Try inverting the gyro value passed to the filter. The filter should be fast - I use a 10ms update rate for my quadcopter and the filter is fast and smooth for pitch and roll.

With a mag, you will have to calculate the tilt compensated angle using either the raw pitch, roll data from the accel or pass in the filtered data to the mag filter with the gyro Z angle. However, depending on your mag, the update rate will be quite slow (10hz maybe). I haven't had much success Kalman filtering mag data. You might try using FreeIMU which uses a MARG algorithm to combine 9DOF data. It's faster than the kalman, but far more suseptable to vibration. Also, external magnetic influences may cause it to drift.

Make sure you calibrate your mag correctly so that you apply offsets to the mag outputs - otherwise you will never get reliable heading angles.

kriista:
Ok, so I've read nearly all of this thread and have a couple of questions.

In my understanding, you need 6dof (3accel, 3gyro) to be able to produce two absolute angles. The third angle is not possible to calculate at all? Or reliably due to gyro drift?

So if you add a magnetometer you can get 3 absolute angles?

If I have an ArduiMU (ArduIMU+ V2 (Flat) - DEV-09956 - SparkFun Electronics) (arduino + 3axis gyro + 3axis accel) can I add a manegometer that uses i2c and be able to spit out all the data to a computer? (without needing more analog ins).

Does it matter how many axis' the magnetometer has? (in order to calculate a third absolute angle)

Lastly, if the data is going to end up in a computer (running Max/MSP) is it better to do the math/calculations there rather than on the Arduino? Any benefit to doing the calculations locally on the Arduino?

cristo829:
@Kashif You have to comment (or delete) that part in order to use both axis without any problems, but it will only measure correctly from 90 to -90

Thanx Cristo829, I think Lauszus by mistake said "comment out", while he meant to "uncomment" :wink:
ya the angles seem ok now but only measuring +90 to -90

So, there is no way I can get a full 360 swing without compromising the other angle?

Lauszus, your code has helped me a lot reaching here, thats why I am sticking to this thread. Please be patient while I fire up some silly questions :wink: Once done, I will pass you my code which you can place along with the thread. It's all your code anyways just with the variation of I2C IMU, hope it will add more flavor to your article :wink:

OK guys, I am now starting my trial-n-error method once again to acheive the following

  1. be able to calculate 360 degree (or at least 180) accurately on both axis without making the other one go crazy.
  2. Remove (or at least minimize) the lag.

I really haven't got the time to play around with it :frowning: But if you succeed in getting 360 degrees resolution, please post the code, and I will update it :slight_smile:
I am thinking about buying a magnetometer, and update the guide, so one can calculate yaw as well. But that might be in the future, as I have so many things going on right now! :frowning:

I think you could minimize the lag, by doing something like this:

int STD_LOOP_TIME = 10;            
int lastLoopUsefulTime = STD_LOOP_TIME;
unsigned long loopStartTime = 0;

setup()
{
//some code
}
loop()
{
//Calculate the angles

lastLoopUsefulTime = millis()-loopStartTime;
if(lastLoopUsefulTime<STD_LOOP_TIME)         
    delay(STD_LOOP_TIME-lastLoopUsefulTime);
loopStartTime = millis();
}

Then it will only read the IMU every 10 ms - that might do the trick :slight_smile:

Hello,

i´ve got a question about the accelero angle calculation. i´m trying myself to calculate the accelero angles with a 3-axis accelerometer.

in my opinion your calcultion is wrong, because you use all three components fromthe accelero. because you want to calculate the angle on the y-axis for example you dont need data of the x-axis (it may cause a certain error).

Here:

R = sqrt(accXval2+accYval2+accZval2)

accYangle = acos(accYval/R)

So the accYangle contains information about the xAxis (accXval2) but you only need the vectorlength of the YZ-plane to compute the angle. or am i wrong ? i´m trying do get 360° angle calculaton, but i don't get results that arent jumping in some situations, where accZval2 is about zero .. :confused: tried tan/cos/scalarcos ... grrml ...

oh and thank you Lauszus for the tutorial :slight_smile:

greets

d0nut