Pages: 1 ... 20 21 [22] 23 24 ... 37   Go Down
Author Topic: Guide to gyro and accelerometer with Arduino including Kalman filtering  (Read 304074 times)
0 Members and 2 Guests are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Dear Thomas, Lauszus,

Thanks for the time you took to reply.

I read the article and searched for a calibration programm related to the LSM303. I found this program:
Code:
#include <Wire.h>
#include <LSM303.h>

LSM303 compass;
LSM303::vector running_min = {2047, 2047, 2047}, running_max = {-2048, -2048, -2048};

// temp
float x_min; float x_max; float x_cur;
float y_min; float y_max; float y_cur;
float z_min; float z_max; float z_cur;

void setup() {
 
  Serial.begin(9600);
  Wire.begin();
  compass.init();
  compass.enableDefault();
 
}

void loop() { 
  compass.read();
 
  running_min.x = min(running_min.x, compass.m.x);
  running_min.y = min(running_min.y, compass.m.y);
  running_min.z = min(running_min.z, compass.m.z);

  running_max.x = max(running_max.x, compass.m.x);
  running_max.y = max(running_max.y, compass.m.y);
  running_max.z = max(running_max.z, compass.m.z);
 
  Serial.print("M min ");
  Serial.print("X: ");
  Serial.print((int)running_min.x);
  Serial.print(" Y: ");
  Serial.print((int)running_min.y);
  Serial.print(" Z: ");
  Serial.print((int)running_min.z);

  Serial.print(" M max "); 
  Serial.print("X: ");
  Serial.print((int)running_max.x);
  Serial.print(" Y: ");
  Serial.print((int)running_max.y);
  Serial.print(" Z: ");
  Serial.println((int)running_max.z);
 
  delay(100);
}

After running the programm and looking at the serial output, I started moving the board in all sorts of direction, and after some time I got a stable output:
Quote
/* Output of Calibrate.ino
  M min X: -548 Y: -378 Z: -547 M max X: 248 Y: 413 Z: 314
  M min X: -548 Y: -378 Z: -547 M max X: 248 Y: 413 Z: 314
  M min X: -548 Y: -378 Z: -547 M max X: 248 Y: 413 Z: 314
  */

These values I entered in the programm "Heading.ino"
Code:
#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 = -548; compass.m_min.y = -378; compass.m_min.z = -547;
  compass.m_max.x = 248; compass.m_max.y = 413; compass.m_max.z = 314;
 
  /* Output van Calibrate
  M min X: -548 Y: -378 Z: -547 M max X: 248 Y: 413 Z: 314
  M min X: -548 Y: -378 Z: -547 M max X: 248 Y: 413 Z: 314
  M min X: -548 Y: -378 Z: -547 M max X: 248 Y: 413 Z: 314
  */
}

