LSM303DLHC Electronic Compass Module and the Arduino

image

Our BM004 breakout module is based on the ST Microelectronics LSM303DLHC.   The LSM303DLHC basically has two ICs embedded in its tiny plastic packaging.  They are a 3-axis accelerometer, and a 3-axis magnetometer.  Both devices are connected to an I2C interface and you access the functions of each by addressing different internal register addresses.

We’re at a point in this product’s development where it needs to go from engineering to production status.  This happens after the first couple of production runs, during which time application notes, documents, and additional testing usually occurs.  Part of the hand-off process is the creation of a tester that can be used by less technical people around the office.   For our breakout modules I’ve designed a tester that tests all of the first 10 modules (BM001 through BM010).  Since these modules have no connectors they are interface to our tester with spring loaded test pins.

In the image above, you can see the BM004, which carries a LSM303DLHC and some additional circuitry.  It’s resting on the spring loaded test points.  In the image below you can see the spring loaded test points and the Arduino Uno we use as the brains for this tester.

image

 

I’ll be putting out some application notes  using the BM004 as a tilt sensor, and using it as an electronic compass.   Here’s the first one that simply shows how to read and write to the LSM303DLHC’s registers.  The accelerometer, magnetometer, and temperature sensor data are all read and displayed using the serial monitor in the Arduino environment.   Future code examples will convert this data to heading information (electronic compass).

/*
BM004_read_write_registers:  This program reads the accelerometer and magnetometer registers 
from ST Micro's LSM303DLHC.  The register values are sent to the serial monitor.

Schematics associated with the BM004 moudle may be used for hardware wiring information.
see www.solutions-cubed.com for additional information.

Accelerometer register addresses are >= 0x1F and along with the temperature
registers are 12-bit and left justified.  Magnetometer register addresses are less
< 0x1F and are 12-bit right-justified.  
*/
 
#include <Wire.h>
 
/*  
Send register address and the byte value you want to write the accelerometer and 
loads the destination register with the value you send
*/
void WriteAccRegister(byte data, byte regaddress)
{
    Wire.beginTransmission(0x19);   // Use accelerometer address for regs >=0x20
    Wire.write(regaddress);
    Wire.write(data);  
    Wire.endTransmission();     
}

/*  
Send register address and the byte value you want to write the magnetometer and 
loads the destination register with the value you send
*/
void WriteMagRegister(byte data, byte regaddress)
{
    Wire.beginTransmission(0x1E);   // Else use magnetometer address
    Wire.write(regaddress);
    Wire.write(data);  
    Wire.endTransmission();     
}

/*  
Send register address to this function and it returns byte value
for the accelerometer register's contents 
*/
byte ReadAccRegister(byte regaddress)
{
    byte data;
    Wire.beginTransmission(0x19);   // Use accelerometer address for regs >=0x20  
    Wire.write(regaddress);
    Wire.endTransmission();
  
    Wire.requestFrom(0x19,1);   // Use accelerometer address for regs >=0x20
    data = Wire.read();
    Wire.endTransmission();   
    return data;  
}  

/*  
Send register address to this function and it returns byte value
for the magnetometer register's contents 
*/
byte ReadMagRegister(byte regaddress)
{
    byte data;
    Wire.beginTransmission(0x1E);   // Else use magnetometer address  
    Wire.write(regaddress);
    Wire.endTransmission();
  
    Wire.requestFrom(0x1E,1);   // Else use magnetometer address
    data = Wire.read();
    Wire.endTransmission();   
    return data;  
}  

/*
Reads the X,Y,Z axis values from the accelerometer and sends the values to the 
serial monitor.
*/
void get_display_Accelerometer(void)
{
    int XAxis = 0;
    int YAxis = 0;
    int ZAxis = 0;

    WriteAccRegister(0x27,0x20);  // Enable accelerometer
    delay(10);  
    WriteAccRegister(0x08,0x23);  // Enable HD mode 
    delay(10);  

  // need to convert the register contents into a righ-justified 16 bit value
  XAxis = (int)((ReadAccRegister(0x29)<<8)+ReadAccRegister(0x28))/16;
  delay(10);  
  YAxis = (int)((ReadAccRegister(0x2B)<<8)+ReadAccRegister(0x2A))/16;
  delay(10);  
  ZAxis = (int)((ReadAccRegister(0x2D)<<8)+ReadAccRegister(0x2C))/16;

  // send register values to the serial monitor 

  Serial.print("Acc XAxis=");
  Serial.print(XAxis,DEC);  
  Serial.print(" ");
  Serial.print("Acc YAxis=");
  Serial.print(YAxis,DEC);  
  Serial.print(" ");
  Serial.print("Acc ZAxis=");
  Serial.println(ZAxis,DEC);    

}  

/*
Reads the X,Y,Z axis values from the magnetometer sends the values to the 
serial monitor.
*/
void get_display_Magnetometer(void)
{
    int XAxis = 0;
    int YAxis = 0;
    int ZAxis = 0;
    int Temperature = 0;

    WriteMagRegister(0x80,0x00);  // Enable temperature sensor
    delay(10);  
    WriteMagRegister(0x20,0x01);  // set gain to +/-1.3Gauss
    delay(10);  
    WriteMagRegister(0x00,0x02);  // Enable magnetometer constant conversions
    delay(10);  

  // need to convert the register contents into a righ-justified 16 bit value
  XAxis = (int)((ReadMagRegister(0x03)<<8)+ReadMagRegister(0x04)); 
  delay(10);  
  YAxis = (int)((ReadMagRegister(0x07)<<8)+ReadMagRegister(0x08)); 
  delay(10);  
  ZAxis = (int)((ReadMagRegister(0x05)<<8)+ReadMagRegister(0x06)); 
  delay(10);  
  Temperature = (int)((ReadMagRegister(0x31)<<8)+ReadMagRegister(0x32))/16;

  // send register values to the serial monitor 
  Serial.print("Mag XAxis=");
  Serial.print(XAxis,DEC);  
  Serial.print(" ");
  Serial.print("Mag YAxis=");
  Serial.print(YAxis,DEC);  
  Serial.print(" ");
  Serial.print("Mag ZAxis=");
  Serial.print(ZAxis,DEC);    
  Serial.print(" ");
  Serial.print("Temperature=");
  Serial.println(Temperature,DEC);    
  Serial.println(" ");    
}  

void setup() {
    Wire.begin();
    Serial.begin(9600);  // start serial for output
}

void loop() {
    get_display_Accelerometer();
    delay(1000);
    get_display_Magnetometer();
    delay(1000);
}

Speak Your Mind

*