Go Down

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

Lauszus

@jasmine_hossam
Check out Pololu's library for Arduino:
https://github.com/pololu/L3G4200D

And also see Sparkfun's example code for the device: http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Gyros/3-Axis/L3G4200D_Example.zip (http://www.sparkfun.com/products/10612).

Regards
Lauszus

ea123

Hi,
here is my implementation of Kalman filter and a comparison with raw sensor and complementary filter
in roll/pitch angle estimation:

http://www.youtube.com/watch?v=n3ysIw1XiOg





Jase_MK

Hi all. Been lurking for a while and reading this thread with interest.

I'm putting together a data logger for my car and have managed to find a reasonably priced 9DOF unit. From what I can see, using the Kalman filter (or similar alternative) only works to calculate a angular position if you're not accelerating. Surely if a car is accelerating, braking or cornering hard then accelerometer readings used as part of the algorithm for calculating pitch and roll is going to generate duff results?

Similarly, I'm not sure how to measure something simple such as g-forces generated due to cornering. Simply taking an accelerometer reading on the x-axis will give an incorrect result due to the fact that the car will be experiencing some roll and therefore the sensor won't be flat. If I knew the angle of roll, I could correct this reading using some simple trig, but this takes us back to the original problem of not being able to calculate pitch/roll whilst the IMU is experiencing significant acceleration (other than gravity).

Hmmmm
/strokes chin...

Apologies if I've misunderstood things or missed this coming up earlier in the thread.

Lauszus

@Jase_MK
Sorry, but you misunderstand the whole point of a Kalman filter or similar. The whole point of a Kalman filter or similar is to filter out any noise i.e. acceleration from a car etc. So if you tune your filter properly it will filter out all the noise from the accelerometer! To get the total amount of g-force, you just have to calculate the length of the force vector, as I did in the code.

Regards
Lauszus

Jase_MK

OK, thanks. So using the Kalman filter, or similar, I can use my IMU readings to calculate angular position (pitch, roll), even if the car is accelerating about all over the place. I think I need to read the thread again from the start and try out some code and see what happens.

Thanks

Lauszus

@Jase_MK
Yes exactly :)
Okay, do that - I think the best way to "learn" how it works is to see the effect of the filter yourself.
Try to upload the Arduino code provided and use the Processing program I created to see a visual representation of the data.

Regards
Lauszus

Jase_MK

Will do. My IMU is in the post so I shall get playing asap.

Thanks again

Lauszus

@Jase_MK
Okay. Your welcome :)
Just write me again if you need further assistance!

Regards
Lauszus

George64

Hello,

Pretty new to the forum and to using the Arduino Uno with the SLM303.

I'm trying to build a tilt compensated compass with an nmea string as out. This string is going to be input for my boat network so my tiller pilot will be able to better steer a course. Quite a project....

The code I have so far:
Code: [Select]
#include <Wire.h>
#include <LSM303.h>

LSM303 compass;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  compass.init();
  compass.enableDefault();
 
  // Calibration values. Use the Calibrate example program to get the values for
  // your compass.
  compass.m_min.x = -397; compass.m_min.y = -284; compass.m_min.z = -464;
  compass.m_max.x = 150; compass.m_max.y = 287; compass.m_max.z = 227;
 
  /* Output van Calibrate
  M min X: -397 Y: -284 Z: -464
  M max X: 150 Y: 287 Z: 227
  */
}

/* Oorspronkelijke code
void loop() {
  compass.read();
  int heading = compass.heading((LSM303::vector){0,-1,0});
  Serial.println(heading);
  delay(500);
}
*/

/*----------------------------------------------------------------------------
        1   2   3 4   5 6
        |   |   | |   | |
$--HDG,x.x,x.x,a,x.x,a*hh<CR><LF>
------------------------------------------------------------------------------

Field Number:
1. Magnetic Sensor heading in degrees
2. Magnetic Deviation, degrees
3. Magnetic Deviation direction, E = Easterly, W = Westerly
4. Magnetic Variation degrees
5. Magnetic Variation direction, E = Easterly, W = Westerly
6. Checksum */

char nmeastr[17]; // HCHDG,000.00,,,,*
int checksum;
char hs[6]; // 000.00

void loop() {
  strcpy(nmeastr,"HCHDG,");
 
  //dtostrf(FLOAT,WIDTH,PRECSISION,BUFFER);
  compass.read();
  dtostrf(compass.heading(), 5, 0, hs);
  //Serial.print("hs ");
  //Serial.print(hs);
  //Serial.println(); 
 
  strcat(nmeastr,hs);
  strcat(nmeastr,",,,,");
 
  //add a checksum
  checksum=0;
  for (int n=0; n < strlen(nmeastr); n++) {
    checksum ^= nmeastr[n];
  }
 
  Serial.print("$");
  Serial.print(nmeastr);
  Serial.print("*");
  Serial.print(checksum, HEX);
  Serial.println();
 
  /* 5hz == 200 */
  delay(500);
}


