Guide to gyro and accelerometer with Arduino including Kalman filtering

Nice to hear you got it working :slight_smile:
Haha why exactly do you "love" the way I write? Be more specific, so I can do more of that in the future.
Normally I actually read a lot about the subject, before even hooking it up, so I got a understanding of what I am doing before I hook it up.

Lauszus:
Nice to hear you got it working :slight_smile:
Haha why exactly do you "love" the way I write? Be more specific, so I can do more of that in the future.
Normally I actually read a lot about the subject, before even hooking it up, so I got a understanding of what I am doing before I hook it up.

Since you asked, here is the truth :wink:
Your are quite expressive, your "reply" is to-the-point & brief and at the same time it contains all the nuts-n-bolts it needs to have to properly convey the message. Don't know if others have felt it or not, I do feel a "spread the knowledge" passion in your writing. Specially when you reposted the same article on Instructables with just this thought that "Many others can reach this too" .... It was great spirit.

Knowing something doesn't mean that one can convey it as well. That's a skill in its own. And I also felt the kindness in your tone as if you are really keen about other people to learn from you. You are not here to make high scores or just to be popular, rather you want to help others to know as much as you know.

Well, may be I am too sensitive to such things, but ya, I really feel if someone is making the difference.

Despite of the fact that you didn't have working knowledge with I2C, you pionted me to the correct location. What I do appreciate, is the thought behind such things. It's about creating a positive atmosphere, a friendly circle and it's just gives a lot of coooooool feeling.

What I will suggest is that please continue your passion of sharing. The killer combination is "Knowledge+Passion to share+Expression" and you have it all. Keep it up.

Oh ya, the reason I "experiment" first and "read" later is that, after I have a working model of that "something", it serves as an energy booster for me, telling me that "yes I can do it". Since I am not properly trained about electronics/physical computing and I have no one in access who can supervise me, so I do require a yard stick to find out if it's do-able by a hobyist or not. It's working for me so far :wink:

Guys, I am not paid for writing it all :wink: Lauszus really helped me a lot thru this forum and his articles. All of you who contribute to the community one way or the other, please keep doing so, .... you are doing a great job ... you may not realize ... but the person on the other side does!

Thank you for your kind words :smiley:
You should check out my blog: http://blog.tkjelectronics.dk/ , if you want to see what else I am doing.

Okay, seems logic. The problem is that I live in Denmark (Scandinavia), so almost all parts comes from the US or china, so it takes about 3-4 weeks for me to receive anything, if I just pay for standard shipping. So normally I just read a lot about it before I can get my hands on it :slight_smile:

I am currently working on a Quad flying machine and I am using the IMU (ArduIMU+ V2 (Flat) - DEV-09956 - SparkFun Electronics) with the magnetometer (Triple Axis Magnetometer Breakout - HMC5843 - SEN-09371 - SparkFun Electronics).
Currently I am working on the IMU with the magnetometer to give a precise reading to control the position of the flying machine. The problem I faced is that the readings from the IMU and the magnetometer will tend to drift and this will then lead to drift in the flying machine as well. I would like to know can I use your code including the Kalman filter to reduce the amount of drift overtime ? Thanks.

Yes you can!
The reason why you experience drift, is because the gyro tends to drift over time. To compensate for that you can either use the complementary filter or the Kalman filter. Have a look at the code taps "KalmanX" and "KalmanY". And line 151-152 in the main code:

compAngleX = (0.98*(compAngleX+(gyroXrate*dtime/1000)))+(0.02*(accXangle));
compAngleY = (0.98*(compAngleY+(gyroYrate*dtime/1000)))+(0.02*(accYangle));

Kk, will give it a try...

hello guys..im new here :slight_smile:
im currently doing my final year project about measuring tilt angle with gyro and accelerometer sensor..
im using IMU5DOF,kalman filter and arduino duemillanove..did u have the source code for connecting all this?
i hope that u guys can guide me :)tq

Yeah. Take a look at the bottom of the guide. Or click at this link: Arduino Forum

I would like to know how can I read raw ADC value of the accelerometer and the gyro from this IMU(ArduIMU+ V2 (Flat) - DEV-09956 - SparkFun Electronics)?

You should have a look at the code provided by Sparkfun: Google Code Archive - Long-term storage for Google Code Project Hosting. :slight_smile:

hi , before i get into my problem i would just like to thank "Lauszus " for this thread it has been a huge help. Im relatively new to Arduino and very new to posting my problems , so far i have been lucky and worked through all my problems by browsing through the forum but this time im stuck.

Im using a different gyro/acc combo board to the example (IMU Combo Board - 3 Degrees of Freedom - ADXL203/ADXRS614 - SEN-09249 - SparkFun Electronics) so ive had to change the sample code a fair bit and been debugging everything as i go. im only interested in solving in the X direction for my project and ive narrowed down my problem to this part of the program

