LSM303 and LabVIEW

Hi there,

I am going to do some testing on the accuracy of the excellent LSM303DLHC. I might post the results later if anyone is interested. More specifically I want to see how the magnetometer readings are affected by noise (i.e. from the Zumo motors) and how the accelerometer reacts to vibrations (and how to filter for further use with tilt-compensation).

I have tried the sample code (LSM303 library) in Arduino and it works great. However I am having problems getting data into LabVIEW and I am hoping someone will be able to give me some pointers on how to proceed.

I have already tested and verified another sensor (HMC6352) with LabVIEW and know how to use I2C to communicate with the module.

My main problem with the LSM303DLHC seems to be with the register settings. I have read through the LSM303.h and LSM303.cpp files but these files contain code for a few other sensors and my brain is about to burst trying do decipher the important parts from the rest.

I have also read through the datasheet of the module but am having a hard time trying to pick out the important parts.

I would like to know the simplest way possible to get the compass to start sending me data (will do accelerometer later).

I am currently doing the following (not actual code but hopefully understandable):

Writing 0 on address 30 (DEC) // this should put the compass in continuos mode
Reading from address 30 (DEC)

I am getting something back in LabVIEW but I need to know how many bytes are received and what they mean so I can structure the data. Any ideas?

ketile

Hello, ketile.

Unfortunately, I don’t think what you have so far is doing anything useful, since 30 (0x1E) isn’t a valid address for any of the registers in the LSM303DLHC.

At a bare minimum, you need to enable the magnetometer by writing 0 to MR_REG_M; this puts it into continuous-conversion mode. Then you can read the magnetometer values from the output registers. The reading on each axis is a 16-bit value, split between the H and L registers, though only the lowest 12 bits are valid.

The process for reading from the registers is a little complicated; you have to write the register address first, then read the value. (see Table 15 in the datasheet). I haven’t used LabVIEW, so I can’t help you with the specifics, but here is some simplified, LSM303DLHC-specific Arduino code that does what I’ve described in case it helps:

// enable magnetometer
Wire.beginTransmission(0b0011110); // I2C start, send magnetometer write address
Wire.write(0x02);                  // MR_REG_M
Wire.write(0);
Wire.endTransmission();            // I2C stop

// read from magnetometer
Wire.beginTransmission(0b0011110); // I2C start, send magnetometer write address
Wire.write(0x03);                  // OUT_X_H_M
Wire.endTransmission(false);       // I2C restart
Wire.requestFrom(0b0011110, 6);    // send magnetometer read address
byte xhm = Wire.read();            // read 6 bytes 
byte xlm = Wire.read();            //   (the magnetometer will automatically update the
byte zhm = Wire.read();            //   register address after each read)
byte zlm = Wire.read();            // watch out - z comes before y
byte yhm = Wire.read();
byte ylm = Wire.read();
                                   // I2C stop (Arduino Wire library does this automatically)

// combine high and low bytes
int x = (int16_t)(xhm << 8 | xlm);
int y = (int16_t)(yhm << 8 | ylm);
int z = (int16_t)(zhm << 8 | zlm);

- Kevin

Hi Kevin and thank you for your input,

LabVIEW is now reading the magnetometer data :smiley:

I remember parts of the code you posted from the LSM303 library. One thing i noticed is this:

Further down the code you combine the bytes:

// combine high and low bytes
int x = (int16_t)(xhm << 8 | xlm);
int y = (int16_t)(yhm << 8 | ylm);
int z = (int16_t)(zhm << 8 | zlm);

However I have not found any part of the code in the LSM303 library where you perform a bit shift on these variables to adjust for the fact that only the lowest 12 bits are valid.

According to the LSM303DLHC product page https://www.pololu.com/catalog/product/2124 there should be a x >> 4 somewhere:

According to this same product page there should be a left-justification of the accelerometer values. However in the LSM303 library there is a right justification performed:

  // combine high and low bytes, then shift right to discard lowest 4 bits (which are meaningless)
  // GCC performs an arithmetic right shift for signed negative numbers, but this code will not work
  // if you port it to a compiler that does a logical right shift instead.
  a.x = ((int16_t)(xha << 8 | xla)) >> 4;
  a.y = ((int16_t)(yha << 8 | yla)) >> 4;
  a.z = ((int16_t)(zha << 8 | zla)) >> 4;

I am a bit confused about this so I hope you can clarify:

  1. Is it necessary to adjust the magnetometer values to fit with the 12 valid bits?
  2. If so, should they be left or right justified?
  3. Should the accelerometer values be left or right justified?

ketile

I think you might be getting confused because you’re interpreting “left justified” to mean “you should shift the value to the left” instead of “the valid bits are on the left” (it’s intended in the latter sense). The valid bits of the accelerometer are the leftmost (upper) 12 bits, so the 16-bit reading needs to be shifted right to discard the meaningless lower 4 bits. The valid bits of the magnetometer are the rightmost (lower) 12 bits, so the 16-bit reading can simply be interpreted as a 12-bit number.

This picture (from here) shows the same convention we’re following:

- Kevin