cancel
Showing results for 
Search instead for 
Did you mean: 

help to read register from LSM6DSO32 i2C

SBaro.11
Associate III

Hi,

I have one LSM6DSO32 with an Atmel SAMD21 Cortex M0. I use i2c to comunicate with the sensor. I use Arduino ide and Arduino librarys Wire for i2C communication.

I've read the datasheet first of all I set some registers of my sensor I set gyro to 500° et accel to 8g

//gyro 500°
  Wire.beginTransmission(DSO_ADDRESS);
  Wire.write(0x11);                   
  Wire.write(0x54);                   
  Wire.endTransmission();     
 
  //accel 8g
  Wire.beginTransmission(DSO_ADDRESS);
  Wire.write(0x10);                   
  Wire.write(0x58);                   
  Wire.endTransmission();

DSO_ADDRESS is define by 0x6A. So I think everything works beceause if I try to read 0x11 after I set the value 0x54 I get this value 😀

My problem comes when I want to read raw data from gyro and accel, I do that :

//global variables
int raw_temperature = 0;
int gyro_raw[3] = {0, 0, 0};
int acc_raw[3] = {0, 0, 0};
 
//some codes here
 
void readSensor(){
  Wire.beginTransmission(DSO_ADDRESS);
  Wire.write(0x20);                                     
  Wire.endTransmission();   
  Wire.requestFrom(DSO_ADDRESS, 14);
 
  uint8_t buff[14];   
  Wire.readBytes(buff, 14);
 
  raw_temperature = buff[1] << 8 | buff[0];
 
  gyro_raw[X] = buff[3] << 8 | buff[2];
  gyro_raw[Y] = buff[5] << 8 | buff[4];
  gyro_raw[Z] = buff[7] << 8 | buff[6];
  acc_raw[X] = buff[9] << 8 | buff[8];
  acc_raw[Y] = buff[11] << 8 | buff[10];
  acc_raw[Z] = buff[13] << 8 | buff[12];
}

X, Y and Z are defines by 0, 1 and 2.

This is in a function called readSensor. If I called this function 1000 times to get offset from gyro I got some strange values

//global variables
int gyro_offset[3] = {0, 0, 0};
 
 
//in my main function
for(int i = 0; i < 2000; i++){
   readSensor();
 
   gyro_offset[X] += gyro_rax[X];
   gyro_offset[Y] += gyro_rax[Y];
   gyro_offset[Z] += gyro_rax[Y];
   
}
 
gyro_offset[X] /= 2000;
gyro_offset[Y] /= 2000;
gyro_offset[Z] /= 2000;

Here this my problem if I print the result after my for loop, for X I got 23-30 (for me this is good) but for Y and Z I got a big value something like 65515 or 65521, and for me these values aren't good no? Do you think I missed something ?

For information, if I read Who I am register 0xF I got good value 0x6C

1 ACCEPTED SOLUTION

Accepted Solutions
Eleon BORLINI
ST Employee

Hi @SBaro.1​ ,

did you correctly configured the LSM6DSO32 to get an output from the?

For example, you can refer to the application note AN5473 p.23, especially for the configuration of the CTRL1_XL (10h) register for the accelerometer and the CTRL2_G (11h) for the gyroscope.

1. Write INT1_CTRL = 01h // Acc data-ready interrupt on INT1
2. Write CTRL1_XL = 60h // Acc = 417 Hz (High-Performance mode)

A more complete configuration can be found on Github where the C code example lsm6dso32_read_data_polling.c is available:

  • Configuration steps:
/* Disable I3C interface */
  lsm6dso32_i3c_disable_set(&dev_ctx, LSM6DSO32_I3C_DISABLE);
  /* Enable Block Data Update */
  lsm6dso32_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
  /* Set full scale */
  lsm6dso32_xl_full_scale_set(&dev_ctx, LSM6DSO32_4g);
  lsm6dso32_gy_full_scale_set(&dev_ctx, LSM6DSO32_2000dps);
  /* Set ODR (Output Data Rate) and power mode*/
  lsm6dso32_xl_data_rate_set(&dev_ctx, LSM6DSO32_XL_ODR_12Hz5_LOW_PW);
  lsm6dso32_gy_data_rate_set(&dev_ctx, LSM6DSO32_GY_ODR_12Hz5_HIGH_PERF);
  • Data reading steps (accelerometer only):
