Pololu Robotics & Electronics
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pololu Forum

LSM303 weird effect with the compass

I finished my Project with LSM303DLH and your LSM303 Library, the calibration with your “Calibrate.ino” module is done,
the results are identical with the Android compass, the North has a difference of 2 degrees.

The problem is, if I turn the sensor 90 degree EST, the sensor reads 112 degree.
the same at 90 degree WEST (270 degree), it indicates 226 degree.

this is my first time using this sensor, maybe I forgot something or the calibration is not correct
Can you tell me my mistake.

This is the portion for LSM303 reading.

  if (compass.init()){
      // You can find your declination on: http://magnetic-declination.com/
      // (+) Positive or (-) for negative
    Calibration values; the default values of +/-32767 for each axis
    lead to an assumed magnetometer bias of 0. Use the Calibrate example
    program to determine appropriate values for your particular unit.
    compass.m_min = (LSM303::vector<int16_t>){ cal.mmin[0], cal.mmin[1], cal.mmin[2]};
    compass.m_max = (LSM303::vector<int16_t>){ cal.mmax[0], cal.mmax[1], cal.mmax[2]};

  // axis towards the satellite
  // ( x-axe {1, 0, 0}  compass.a.x )
  // ( y-axe {0, 1, 0 } compass.a.y )
  heading = compass.heading((LSM303::vector<int>){1, 0, 0});
  // for elevation  compass.a.x;  compass.a.y;   compass.a.z;
  // Calculate the angle of the vector x,z
  // The result willbe in radians, so we multiply by 180 degrees and divide by Pi to convert that to degrees
  elevation = (atan2(compass.a.x, compass.a.z) * 180) / PI;

This is the Calibrate function.

bool Calibrate(){

  //int16_t xcounter,ycounter, zcounter;
  // vector intern for calibrate  
  // load default Value into LSM303DLHC
  LSM303::vector<int16_t> running_min = {+32767, +32767, +32767} , running_max = {-32767, -32767, -32767};

  char report[80];

  digitalWrite(LEDR, HIGH);       // LED RED ON Start of Calibration

   while (true)

    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);

    snprintf(report, sizeof(report), "min: {%+6d, %+6d, %+6d}    max: {%+6d, %+6d, %+6d}",
    running_min.x, running_min.y, running_min.z,
    running_max.x, running_max.y, running_max.z);
    if(toupper(Serial.read()) == 'Z') { break; };
  // save calibration value
  cal.mmin[0] = running_min.x;
  cal.mmin[1] = running_min.y;
  cal.mmin[2] = running_min.z;
  cal.mmax[0] = running_max.x;
  cal.mmax[1] = running_max.y;
  cal.mmax[2] = running_max.z;

  digitalWrite(LEDG, HIGH);       // LED Yellow ON end of Calibration
  return true;

Please edit your post to add code tags.

Did you apply the correct magnetic declination at your location?

You may need to do the calibration more carefully. See this post for the most reliable and accurate approach: Correcting the Balboa magnetometer