Stuck on calibration for (LSM303) Accelerometer

Hi all,

This is my first foray into robotics so I've made myself a mini-tank with a: Triple-axis Accelerometer+Magnetometer (Compass) Board - LSM303

My plan was to teach myself how to use the accelerometer, and use it for simple applications ie. (tank getting stuck -> it executes a maneuver to become unstuck, and the tank uses the compass reading to always head in a northern direction.) I believe I am getting consistent readings from the Accelerometer, and while I was researching I found out that I need to calibrate it so I did some research on the forums and found this topic post:
http://arduino.cc/forum/index.php/topic,140494.0.html

I tried to recreate this within my code but I think I goofed somewhere or maybe I'm not applying it properly?? ** I tested just the X Axis so far**

Based off the reading from the Serial Monitor I'm not sure whats causing my readings to be off. I tried to find the answer by reading the accelerometer documentation but it left me even more confused.
Accel X: 149620
-24
Accel X: 112000
-84
Accel X: 134120
-12
Accel X: 141620
-24

Code:

[size=10pt]
#include <Wire.h>
#include <Adafruit_LSM303.h>

Adafruit_LSM303 lsm;

const int XMin = 1064;
const int XMax = 1032;
//const int YMin = 
//const int YMax = 
//const int ZMin
//const int ZMax

void setup() 
{
  Serial.begin(9600);
  
  // Try to initialize and warn if it couldn't detect the chip
  if (!lsm.begin())
  {
    Serial.println("Oops ... unable to initialize the LSM303. Check your wiring!");
    while (1);
  }
}

void loop() 
{
  unsigned long XSum = 0;
  unsigned long YSum = 0;
  unsigned long ZSum = 0;
  
  for (int i=0; i<100; i++) 
  {
    XSum += ((int)lsm.accelData.x);
    //YSum += analogRead(YPin);
    //ZSum += analogRead(ZPin);
  }
  
  lsm.read(); 

  //Serial.print("Accel X: "); 

  Serial.print((int)lsm.accelData.x); 
  Serial.print("\n");
  Serial.print("Accel X: ");
  Serial.print(map(XSum/100, XMin, XMax, -2000, 2000));
  Serial.print("\n");

  //Serial.print("Y: "); Serial.print((int)lsm.accelData.y);       Serial.print(" "); //Accel Y
  //Serial.print("Z: "); Serial.println((int)lsm.accelData.z);     Serial.print(" "); //Accel Z
  //Serial.print("Mag X: "); Serial.print((int)lsm.magData.x);     Serial.print(" ");
  //Serial.print("Y: "); Serial.print((int)lsm.magData.y);         Serial.print(" ");
  //Serial.print("Z: "); Serial.println((int)lsm.magData.z);       Serial.print(" ");
  delay(500);
}[/size]

This is not correct. lms.accelData.x (or y or z) is only updated after calls to lsm.read(). If you .read() it once then look at it 100 times it will be the same value.

gdavisiv:

  for (int i=0; i<100; i++) 

{
   XSum += ((int)lsm.accelData.x);
   //YSum += analogRead(YPin);
   //ZSum += analogRead(ZPin);
 }
 
 lsm.read();

Not sure why you're getting a crazy value here though:

Serial.print(map(XSum/100, XMin, XMax, -2000, 2000));

ahh ok ok I didn't even notice that silly little mistake thanks!!

I'll try looking at it again at the map function maybe the last two values should be -1000, 1000 instead??

Your X readings are coming back -12, -24, -84, and you're trying to map that from the range 1032 to 1064 (Xmin to Xmax). Those numbers aren't inside that range. I don't know how map() will react to that.

If you are trying to add up 100 readings to get some sort of average, then
(a) after you add up 100 readings, you need to divide by 100
(b) make sure you don't overflow the int

try seeing what the actual readings are, without confusing yourself and me with the stoopid map() function.

try reading the y and z axes as well, that will give you a better idea if the device is actually working and the
communications to the device are actually working.

the answer from an accelerometer is going to look rather boring unless the device is actually accelerating.

When I rotate the accel on its x-axis the values jump up to -1096, and 1029

ok ill get all the readings without the extra code

Accel and Mag reading rotation on all 3 Axes:
Thanks again for your help!

X:
Accel X: -1084 Y: -80 Z: 68
Mag X: 712 Y: 274 Z: 205
Accel X: 1044 Y: 48 Z: 48
Mag X: -707 Y: 189 Z: 96

Y:
Accel X: 16 Y: -1068 Z: 108
Mag X: 51 Y: 644 Z: 411
Accel X: 4 Y: 1048 Z: -156
Mag X: 45 Y: -814 Z: -6

Z:
Accel X: -12 Y: 228 Z: 1056
Mag X: 74 Y: -115 Z: -546
Accel X: 28 Y: -12 Z: -992
Mag X: -4 Y: -383 Z: 841

It's a good idea to find out which way the magnetic field vector is pointing at your location
and see if the vector you get agrees with that.

michinyon:
It's a good idea to find out which way the magnetic field vector is pointing at your location
and see if the vector you get agrees with that.

How would I do that? Do you just simply mean where north is??

I verified using my iPhone compass, found magnetic north, and then faced my sensor in the same orientation (make sure it is horizontal so you don't have to deal with tilt compensation). Your magnetometer should show 0, at magnetic north (or at least is how my my HMC5883L is setup when reading raw values). If it doesn't, you can create an offset so that it is 0 at north. Then rotate it 180 degrees and make sure the raw value goes to max, and then returns to 0 when back at magnetic north. If for your application the sensor will never be tilted, this may be all you have to do if everything checks out. If the sensor will be at other orientations other than horizontal, you will need to look into tilt compensation.

The closest I could get the Y Value was to -1 when i point it to North

Accel X: 16 Y: 52 Z: 1052
Mag X: 278 Y: -1 Z: -203

When I turn it -180 degree's (South) it goes up to -180. Is it safe to assume the Y-axis will give me my reading of North?

Accel X: -20 Y: 44 Z: 1056
Mag X: -249 Y: -180 Z: -185

Thanks!

Sounds like it, are the results repeatable? If so, I would guess the orientation of the sensor is such that the y-axis is your heading axis. It is Z for mine.

Yes they are repeatable I just copied one instance. Awesome! Thanks for your help one problem solved.

Back to my original question how do I tell if the readings I'm getting for the Accelerometer are 1. correct, 2. how do i translate them into something usable? or are they already usable?

The acceleration due to gravity is pretty constant 8) so when you've got it sitting still in any position you know the value it's reporting is 9.8 m/s2. The datasheet for the chip states it is factory calibrated so there shouldn't be any second guessing required.

The magnetometer is a different problem since it will see interference from any number of wires or traces running around it. When you complete your project you would need to calibrate it in situ by rotating it full circle and checking its readings at a chosen number of points.

Chagrin:
The acceleration due to gravity is pretty constant 8) so when you've got it sitting still in any position you know the value it's reporting is 9.8 m/s2. The datasheet for the chip states it is factory calibrated so there shouldn't be any second guessing required.

I'll be honest I attempted to read the datasheet but a lot of it seemed like jibberish to me.. I'll read it again and at least try to find the part you mentioned so I know for next time.. anything else I should know? A friend of mine suggested I look into "Azmuth equations?"