while (1) {
    lsm6dso32_reg_t reg;
    /* Read output only if new data is available */
    lsm6dso32_status_reg_get(&dev_ctx, &reg.status_reg);
 
    if (reg.status_reg.xlda) {
      /* Read acceleration data */
      memset(data_raw_acceleration, 0x00, 3 * sizeof(int16_t));
      lsm6dso32_acceleration_raw_get(&dev_ctx, data_raw_acceleration);
      acceleration_mg[0] =
        lsm6dso32_from_fs4_to_mg(data_raw_acceleration[0]);
      acceleration_mg[1] =
        lsm6dso32_from_fs4_to_mg(data_raw_acceleration[1]);
      acceleration_mg[2] =
        lsm6dso32_from_fs4_to_mg(data_raw_acceleration[2]);
      sprintf((char *)tx_buffer,
              "Acceleration [mg]:%4.2f\t%4.2f\t%4.2f\r\n",
              acceleration_mg[0], acceleration_mg[1], acceleration_mg[2]);
      tx_com(tx_buffer, strlen((char const *)tx_buffer));
    }

Let me please know if this can be an issue related to the device configuration.

-Eleon

View solution in original post

6 REPLIES 6
Eleon BORLINI
ST Employee

Hi @SBaro.1​ ,

did you correctly configured the LSM6DSO32 to get an output from the?

For example, you can refer to the application note AN5473 p.23, especially for the configuration of the CTRL1_XL (10h) register for the accelerometer and the CTRL2_G (11h) for the gyroscope.

1. Write INT1_CTRL = 01h // Acc data-ready interrupt on INT1
2. Write CTRL1_XL = 60h // Acc = 417 Hz (High-Performance mode)

A more complete configuration can be found on Github where the C code example lsm6dso32_read_data_polling.c is available:

  • Configuration steps:
/* Disable I3C interface */
  lsm6dso32_i3c_disable_set(&dev_ctx, LSM6DSO32_I3C_DISABLE);
  /* Enable Block Data Update */
  lsm6dso32_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
  /* Set full scale */
  lsm6dso32_xl_full_scale_set(&dev_ctx, LSM6DSO32_4g);
  lsm6dso32_gy_full_scale_set(&dev_ctx, LSM6DSO32_2000dps);
  /* Set ODR (Output Data Rate) and power mode*/
  lsm6dso32_xl_data_rate_set(&dev_ctx, LSM6DSO32_XL_ODR_12Hz5_LOW_PW);
  lsm6dso32_gy_data_rate_set(&dev_ctx, LSM6DSO32_GY_ODR_12Hz5_HIGH_PERF);
  • Data reading steps (accelerometer only):
while (1) {
    lsm6dso32_reg_t reg;
    /* Read output only if new data is available */
    lsm6dso32_status_reg_get(&dev_ctx, &reg.status_reg);
 
    if (reg.status_reg.xlda) {
      /* Read acceleration data */
      memset(data_raw_acceleration, 0x00, 3 * sizeof(int16_t));
      lsm6dso32_acceleration_raw_get(&dev_ctx, data_raw_acceleration);
      acceleration_mg[0] =
        lsm6dso32_from_fs4_to_mg(data_raw_acceleration[0]);
      acceleration_mg[1] =
        lsm6dso32_from_fs4_to_mg(data_raw_acceleration[1]);
      acceleration_mg[2] =
        lsm6dso32_from_fs4_to_mg(data_raw_acceleration[2]);
      sprintf((char *)tx_buffer,
              "Acceleration [mg]:%4.2f\t%4.2f\t%4.2f\r\n",
              acceleration_mg[0], acceleration_mg[1], acceleration_mg[2]);
      tx_com(tx_buffer, strlen((char const *)tx_buffer));
    }

Let me please know if this can be an issue related to the device configuration.

-Eleon

SBaro.11
Associate III

Hi @Eleon BORLINI​ ,

I think my configuration is good, maybe the problem comes when I try to read raw data, I'll check this code here https://github.com/STMicroelectronics/STMems_Standard_C_drivers/blob/master/lsm6dso32_STdC/example/lsm6dso32_read_data_polling.c

I'll do the same think for my reading function 😉

SBaro.11
Associate III

For the moment I only play with the temperature, it will be simple narmaly, but also here I got strange value :|

I configure my captor like this I don't use gyro and accel juste temperature, so I disabled only i3C.

After that I have read function (I inspired me by soure code here, so my function is here

static int16_t data_raw_temperature[1];
memset(data_raw_temperature, 0x00, 1 * sizeof(int16_t));
 
//read 14 bytes from 0x20
Wire.beginTransmission(DSO_ADDRESS); 
Wire.write(0x20);                                      
Wire.endTransmission();   
Wire.requestFrom(DSO_ADDRESS, 14);
 
uint8_t buff[14];    
Wire.readBytes(buff, 14);
 
data_raw_temperature[0] = (int16_t)buff[1];
data_raw_temperature[0] = (data_raw_temperature[0] * 256) + (int16_t)buff[0];

It's really look like the C code I posted above. But when I try to print the value like thaht

SerialUSB.println(((float_t)data_raw_temperature[0] / 256.0f) + 25.0f);

The captor returns to me 29.12° (it's an example) and it's impossible beceause in the room the temperature is maybe 23 or 24 maximum. And another strange things, if I put my finger on the captor, the captor bug and I get value 25 (raw value is 0), I must reset the board if I want a new value... I really don't understand what happened here, maybe the captor is defective?

I'am aware taht the temperature can't be the same as a thermometer but 5-7° of difference is a lot ?:\

Hi @SBaro.1​ ,

it's indeed a little high difference, between standard thermometer and your acquisition form LSM6DSO32.

However, please note that the declared Toff (Temperature offset) defined in the datasheet p.29 can be up to +-15°C.

For this reason, my suggestion is to "calibrate" at software level your device (with a reference one), and compensate the read temperature with this offset.

Not sure to have well understood the last part of your comment... do you mean that when you try to change the temperature, the sensor get stuck? This is important to be able to compensate a gain different than 1 across the temperature range.

-Eleon

SBaro.11
Associate III

Hi @Eleon BORLINI​ 

OK I didn't read this information, +-15° waw this amazing, I really need to calibrate my software 😁.

For the second part, what I'am saying is, if I put my finger on the captor or if I blow on it for example, just to see if the temperature up or down, the captor seems to freeze. For example if I put my finger on it, suddenly the temperature up to 100° and after that the captor bug, he returns to me always 25° and 25 ° is for a 0 raw value comes from temperature register, I must reset the board if I want a new valid temperature.

I have an another question for gyroscope 0x22h Pitch axis (X) angular rate value is signed or not ? Because this value can be negative that's right ?

Hi @SBaro.1​ ,

LSM6DSO32 is not a temperature sensor, indeed 😉 But I cannot understand what is the captor you are referring to... is the IMU itself?

Regarding the other question, yes, the output is signed, since you can have a negative rotation (in the sense that the device rotates in the opposite direction with respect to the one depicted in the datasheet p.22, which indicates the positive orientation.

0693W000008yO3GQAU.png 

-Eleon