## Introduction: Guide to Gyro and Accelerometer With Arduino Including Kalman Filtering

This guide was first posted at the Arduino forum, and can be found here: http://arduino.cc/forum/index.php/topic,58048.0.html

I just reposted it, so even more will get use of it. The code can be found here:

https://github.com/TKJElectronics/Example-Sketch-for-IMU-including-Kalman-filter

Hallo everybody

I recently bought this analog 6DOF (six degrees of freedom) IMU board (http://www.sparkfun.com/products/10010) from watterott.com. It uses three gyros and three accelerometers to calculate angles in three dimensions.

I looked a while for some code online and how to connect with them. After many hours of research I succeeded of making af precise measurement of angles in two directions. I decided to write a short guide for fellow electronic enthusiasts.

The main purpose of this guide is to teach others how to get some useful data from their IMU or just a gyro or accelerometer. The code for Arduino can be found at github: https://github.com/TKJElectronics/Example-Sketch-for-IMU-including-Kalman-filter. It should be pretty easy to implement my code to your own sensor. I will not describe all the details about the theory behind, instead you can look at the sources for more info.

Before you begin you have to connect the IMU as follows:

Acc_Gyro Arduino

3.3V <—> 3.3V

GND <—> GND

Gx4 X <—> AN0

Gx4 Y <—> AN1

Gx4 Z <—> AN2

Acc X <—> AN3

Acc Y <—> AN4

Acc Z <—> AN5

Also connect 3.3V to the AREF pin on the Arduino for more accuracy.

It is

Now your are ready for reading some data from the sensor.

To communicate with the sensor is straightforward:

The gyro measures degrees per second while the accelerometer measures acceleration (g's) in three dimensions. Both outputs the measurements as a analog signal.

To get these translated into degrees you have to do some coding:

First you have to translate quids (a number from 0-1023) into something useful (this is for a ADC with a 10 bit resolution, for example this should be 4095 (2^12-1=4095) for 12 bit ADC). To do this I just use this simple equation:

gyroRate = (gyroAdc-gyroZero)/sensitivity - where gyroAdc are the readed value from our sensor, gyroZero is the value when it is stationary (this is done in the code - look in the "Setup" section) while sensitivity is the sensitivity found in the datasheet, but translated into quids.

If you look in the two gyros datasheets (http://www.sparkfun.com/datasheets/Sensors/IMU/lpr530al.pdf and http://www.sparkfun.com/datasheets/Sensors/IMU/LY530ALH.pdf) you will see that the sensitivity is 3.33mV/deg/s for the 4xOUT. To translate these into quids is pretty easy: sensitivity/3.3*1023.

So in this example I get:

0.00333/3.3*1023=1.0323.

NB: to translate mV to V simple just divide by one thousand.

The final equation will look like this:

gyroRate = (gyroAdc-gryoZero)/1.0323

The result will come out as degrees per second. To translate this into degrees you have to know the exact time since the last loop. Fortunately, the Arduino got a simple command to do so: millis(). By using that, one can calculate the time difference (delta time) and thereby calculate the angle of the gyro. The final equation will look like this:

gyroAngle += gyroRate*dtime/1000

Unfortunately, the gyro drifts over time. That means it can not be trusted for a longer timespan, but it is very precise for a short time. This is when the accelerometer comes in handy. It does not have any drift, but it is too unstable for shorter timespan. I will describe how to combine these measurements in a while, but first I will describe how to translate the readings from the accelerometer into something useful.

The accelerometer measures the acceleration (g's) in three dimensions. To translate the analog readings into degrees you simply need to read the axis and to subtract the zero offset like so:

accVal = accAdc-accZero

Where accAdc is the analog reading and accZero is the value when it reads 0g - this is calculated in the start of the code, look in the "Setup" section. The zero value can also be found in the datasheet: http://www.sparkfun.com/datasheets/Components/SMD/adxl335.pdf. You will see that the zero voltage at 0g is approximately 1.5V, to translate this into quids, you again have to use this equation: zeroVoltage/3.3*1023.

So in this example I get:

1.5/3.3*1023=465.

You can then calculate the pitch and roll using the following equations:

pitch = atan2(accYval, accZval)+PI

roll = atan2(accXval, accZval)+PI

Atan2 has a output range from -π to π (see http://en.wikipedia.org/wiki/Atan2), I simply add π, so the range it converted to 0 to 2π.

To convert it from radians to degrees we simply multiply the result by 57.295779513082320876798154814105 - this is predefined in the Arduino IDE as RAD_TO_DEG.

As I explained earlier the gyro is very precise, but tend to drift. The accelerometer is a bit unstable, but does not drift. You can calculate the precise angle by using something called a Kalman filter. A detailed guide on how it's implemented can be found at my blog: http://blog.tkjelectronics.dk/2012/09/a-practical-approach-to-kalman-filter-and-how-to-implement-it/.

If you want to use something a bit more simple, you can use what's called a Complementary Filter. It is pretty easy to understand and the math is much simpler, because it only works in one step.

For example the equation could look like this:

angle = 0.98 *(angle+gyro*dt) + 0.02*acc - you can fine tune the numbers to whatever you like. Just remember that the sum must be 1.

For me the result from the Complementary Filter was very close (or almost the same) as the one calculated by the Kalman filter.

You have now learned (hopefully) how to get analog data from IMU and translate it to something useful. I have attached my own code for my 6DOF IMU (http://www.sparkfun.com/products/10010), but with some slightly modification, I am pretty sure that it is possible to use it with any analog gyro/accelerometer.

If you have any question, fell free to post a comment below.

https://www.instructables.com/id/Accelerometer-Gyro-Tutorial/

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1284738418

http://www.x-firm.com/?page_id=148

http://web.mit.edu/first/segway/

I have just finished a Processing code which prints out data from the Arduino on a nice graph. As you can see in the video below the filtering is quit effective. The light blue line is the accelerometer, the purple line is the gyro, the black line is the angle calculated by the Complementary Filter, and the red line is the angle calculated by the Kalman filter. As you might see the Kalman filter is just a bit more precise (i know it is difficult to see in the video) than the Complementary Filter, especially when I shake it.

I have attached my code, both the updated code for the Arduino and the Processing code. It is also possible to see the data from the y-axis. Just uncomment drawAxisY(); in the code.

I decided to put all the source code on github, as it is much easier to maintain.

The newest code can now be found at github: https://github.com/TKJElectronics/Example-Sketch-for-IMU-including-Kalman-filter

Below is a video of my balancing robot. It uses the same IMU and algorithm as described in the post above.

I have just released my balancing robot on Kickstarter: http://www.kickstarter.com/projects/tkjelectronics/balanduino-balancing-robot-kit

Please consider backing the project.

I just reposted it, so even more will get use of it. The code can be found here:

https://github.com/TKJElectronics/Example-Sketch-for-IMU-including-Kalman-filter

Hallo everybody

I recently bought this analog 6DOF (six degrees of freedom) IMU board (http://www.sparkfun.com/products/10010) from watterott.com. It uses three gyros and three accelerometers to calculate angles in three dimensions.

I looked a while for some code online and how to connect with them. After many hours of research I succeeded of making af precise measurement of angles in two directions. I decided to write a short guide for fellow electronic enthusiasts.

The main purpose of this guide is to teach others how to get some useful data from their IMU or just a gyro or accelerometer. The code for Arduino can be found at github: https://github.com/TKJElectronics/Example-Sketch-for-IMU-including-Kalman-filter. It should be pretty easy to implement my code to your own sensor. I will not describe all the details about the theory behind, instead you can look at the sources for more info.

Before you begin you have to connect the IMU as follows:

Acc_Gyro Arduino

3.3V <—> 3.3V

GND <—> GND

Gx4 X <—> AN0

Gx4 Y <—> AN1

Gx4 Z <—> AN2

Acc X <—> AN3

Acc Y <—> AN4

Acc Z <—> AN5

Also connect 3.3V to the AREF pin on the Arduino for more accuracy.

It is

**VERY**important that you do not connect the sensor to 5V - this will destroy the sensor.Now your are ready for reading some data from the sensor.

To communicate with the sensor is straightforward:

The gyro measures degrees per second while the accelerometer measures acceleration (g's) in three dimensions. Both outputs the measurements as a analog signal.

To get these translated into degrees you have to do some coding:

**The gyro**First you have to translate quids (a number from 0-1023) into something useful (this is for a ADC with a 10 bit resolution, for example this should be 4095 (2^12-1=4095) for 12 bit ADC). To do this I just use this simple equation:

gyroRate = (gyroAdc-gyroZero)/sensitivity - where gyroAdc are the readed value from our sensor, gyroZero is the value when it is stationary (this is done in the code - look in the "Setup" section) while sensitivity is the sensitivity found in the datasheet, but translated into quids.

If you look in the two gyros datasheets (http://www.sparkfun.com/datasheets/Sensors/IMU/lpr530al.pdf and http://www.sparkfun.com/datasheets/Sensors/IMU/LY530ALH.pdf) you will see that the sensitivity is 3.33mV/deg/s for the 4xOUT. To translate these into quids is pretty easy: sensitivity/3.3*1023.

So in this example I get:

0.00333/3.3*1023=1.0323.

NB: to translate mV to V simple just divide by one thousand.

The final equation will look like this:

gyroRate = (gyroAdc-gryoZero)/1.0323

The result will come out as degrees per second. To translate this into degrees you have to know the exact time since the last loop. Fortunately, the Arduino got a simple command to do so: millis(). By using that, one can calculate the time difference (delta time) and thereby calculate the angle of the gyro. The final equation will look like this:

gyroAngle += gyroRate*dtime/1000

Unfortunately, the gyro drifts over time. That means it can not be trusted for a longer timespan, but it is very precise for a short time. This is when the accelerometer comes in handy. It does not have any drift, but it is too unstable for shorter timespan. I will describe how to combine these measurements in a while, but first I will describe how to translate the readings from the accelerometer into something useful.

**The accelerometer**The accelerometer measures the acceleration (g's) in three dimensions. To translate the analog readings into degrees you simply need to read the axis and to subtract the zero offset like so:

accVal = accAdc-accZero

Where accAdc is the analog reading and accZero is the value when it reads 0g - this is calculated in the start of the code, look in the "Setup" section. The zero value can also be found in the datasheet: http://www.sparkfun.com/datasheets/Components/SMD/adxl335.pdf. You will see that the zero voltage at 0g is approximately 1.5V, to translate this into quids, you again have to use this equation: zeroVoltage/3.3*1023.

So in this example I get:

1.5/3.3*1023=465.

You can then calculate the pitch and roll using the following equations:

pitch = atan2(accYval, accZval)+PI

roll = atan2(accXval, accZval)+PI

Atan2 has a output range from -π to π (see http://en.wikipedia.org/wiki/Atan2), I simply add π, so the range it converted to 0 to 2π.

To convert it from radians to degrees we simply multiply the result by 57.295779513082320876798154814105 - this is predefined in the Arduino IDE as RAD_TO_DEG.

**Kalman filter**As I explained earlier the gyro is very precise, but tend to drift. The accelerometer is a bit unstable, but does not drift. You can calculate the precise angle by using something called a Kalman filter. A detailed guide on how it's implemented can be found at my blog: http://blog.tkjelectronics.dk/2012/09/a-practical-approach-to-kalman-filter-and-how-to-implement-it/.

If you want to use something a bit more simple, you can use what's called a Complementary Filter. It is pretty easy to understand and the math is much simpler, because it only works in one step.

For example the equation could look like this:

angle = 0.98 *(angle+gyro*dt) + 0.02*acc - you can fine tune the numbers to whatever you like. Just remember that the sum must be 1.

For me the result from the Complementary Filter was very close (or almost the same) as the one calculated by the Kalman filter.

You have now learned (hopefully) how to get analog data from IMU and translate it to something useful. I have attached my own code for my 6DOF IMU (http://www.sparkfun.com/products/10010), but with some slightly modification, I am pretty sure that it is possible to use it with any analog gyro/accelerometer.

If you have any question, fell free to post a comment below.

**Sources:**https://www.instructables.com/id/Accelerometer-Gyro-Tutorial/

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1284738418

http://www.x-firm.com/?page_id=148

http://web.mit.edu/first/segway/

**Update**I have just finished a Processing code which prints out data from the Arduino on a nice graph. As you can see in the video below the filtering is quit effective. The light blue line is the accelerometer, the purple line is the gyro, the black line is the angle calculated by the Complementary Filter, and the red line is the angle calculated by the Kalman filter. As you might see the Kalman filter is just a bit more precise (i know it is difficult to see in the video) than the Complementary Filter, especially when I shake it.

I have attached my code, both the updated code for the Arduino and the Processing code. It is also possible to see the data from the y-axis. Just uncomment drawAxisY(); in the code.

**Newest firmware**I decided to put all the source code on github, as it is much easier to maintain.

The newest code can now be found at github: https://github.com/TKJElectronics/Example-Sketch-for-IMU-including-Kalman-filter

**My Balancing robot**Below is a video of my balancing robot. It uses the same IMU and algorithm as described in the post above.

**Kickstarter**

I have just released my balancing robot on Kickstarter: http://www.kickstarter.com/projects/tkjelectronics/balanduino-balancing-robot-kit

Please consider backing the project.

## Share

## Recommendations

We have a **be nice** policy.

Please be positive and constructive.

## 138 Comments

Hi Lauszus,

I found your article very interesting but I was wondering if you could answer a quick question of mine. I am trying to implement an IMU attached to a foot to measure position in the z (vertical) axis. It is a 9DOF IMU and from my research I believe there should be a way to use kalman filtering on the gyroscope and accelerometer data to find position, just like you have done to find the angle.

Do you know if this is possible and would the method be similar to what you have demonstrated in the article?

Thank you.

Hi Lauszus,

Thank you for your code it has really helped me understand how the Kalman filter works.

I but i just cannot get my head over how you arrived at your estimated covariance matrix. I thought

P = F*p*F^2 + Q, where F =[1,dt; 0,1] and

Q =[dt^3/3,dt^2/2;dt^2/2,dt]*var^2

But this doesnt work in practice, like when i program it. How did you arrive at you covariance estimation in step 2? What formulas did you use?

thanks!

In the article above, 3 axis accelerometer and gyro are used, right?

In that case what will be the equation for calculating YAW?just like the following equations for roll and pitch..

pitch = atan2(accYval, accZval)+PI

roll = atan2(accXval, accZval)+PI

You can find more information on how to calculate yaw in my bachelor's thesis: https://github.com/Lauszus/LaunchPadFlightController/blob/master/docs. The relevant code is located here: https://github.com/Lauszus/LaunchPadFlightController/blob/master/src/IMU.c#L76-L93.

Regards

Kristian Sloth Lauszus

Can the code be used for a self balancing robot? There is no setup of motors in the code...i think its not the code for balancing...it would be great if u could upload it to github and post the link or just send me at - ilovecars252003mukut@gmail.com

Actually I am just 13 years old and I have made several robots but easy ones.. I want to implement ROS so I wanted to understand KF and EKF so thought of doing this project. Hope you can help me!

Please see my blog post: http://blog.tkjelectronics.dk/2012/03/the-balancing-robot.

how to calibrating mpu 6050 with arduino use trigonometri formula?

To Find more you can found formulas description here

https://www.instructables.com/id/Accelerometer-Gyro...

Found has to be corrected by Find :p

Hello Lauszus,

how to change the max angle of pitch in your kalman code for mpu6050 from 90 degree to 180 degree?

thankyou