2023-09-14 06:01 AM - edited 2023-09-14 06:53 AM
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
}
}
Solved! Go to Solution.
2023-09-14 07:08 AM - edited 2023-09-14 07:09 AM
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.
2023-09-14 06:31 AM
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.
2023-09-14 06:32 AM
Show the code, show the signals on the SPI line that are incorrect, and what you are expecting them to be.
2023-09-14 06:55 AM - edited 2023-09-14 06:56 AM
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.
2023-09-14 07:06 AM
lsm6ds3_write_register and lsm6ds3_read_register_1B_blocking and lsm6ds3_read_register_1B_blocking at a minimum.
2023-09-14 07:08 AM - edited 2023-09-14 07:09 AM
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.
2023-09-14 07:38 AM
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!