Tuesday, March 20, 2012

[ROBOMAG2012] Compass Module

We've decided to use a tilt-compensated compass module that consists of an accelerometer and a magnetometer. This particular module is a Pololu LSM303DLH #1250. It's no longer available for sale, but details are still on their website. It needed calibration based on its maximum and minimum values which were obtained by spinning the module in all directions. After the values were obtained, the heading can be accurately determined by some sample code in their Arduino library. A few modifications were made and the Arduino interfaces with the serial port. Any UART sending it the appropriate commands will receive the desired response. As of now, the only valid command is getting the heading direction. The code looks like this:

#include <Wire.h>
#include <LSM303.h>

LSM303 compass;
char iscommand;
char command;
char a;
int count = 0;
void setup() {
  Serial.begin(115200);
  Wire.begin();
  compass.init();
  compass.enableDefault();
 
  // Calibration values. Use the Calibrate example program to get the values for
  // your compass.

  compass.m_min.x = -705; compass.m_min.y = -539; compass.m_min.z = -337;
  compass.m_max.x = +325; compass.m_max.y = +546; compass.m_max.z = 605;
}

void loop() {
  //compass must be read constantly to get updated position
  //so regardless of a need for data stream, this line is needed
  compass.read();
  int heading = compass.heading((LSM303::vector){0,-1,0});
  //& signifies the beginning of the command
  if( Serial.peek( ) == '&' )
  {
    //this just gets rid of the & char
    Serial.read( );
    //command is the next char in buffer
    command = Serial.read( );
    if ( command == '1' )
    {
      Serial.print( "Heading: " );
      Serial.println(heading);
    }
    else
      Serial.println( "Invalid command" );
  }
  //get rid of anything that's not part a command
  else if( Serial.peek( ) != -1 )
  {
    Serial.read( );
  }
  //delay needed because processing speed > transfer speed
  delay( 25 );
}