/* 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((LSM303::vector){0,-1,0}), 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);
}

While running this programm, serial output showed the heading as NMEA-string. Having it away from all sorts of electroncs and put a normal (old fashion smiley-wink ) compass pointing in the same directoin, and laying flat on the floor,, the output showed:
Quote
$HCHDG,    0,,,,*5C
$HCHDG,    2,,,,*5E
$HCHDG,    5,,,,*59
$HCHDG,    1,,,,*5D
$HCHDG,    3,,,,*5F
$HCHDG,    1,,,,*5D
$HCHDG,    2,,,,*5E
$HCHDG,    4,,,,*58
$HCHDG,    1,,,,*5D
$HCHDG,    2,,,,*5E
$HCHDG,    2,,,,*5E
$HCHDG,    0,,,,*5C
$HCHDG,    3,,,,*5F
$HCHDG,    1,,,,*5D
$HCHDG,    2,,,,*5E
$HCHDG,    3,,,,*5F
$HCHDG,    3,,,,*5F
$HCHDG,    3,,,,*5F
$HCHDG,    3,,,,*5F
$HCHDG,    2,,,,*5E
$HCHDG,    4,,,,*58
$HCHDG,    4,,,,*58
$HCHDG,    5,,,,*59

Allthough not very accurated, it points north with some variance. Not too bad, but room for improvement, I think.

As soon as I start turning the lsm303 up and down , still pointing in the same direction, I would expect to see the same heading however the output shows:
Quote
$HCHDG,   14,,,,*49
$HCHDG,   14,,,,*49
$HCHDG,   16,,,,*4B
$HCHDG,   12,,,,*4F
$HCHDG,   10,,,,*4D
$HCHDG,    6,,,,*5A
$HCHDG,    5,,,,*59
$HCHDG,    6,,,,*5A
$HCHDG,   10,,,,*4D
$HCHDG,    7,,,,*5B
$HCHDG,    9,,,,*55
$HCHDG,    8,,,,*54
$HCHDG,    9,,,,*55
$HCHDG,   12,,,,*4F
$HCHDG,   13,,,,*4E
$HCHDG,   11,,,,*4C
$HCHDG,   10,,,,*4D
$HCHDG,   11,,,,*4C

IMHO, this heading info is too inaccurate to use as a compass. The autopilot will move the boat from left to right, like a drunken sailor smiley-wink

I'm not sure wether this is part of the lsm303 (in that case it is not a sufficiënt solution for a compass for an auto pilot) or filtering or something else is required to get a more stable output.

Many thanks, George
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
Vita est effugium de veritatis
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You can not use the kalman filter with only one input. Sorry but you need a gyro too, that is why it called "sensor fusion" smiley
You could perhaps use some other kind of smoothing algorithm.
- Lauszus

This is not a true statement. I'm surprised no one picked up on it. A Kalman filter is a useful tool often used to to do sensor fusion. It is not a synonym for sensor fusion. It was originally invented for single measurement systems. The value of a Kalman filter over a regular filter is that it is focused on predicting a future state rather than just  estimating the current state.
Logged

Denmark
Offline Offline
Sr. Member
****
Karma: 10
Posts: 287
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@zencuke
You are totally right, sorry if it has caused anybody problems!
You could actually try to use the Kalman code provided in the sketch and the just set the gyrorate at 0. I havn't tried it, but in theory it could be done, but you will probably have tune the noise covariances for it to work properly.

Thanks for your feedback!
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

Please I have some questions about this gyro+acc

1. my arduino (ARDUINO UNO R3) works with a SPI communication (i think so :s) , and i think the gyro+acc board works with a I2C communication protocol. Do you think my arduino can fit with it ? Or do you think it can work with a I2C communication like maybe i'm wrong ?

2. I wanted to buy this IMU Analog Combo Board Razor - 6DOF Ultra-Thin IMU (http://www.sparkfun.com/products/10010) but in the link, it is said that the IMU is replaced by another one (IMU Digital Combo Board - 6 Degrees of Freedom ITG3200/ADXL345). I think it is quite the same but i want to be sure before buying it. Do you think your different equations to translate acc and gyro data in degrees is gonna work on the new board ?

3. I Also saw in the sensor's datasheet of the new board that the sensivity is 14.375 LSB/º/s... It's not the same unit as the sensivity of the old one (3.33mV/º/s)... Do you have an idea of what i got to do ?

Thanks
Logged

Denmark
Offline Offline
Sr. Member
****
Karma: 10
Posts: 287
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
1. my arduino (ARDUINO UNO R3) works with a SPI communication (i think so :s) , and i think the gyro+acc board works with a I2C communication protocol. Do you think my arduino can fit with it ? Or do you think it can work with a I2C communication like maybe i'm wrong ?
The Arduino supports both SPI and I2C at the same time. By default you don't use the SPI for your Arduino, it is programmed via UART using the bootloader. See the last section at the following page: http://arduino.cc/en/Guide/Environment#uploading. You only use SPI for programming if you are using a programmer (see http://arduino.cc/en/Hacking/Programmer).
You can also use SPI to communicate with sensors etc. See http://arduino.cc/en/Reference/SPI. A lot of sensors support both SPI and I2C. Since the name I2C is copyright protected by Phillips, the Arduino team is not allowed to call the library I2C, so instead they call it the Wire library. See: http://arduino.cc/it/Reference/Wire.

Quote
2. I wanted to buy this IMU Analog Combo Board Razor - 6DOF Ultra-Thin IMU (http://www.sparkfun.com/products/10010) but in the link, it is said that the IMU is replaced by another one (IMU Digital Combo Board - 6 Degrees of Freedom ITG3200/ADXL345). I think it is quite the same but i want to be sure before buying it. Do you think your different equations to translate acc and gyro data in degrees is gonna work on the new board ?
It will works just as well, there is even more functions when using a digital board - like tap sensing, free fall detection etc.
The reason why I started out by using analog sensors, were because I didn't need the increased functionality that a digital IMU offers, as I wanted to build a balancing robot (https://github.com/TKJElectronics/BalancingRobotArduino) since I only wanted to calculate the angle of the robot, I just bought a analog one. But I also got a cheap digital IMU to mess around with.
It takes a bit more of work to get a digital sensor working, but there is plenty of example code for all kinds of IMU's so even a beginner could get it working in a couple of hours.

Quote
3. I Also saw in the sensor's datasheet of the new board that the sensivity is 14.375 LSB/º/s... It's not the same unit as the sensivity of the old one (3.33mV/º/s)... Do you have an idea of what i got to do ?
Yes, it's pretty simple, just devide the reading (minused the offset) by 14.375 to convert it to º/s.
I will upload a alternative version of the code using a digital IMU instead in a couple of hours to get you started!

Regards
Lauszus
Logged

Denmark
Offline Offline
Sr. Member
****
Karma: 10
Posts: 287
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@kevinh4c
The code for a digital IMU can now be found at github: https://github.com/TKJElectronics/Example-Sketch-for-IMU-including-Kalman-filter/tree/master/IMU6DOF/Digital_IMU

Regards
Lauszus
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This post really help my understanding. Thank a lot!!! Keep it up!
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks So much Lauszus For your HELP
I'll look after all this smiley
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Quote
3. I Also saw in the sensor's datasheet of the new board that the sensivity is 14.375 LSB/º/s... It's not the same unit as the sensivity of the old one (3.33mV/º/s)... Do you have an idea of what i got to do ?
Yes, it's pretty simple, just devide the reading (minused the offset) by 14.375 to convert it to º/s.
I will upload a alternative version of the code using a digital IMU instead in a couple of hours to get you started!


So i just got to do this operation for the digital GIRO ?

gyroRate = (gyroAdc-gryoZero)/14.375 ?

Thanks

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello Lauszus, I greet the other Builders can someone help me cause even Lauszus unreachable!

(Translated by  Google Interpreter) My English is very very weak
 

I'm very fascinated by your robot. Its stability captivated me. My dream is to also perform similar trinket.

Much I ask you to kinda helped me by my project.

 
I just finished assembling Balance Robot.
Because I do not even ACC and Gyro (Analog) I can not even begin your trial.
All Sensor Signal (GYRO and ACC) from A/D Converter set to ca. 1,65V

How do I connect the power supply is buzzer Arduino seems a 100ms tone.
Without connected sensor ACC and Gyro the outputs 11,12, 20, 21.32, and 33 are High (Is this a good sign?)
After switching the PS3 controller,  Press Home Key(PS KEY) BT LED indicates the connection.

Nothing pressing the keys does not cause any reactions mentioned above, get out.
I Send my configurations for my Arduino 2560. It  my configuration is okay?

(USB is PIN 9 and 10)



The signals from the sensors.
Do I understand correctly:
bending forward and gives a minus ACC and GYRO.
slope backwards gives plus ACC and Gyro
If the robot is standing upright is a sensor "Z" gives a minus

You have a way to check the accuracy of encoder connection? (Trick)

 

 

Cordial greetings
Roman
 

 

#define leftA PIND0 //   BEI ATMEGA2560 Pin 21            PD0 - pin 0

#define leftB PIND1 //   BEI ATMEGA2560 Pin 20            PD1 - pin 1

#define leftPWM PINB5 // BEI ATMEGA2560 PB.5 PIN 11       PB1 - pin 9 (OC1A)

 

/* Right motor */

