LSM6DS3 returning Register address instead of value on most registers
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
}
}
