cancel
Showing results for 
Search instead for 
Did you mean: 

LSM6DS3 returning Register address instead of value on most registers

Maglog
Associate II

I have multiple LSM6DS3 (with SH SMD markings) and all of them show the same strange behavior.
The chip is soldered to a breakout board that is set up on a breadboard. And is connected to the MCU breakout with 20 cm jumper wire.

1. When I read a register, they return the registers address as the register value. The exceptions are the ID register, which is correctly returned as 0x69 and the Data registers that contain the acceleration and gyro data.

2. Reconfiguration (for example the resolution) will take effect only after a power cycle and another write. I tested it multiple times while changing the SPI wire lengths to make sure it's not some kind of glitch from bad wiring.

3. The Gyros Z Axis is always outputting zero.

4. Configuring the secondary I2C for reading a slave magnetometer does not work, the I2C does not show any activity on the lines. I implemented it according to Application Note AN4650.

The sensor values that are put out are correct (except gyro-Z), and change as expected when I tilt the sensor or move it around.

I looked at the signals with an oscilloscope and they are clean, no significant noise.
The value that is returned from the registers is consistent with what is actually on the line (also checked that with an oscilloscope).

I use the same SPI initialization across multiple projects and SPI slaves, every other chip runs just fine.
The clock polarity and clock phase is also implemented according to the datasheet.
I tested the Chip as the only slave to the MCU master and the problems persist.

Is this a known problem? Google, ChatGPT and Stackexchange returned nothing useful.
Slowly I'm running out of ideas, help is greatly apprechiated.

 

This is the initialization code of the device

void lsm6ds3_init()
{
	imu_initialized = 0;
	volatile uint32_t check = 0;

	// Read WHO AM I
	volatile uint8_t id = lsm6ds3_read_register_1B_blocking(S3_REG_WHO_AM_I);
	if (id != 0x69)
	{
		// read failed
		errorhandling_new_error(ERROR_ID_IMU_NOT_RESPONDING, SEVERITY_WARNING);
		return;
	}
		// Acc set scale (scale +-2G),  Acc set ODR (833 Hz), 200 Hz LowPass filter
	check += lsm6ds3_write_register_1B_blocking(S3_REG_CTRL1_XL, IMU_CTRL1_FS_2G | IMU_CTRL1_ODR_833HZ | IMU_CTRL1_BW_200HZ);
	// Gyr set scale (full scale 2000 dps) and ODR (833 Hz), (last bit has to be fixed at 0 because DS says so)
	check += lsm6ds3_write_register_1B_blocking(S3_REG_CTRL2_G, IMU_CTRL2_ODR_416HZ | IMU_CTRL2_FS_250HZ);
	
        if (check > 0)
        {
             // reading the register back correctly failed
        }
	imu_initialized = 1;
	
}

This is the implementation of the writing function. The underlying functions are typical DMA SPI functions that are shared across multiple projects and devices and are well tested.

static uint8_t lsm6ds3_write_register_1B_blocking(uint8_t reg, uint8_t data)
{
	spi_tx_data_buffer[0] = reg;
	spi_tx_data_buffer[1] = data;
	spi_waiting = 1;
	if(spiarb_request_imu_block())  // Manage multiple slaves on the SPI, request an blocking SPI transfer
	{
		lsm6ds3_write_register(reg, spi_tx_data_buffer, 1);  // DMA SPI call
	}
	while(spi_waiting){};
	delay_ms(50);               // Todo: remove later, this is for testing only
        // reading back the written value
	volatile uint8_t res = lsm6ds3_read_register_1B_blocking(reg);
	if (data == res)
	{
		return 0;    // success
	}else
	{
		return 1;   // read back value is not the written value
	}
		
}

 

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

 

 

	spi_tx_data_buffer[0] = reg;
	spi_tx_data_buffer[1] = data;
	spi_waiting = 1;
	if(spiarb_request_imu_block())  // Manage multiple slaves on the SPI, request an blocking SPI transfer
	{
		lsm6ds3_write_register(reg, spi_tx_data_buffer, 1);  // DMA SPI call

 

This is probably the problem. Looks like you're writing reg + data (or maybe even just reg) to register reg.

The ID register works because you can't overwrite it.

Code from lsm6ds3_write_register would confirm.

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

6 REPLIES 6
Foued_KH
ST Employee

Hello @Maglog ,

Could you please share your code *?

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

TDK
Guru

Show the code, show the signals on the SPI line that are incorrect, and what you are expecting them to be.

If you feel a post has answered your question, please click "Accept as Solution".
Maglog
Associate II

I added the relevant code for initialization and the register write and read back function.
Is there any specific code you need?
I will upload pictures of the incorrect SPI signals shortly.

lsm6ds3_write_register and lsm6ds3_read_register_1B_blocking and lsm6ds3_read_register_1B_blocking at a minimum.

If you feel a post has answered your question, please click "Accept as Solution".
TDK
Guru

 

 

	spi_tx_data_buffer[0] = reg;
	spi_tx_data_buffer[1] = data;
	spi_waiting = 1;
	if(spiarb_request_imu_block())  // Manage multiple slaves on the SPI, request an blocking SPI transfer
	{
		lsm6ds3_write_register(reg, spi_tx_data_buffer, 1);  // DMA SPI call

 

This is probably the problem. Looks like you're writing reg + data (or maybe even just reg) to register reg.

The ID register works because you can't overwrite it.

Code from lsm6ds3_write_register would confirm.

If you feel a post has answered your question, please click "Accept as Solution".
Maglog
Associate II

You're absolutely correct, I completely dismissed the non-blocking write function. It was even worse then you suggested, "spi_tx_data_buffer" was used in both functions as spi buffer that got passed to the DMA Controller.


I completely looked in the wrong places, thanks a bunch for the support!