#define rightPort PORTC

#define rightPortDirection DDRC

#define rightPwmPortDirection DDRB

 

#define rightA PINC4 //    BEI ATMEGA2560 Pin 33         PC4 - pin A4

#define rightB PINC5 //    BEI ATMEGA2560 Pin 32         PC5 - pin A5

#define rightPWM PINB6 //  BEI ATMEGA2560 PB.6  PIN 12   PB2 - pin 10 (OC1B)

 

/* Encoders */

#define leftEncoder1 2

#define leftEncoder2 4

#define rightEncoder1 3

#define rightEncoder2 5

 

volatile long leftCounter = 0;

volatile long rightCounter = 0;

 

/* IMU */

#define gyroY A0

#define accY A1

#define accZ A2

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
      I've been working with two different IMUs, Chr-UM6 from CH Robotics and 3space TSS-EM from Yost Engineering.  I'd like to estimate the acceleration bias for x, y, and z so I can subtract it out.  For example, when I move my IMU up from the bench surface and then return it to a rest position the acceleration does not go back to the same value, or at least not in a reasonable time.  Most of the  kalman filters I've seen implemented in code appear to focus on gyros and attitude.

     Does anyone know where I might find a project that has a kalman filter for estimating bias?

Thanks
Logged

Denmark
Offline Offline
Sr. Member
****
Karma: 10
Posts: 287
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@timbopoise
It sounds a bit odd that your accelerometer value doesn't get back to the same value - all my IMU's get back to nearly perfect the same.
You could actually just rewrite the kalman filter, as it would be possible to only use the accelerometer or you could use a digital low-pass filter to filter out the noise from the accelerometer.