When laying flat on the table, it produces:
Quote
$HCHDG,  207,,,,*59
$HCHDG,  211,,,,*5E
$HCHDG,  213,,,,*5C
$HCHDG,  209,,,,*57
$HCHDG,  213,,,,*5C
$HCHDG,  211,,,,*5E
$HCHDG,  210,,,,*5F
$HCHDG,  215,,,,*5A
$HCHDG,  212,,,,*5D
$HCHDG,  207,,,,*59
$HCHDG,  208,,,,*56
$HCHDG,  208,,,,*56
$HCHDG,  208,,,,*56
$HCHDG,  211,,,,*5E
$HCHDG,  210,,,,*5F
$HCHDG,  210,,,,*5F
$HCHDG,  207,,,,*59
$HCHDG,  217,,,,*58
$HCHDG,  215,,,,*5A
$HCHDG,  211,,,,*5E
$HCHDG,  211,,,,*5E
$HCHDG,  209,,,,*57
$HCHDG,  212,,,,*5D
$HCHDG,  210,,,,*5F
$HCHDG,  209,,,,*57
$HCHDG,  210,,,,*5F
$HCHDG,  211,,,,*5E
$HCHDG,  212,,,,*5D
$HCHDG,  211,,,,*5E
$HCHDG,  210,,,,*5F


As you can see, not a stable course to steer ;) The video shows the issue I'm facing when it comes to stable ocurse
http://youtu.be/3XHxAKu6n7E

I know I should do some filtering, and this is where I got to this topic and also got stuck on how to get the kalman filter to this code. I'd like some help on how I can put the filter in place so the course gets more stable.

Many thanks in advance for your reply!

Lauszus

Hi,
I don't have any experience with magnetometers - I know that Sparkfun called it a compass sensor, but it's really a magnetometer.

Have you check out this application note:
http://www.sparkfun.com/datasheets/Sensors/Magneto/Tilt%20Compensated%20Compass.pdf

Also check out this library I found:
https://github.com/pololu/LSM303

I don't know if that is the library you are already using? But it look like it? Have you tried to run the example sketch (https://github.com/pololu/LSM303/blob/master/LSM303/examples/Heading/Heading.ino) and see how that went?

Remember that any magnetic field will affect your reading, so keep away all electronics - my friend had a big problem with his until he realized that his laptop's harddrive affected his magnetometer a lot!

Sorry that I can't help you no more - I have no experience with magnetometers. If it were me would properly try the example sketch provided in the library and then read the application note to understand what was going on :)
I don't think you can use the Kalman filter I provided. You need another type of filter - try google for "ahrs magnetometer" and see what you can find.

Regards
Lauszus

George64

Thanks for your explaination Lauszus.

The code from https://github.com/pololu/LSM303 is the code I use for the compass function. The output shown is the result of a minor addition I did to create nmea output.

I'll google "ahrs magnetometer" to see if it can help. Part of the learning curve ;)

George

Lauszus

Okay. I will try to talk with my teammate tomorrow as he is currently building a quadrocopter, so he has some experience with magnetometers, and then ask him for good links and so on.

Regards
Lauszus

George64

Thanks Lauszus, that woud be great!

Been searching using the keywords you suggest, however I did not find a solution that would fit my needs. Sites I found suggest to use some sort of Kalman filter. Will also do more digging.

Cheers, George

Thomas Jespersen

Dear George.

This is Thomas, Lauszus' teammate. As Lauszus sure enough introduced me I am building a Quadrocopter. To do this you need a 9DOF sensor, which means a 3-angled accelerometer, gyro and magnetometer.
To combine all the sensor data I use a DCM algorithm - Direct Cosine Matrix - which then gives me the orientation of the board in x, y and z rotational degrees.

With the orientation I am then also able to get the tilt compensated heading by combining the magnetometer data and the orientation values.

On the Arduino, which I am not using for this project though, it can be done with the following code: https://dev.qu.tu-berlin.de/projects/sf-razor-9dof-ahrs/wiki/Tutorial
If that doesn't work out for you because of it being to advanced then have a look at the smaller version of the code here: http://code.google.com/p/sf9domahrs/

Let me know if you can get it working.

Best Regards
Thomas Jespersen
Need any help with your electronics projects?
TKJ Electronics, a consultancy company located in Denmark (Europe), has the required ex

Go Up