I can't quite work this out. Someone tell me if I'm crazy.

LSM303DLHC datasheet is somewhat difficult to read here. I have CRB_REG_M set to 001, +/-1.3gauss, its most sensitive range. But all its axes are not equally sensitive, the datasheet Table 75:

Sensor input field range [Gauss] : +/- 1.3

Gain X, Y, and Z[LSB/Gauss] : 1100 (the "Z" is surely a typo here, Z is described in the NEXT field)

Gain Z[LSB/Gauss]: 980

Output Range: 0xF800–0x07FF (-2048–2047)

They're saying Z is actually less sensitive and has greater range, which is correct, the Z component of the Earth's magnetic field is actually significantly greater than the vector sum of the XY components.

I am fairly certain I have correctly decoded the I2C registers. X and Y are signed 2's compliment 16 bit ints, divided by 1100. Z is divided by 980. The vector sum of this yields ~0.480gauss, the correct magnetic field for my location, and the sum is fairly constant as it is rotated.

However, when the device is rotated so the Y is aligned with the Earth's magnetic vector, it will suddenly saturate. Saturation by exceeding range is not described in the datasheet, but I got 0xF000 when it turns "too negative". That limit seems to be about -0.439gauss on the X or Y. The most negative number on the I2C registers is -483.

Just exploring this with a magnet, I experimentally discovered the following limits (approximate):

Xrange=+/-0.736 gauss

Yrange=+/-0.439gauss

Zrange=+/-2.080 gauss(!)

Additionally, when the Z-axis approaches its limit, it will actually FLIP SIGN, while the absolute value stays consistent. As the field increases, the value might go from +1.833gauss to +1.923gauss then an erroneous -2.079. Neither the X nor Y did this.

In all axes, the value 0xF000 is returned for "out of range", whether too positive or negative.

Note that the Y-axis' apparent maximum range of +/-0.439 gauss can be exceeded by the Earth's magnetic field alone, in certain orientations. This makes this one range fairly useless for any application in this planet.

I can't explain this. The datasheet said several things, none of which explain it.

1. It said the data range would go to -2048, which it doesn't. That would have been -1.86gauss, so I don't know why this says this. The most negative value it would read is -483.

2. It said the range is +/- 1.3 gauss, it's not, on any axis. Early on I had a theory that this was the vector sum of all the axis maximums, that would be 0.750gauss, which roughly correlates to the X-axis max but not the Y or Z.

I don't understand why the axes would be different ranges, either. The Z-component of the Earth's magnetic field is stronger, yes, but by the nature of a 3D compass, the device will be rotated and the X,Y, or Z could be aligned with that vector at any time, so the operating range would not be larger than the smallest axis.

It's easy enough to "work around"- just increase the range. The 1.9gauss range did not yield an error at any angle to the Earth's field. However, I'll need to test the range figures for these as well, I suspect they've also got these "unusual" range profiles. It's unfortunate because we do lose resolution here when going to larger scales. The "1.3gauss" scale was only +/-483 LSBs of range in the Y, not 2047, and certainly not 16 bits of range. Increasing the range will further decrease the resolution of the Earth's magnetic field, and a far larger scale may be necessary to avoid saturating the output when disturbed by a second magnetic field source, a magnet near the device.

LSM303DLHC datasheet is somewhat difficult to read here. I have CRB_REG_M set to 001, +/-1.3gauss, its most sensitive range. But all its axes are not equally sensitive, the datasheet Table 75:

Sensor input field range [Gauss] : +/- 1.3

Gain X, Y, and Z[LSB/Gauss] : 1100 (the "Z" is surely a typo here, Z is described in the NEXT field)

Gain Z[LSB/Gauss]: 980

Output Range: 0xF800–0x07FF (-2048–2047)

They're saying Z is actually less sensitive and has greater range, which is correct, the Z component of the Earth's magnetic field is actually significantly greater than the vector sum of the XY components.

I am fairly certain I have correctly decoded the I2C registers. X and Y are signed 2's compliment 16 bit ints, divided by 1100. Z is divided by 980. The vector sum of this yields ~0.480gauss, the correct magnetic field for my location, and the sum is fairly constant as it is rotated.

However, when the device is rotated so the Y is aligned with the Earth's magnetic vector, it will suddenly saturate. Saturation by exceeding range is not described in the datasheet, but I got 0xF000 when it turns "too negative". That limit seems to be about -0.439gauss on the X or Y. The most negative number on the I2C registers is -483.

Just exploring this with a magnet, I experimentally discovered the following limits (approximate):

Xrange=+/-0.736 gauss

Yrange=+/-0.439gauss

Zrange=+/-2.080 gauss(!)

Additionally, when the Z-axis approaches its limit, it will actually FLIP SIGN, while the absolute value stays consistent. As the field increases, the value might go from +1.833gauss to +1.923gauss then an erroneous -2.079. Neither the X nor Y did this.

In all axes, the value 0xF000 is returned for "out of range", whether too positive or negative.

Note that the Y-axis' apparent maximum range of +/-0.439 gauss can be exceeded by the Earth's magnetic field alone, in certain orientations. This makes this one range fairly useless for any application in this planet.

I can't explain this. The datasheet said several things, none of which explain it.

1. It said the data range would go to -2048, which it doesn't. That would have been -1.86gauss, so I don't know why this says this. The most negative value it would read is -483.

2. It said the range is +/- 1.3 gauss, it's not, on any axis. Early on I had a theory that this was the vector sum of all the axis maximums, that would be 0.750gauss, which roughly correlates to the X-axis max but not the Y or Z.

I don't understand why the axes would be different ranges, either. The Z-component of the Earth's magnetic field is stronger, yes, but by the nature of a 3D compass, the device will be rotated and the X,Y, or Z could be aligned with that vector at any time, so the operating range would not be larger than the smallest axis.

It's easy enough to "work around"- just increase the range. The 1.9gauss range did not yield an error at any angle to the Earth's field. However, I'll need to test the range figures for these as well, I suspect they've also got these "unusual" range profiles. It's unfortunate because we do lose resolution here when going to larger scales. The "1.3gauss" scale was only +/-483 LSBs of range in the Y, not 2047, and certainly not 16 bits of range. Increasing the range will further decrease the resolution of the Earth's magnetic field, and a far larger scale may be necessary to avoid saturating the output when disturbed by a second magnetic field source, a magnet near the device.

The problem is this. The LSM303DLHC accel/mag doesn't seem to read consistently in I2C single-read mode. You NEED to do I2C sequential-reads of the 6 output registers.

Repeat-reads didn't work for me. I thought it was the driver. However, there's a line in the datasheet which says you NEED TO CHANGE THE I2C REGISTER ADDRESS'S MSB TO 1 TO AUTO-INCREMENT. I didn't do that, my I2C driver wasn't working for repeat-reads so I'd fallen back to single-read transactions.

This is specified for both the LSM303DLHC and L3GD20, but oddly enough failing to set the MSB to 1 only resulting in the register failing to auto-increment for the accelerometer. The LSM303DLHC mag and L3GD20 seem to auto-increment when the register MSB is 0 even though the spec sheet says they won't. "weird".