0
\$\begingroup\$

I'm having trouble reading the 6 magnetic field data registers from the LSM303DLHC on my STM32F3Discovery board. (OUT_X_H_M, OUT_X_L_M, etc)

I used the STM32F3Discovery demo as an example for how to read from the compass sensor. I copied the Demo_CompassConfig() and Demo_CompassReadMag() functions provided in main.c of the demo. I also setup a virtual com port so I could dump text data to a terminal program on my PC and see the values I was reading.

I can read the acceleration data from same sensor just fine, but not the magnetic field data.

Like the code in the demo, I'm initializing the sensor like this:

LSM303DLHCMag_InitTypeDef LSM303DLHC_InitStructure;
LSM303DLHC_InitStructure.Temperature_Sensor = LSM303DLHC_TEMPSENSOR_DISABLE;
LSM303DLHC_InitStructure.MagOutput_DataRate = LSM303DLHC_ODR_7_5_HZ ;
LSM303DLHC_InitStructure.MagFull_Scale = LSM303DLHC_FS_8_1_GA;
LSM303DLHC_InitStructure.Working_Mode = LSM303DLHC_CONTINUOS_CONVERSION;
LSM303DLHC_MagInit(&LSM303DLHC_InitStructure);

When I try to read the X Y Z values of the magnetic field data using the demo's read function, they show the first reading measured, but then never update and always stay the same.

uint8_t buffer[3];
while (1) {
   // ... 
   Demo_CompassReadMag(buffer);
   // ...
}

If I call LSM303DLHC_MagGetDataStatus() before and after the read, it's always 0x03. Bit 0 indicates a new set of measurements is available, and Bit 1 indicates that the output registers are locked.

In my searching I read that the 6 output registers are locked until they are all read, and then the next measured data is loaded for another read. The data seems to be correct if I power cycle the device in different orientations and read it, but it seems to be locking the first value and then never loading any more. So I tried reading all 6 values at once to unlock the output registers.

uint8_t buffer[6];
while (1) {
   // ... 
   LSM303DLHC_Read(MAG_I2C_ADDRESS, LSM303DLHC_OUT_X_H_M, buffer, 6);
   // ...
}

Same thing, the XYZ data never changes. I even tried reading all 13 bytes (0x00 to 0x0C) from the magnetic sensor. Still does not update.

If I reconfigure the device after every read, I can get real time data out of the sensor. Obviously this is not what you're supposed to do.

uint8_t buffer[3];
while (1) {
   // ... 
   Demo_CompassReadMag(buffer);
   Demo_CompassConfig();
   // ...
}

I'm guessing that I'm doing something wrong or missing something simple, and the lock is never being released, and the next set of values is never being loaded.

Can anyone tell me how you are supposed to read the 6 magnetic field data values out and reset the output register lock? I've tried a lot of things and can't get it working.

\$\endgroup\$
1
\$\begingroup\$

I ran into the same problem with the LSM303DLHC in continuous mode using the auto-incrementing mag data registers. I didn't manage to resolve the issue with the data lock never clearing but did get around the problem with the following algorithm:

1. Power on chip and wait ~400us
2. Open/Enable/Start I2C
Loop
    3. Write to the MR_REG_M register with value 0x01 to place into single shot mode
    4. Read SR_REG_M register until DATA_RDY flag is set
    5. Read 6 mag data registers
    6. Write to the MR_REG_M register with value 0x3 to place into sleep mode
EndLoop
7. Close I2C
8. Power down chip

Stopping and starting I2C during the loop caused me problems but the single shot-sleep-single shot method seems to be fairly robust.

Hope that helps.

\$\endgroup\$
  • \$\begingroup\$ Oh, and sticking a 100 clock cycle delay (at 1MHz) between register reads seems to be required otherwise the results get 'locked' again...maybe the whole problem is down to inserting enough delays to let the chip keep up... \$\endgroup\$ – user38932 Mar 19 '14 at 17:14
1
\$\begingroup\$

I am responding to this old posting in hopes it will help new users of the LSM303DHLC magnetometer...

I encountered the (apparent) data locking problem and found out it was because the final register read has to be terminated with NMAK (not MAK) then SP(stop). Once I modified the call for the last register read (OUT_Y_L_M), the data updated as expected. Without the NMAK the device thinks the initial transaction is still pending. NMAK (negative acknowledge) requires leaving the SDA line high (as opposed to pulling it low for MAK).

If you are using a subroutine call that issues a MAK for the other register reads, like I was, you will have to modify the last call.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.