R = sqrt(accXval);//the force vector
accXangle = (acos(accXval/R))*RAD_TO_DEG-90;

if(accXangle < 0)
{
accXangle = -180-accXangle;
}
else
{
accXangle = 180-accXangle;
}

When i debug accXangle with the code like this it seams to give me the number i expect to see , however when i run the debug part of the code further down

compAngleX = (0.98*(compAngleX+(gyroXratedtime/1000)))+(0.02(accXangle));
xAngle = kalmanCalculateX(accXangle, gyroXrate, dtime);

Serial.print("comp_angle");
Serial.print(compAngleX,0);Serial.print("\t");
Serial.print ("kalman");
Serial.println(xAngle,0);Serial.print("\t");

it returns only the value of "0" for both the comp_angle and xAngle i know my problem lies with accXangle because when i substitute in accXval the equations work (not giving anywhere the right answers but they do give me a reading )

any help you could all lend me would be tops, im sure there is a better way to post snipets of my code also but thats another thing im not yet sure how to do.

scrap that i figured it out because im only interested in one angle i dont need to include the force vector (R) or cos-1 (acos) now my code reads like this

accXadc = analogRead(aX);

accXval = (accXadc-accZeroX)/204.6;//(accXadc-accZeroX)/Sensitivity - in quids Sensitivity = 0.33/3.31023=102.3....204.6
accXangle = accXval
RAD_TO_DEG;

the program would reads zero when level but now for some reason my range reads

100........20..0.....20...100 (always giving a positive reading but zero when level), and when i debug accXangle it also only gives me positive readings

back to scratching my head lol

Are you sure your gyro reading are correct? You can not use a complimentary filter og kalman filter on only one of them, you need both to have a gyro reading (degrees/s) and a accelerometer reading (degrees).

You can not calculate the force vector using your IMU, as it only uses a dual axis accelerometer - you need three to calculate the force vector.

Instead you should calculate the angle using:

accXangle = asin(accXval)*RAD_TO_DEG;

If you then got the gyro reading (degrees/s), you can use the complimentary and the kalman filter provided :slight_smile:

hey , yea im definitely reading the gyro correctly and i substituted in the line of code u suggested everything is working including kalman complementary filter gyro and accelerometer!!! :slight_smile: ....except im still getting only positive value's from accXangle , however accXval is working perfectly with both negative and positive values . ive tried changing a few things but i don't seam to be getting anywhere

  accXadc = analogRead(aX);
  accXval = (accXadc-accZeroX)/102.3;//(accXadc-accZeroX)/Sensitivity - in quids              Sensitivity = 0.33/3.3*1023=102.3
  accXangle = asin(accXval)*RAD_TO_DEG;
 

    
  dtime = millis()-timer;
  timer = millis();
  
  compAngleX = (0.98*(compAngleX+(gyroXrate*dtime/1000)))+(0.02*(accXangle));
 
  xAngle = kalmanCalculateX(accXangle, gyroXrate, dtime);

First of all, you are using the wrong sensitivity. If you take a look at the datasheet: http://www.sparkfun.com/datasheets/Accelerometers/ADXL203.pdf you you will see that the sensitivity is 1000mV/g - translated into quids: 310 (1.000/3.3*1023=310).
Please post your code for the gyro readings as well and I will have a look at it :slight_smile:

I would like to know what does PX_00, KX_0, KX_1 under the Kalman section code represent ? Is it a representing as a form of matrix ?

float PX_00 = 0, PX_01 = 0, PX_10 = 0, PX_11 = 0;	
float KX_0, KX_1;

To be honest I really don't know. It's pretty complex mathematics. I just found a kalman filter used by another Arduino user (he also got it from some place else). But yes it represents a matrix.

here's a copy of my void loop , i had a look at my sensitivity values i think they r right now. My combo board uses 5v input.

void loop()
{
  gyroXadc = analogRead(gX);
  gyroXrate = (gyroXadc-gyroZeroX)/5.11;        //(gyroXadc-gryoZeroX)/Sensitivity - in quids       Sensitivity = 0.025/5*1023=5.11 
  gyroXangle += gyroXrate*dtime/1000;            //Without any filter
  
  accXadc = analogRead(aX);
  accXval = (accXadc-accZeroX)/204.6;             //(accXadc-accZeroX)/Sensitivity - in quids     Sensitivity = 1.00/5*1023=204.6 
  accXangle = asin(accXval)*RAD_TO_DEG;
 
  dtime = millis()-timer;
  timer = millis();
  
  compAngleX = (0.98*(compAngleX+(gyroXrate*dtime/1000)))+(0.02*(accXangle));
 
 
  xAngle = kalmanCalculateX(accXangle, gyroXrate, dtime);
  
  processing();
 
  delay(10);
  }
[code]

[/code]

It all looks correct. Have you tested it yet? :slight_smile:

yea thanks for all your help!!! , I'm pretty sure it is working correctly now i put a short video on you tube of my results in simplot if u r interested.