Regards
Lauszus
Logged

Manchester, UK
Offline Offline
Sr. Member
****
Karma: 0
Posts: 293
Rodrigo Constanzo is a performer and composer living in Manchester, England. He is an avid improviser and performs regularly using home made electro acoustic, and modified electronic instruments. He is currently working towards a PhD in Composition at th
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Loving this guide! My project is quite different as I'm just sending out raw data and doing the actual math/crunching/calibration in Max/MSP, but the 'plain english' description of everything on the first post has been invaluable!

Now I'm trying to calibrate my magnetometer data (I have a 9DOF setup) but I can't figure out how to get to a useful number.

I'm using an HMC5883L (3-axis magnetometer)(https://www.sparkfun.com/products/10530) coming in over i2c, so it's 12-bit ADC. Looking at the datasheet the sensitivity is a massive range. Here is what it says:



I'm powering the HMC5883L breakout board with the 3.3v from my Arduino board (ArduIMU v2+)(https://www.sparkfun.com/products/9956). On the sparkfun page it lists the resolution as "5 milli-gauss resolution". So am I supposed to get the digital resolution from the above spec?

(nevermind on that part, I figured out the math).

So with this being 12-bit data, should my first formula be this:
sensitivity/3.3* 4095

0.0035958333/3.3*4095 = 4.46209814


So following on I should have

magRate = (magAdc-magZero)/4.46209814


Looking good so far. But now I'm not sure what type of number I'm looking at now, and if it needs further conversion. Do I need to calculate it against the previous value (like a gyro)?

Logged

Denmark
Offline Offline
Sr. Member
****
Karma: 10
Posts: 287
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@kriista
Actually you don't have to use the sensitivity at all, you can simply use atan2 like so:
Code:
atan2(raw.YAxis, raw.XAxis)

I don't have any experience with magnetometers, but have a look at this guide: https://www.loveelectronics.co.uk/Tutorials/8/hmc5883l-tutorial-and-arduino-library

They even wrote a library for the HMC5883L: https://www.loveelectronics.co.uk/Download/Arduino%20Library%20for%20HMC5883L/aHR0cDovL2M0ODc1My5yNTMuY2YzLnJhY2tjZG4uY29tL0xvdmVFbGVjdHJvbmljc19ITUM1ODgzTF9BcmR1aW5vTGlicmFyeS56aXA%3d

Regards
Lauszus

Logged

Manchester, UK
Offline Offline
Sr. Member
****
Karma: 0
Posts: 293
Rodrigo Constanzo is a performer and composer living in Manchester, England. He is an avid improviser and performs regularly using home made electro acoustic, and modified electronic instruments. He is currently working towards a PhD in Composition at th
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

That's a handy guide! Having a look now.

So would I do that for each pair? (X/Y, Y/Z, Z/X)
Logged

Pages: 1 ... 20 21 [22] 23 24 ... 37   Go Up
Jump to: