LSM6DS33 Acceleration and Angular velocity problems, doesn't know it's still

I’m using a LSM6DS33 and I am getting really weird numbers for the acceleration and angular velocity. It is really large when it still. I use the LSM303 library.

Here is example data (this is the average of points) when the sensor is still
linear acceleration data at ±8g (mm/s^2): x: 265.69 y:126.86 z:10201.69
angular velocity for 2000dps (mdps): x: 3920.00 y:-5950.00 z: -2520.00

I changed the scales and it only changes the variation. I’m very confused by the large Z acceleration. Is that just the IMU being aware of gravity?

Here is my code:

#include <ros.h>
#include <ros/time.h>
#include <geometry_msgs/Twist.h> //Add the message types
#include <geometry_msgs/Pose.h>
#include <geometry_msgs/Vector3.h>
#include <std_msgs/Float32.h>
#include <sensor_msgs/Imu.h>
#include <LIS3MDL.h>
#include <LSM6.h>
#include <Wire.h>
#include <math.h>

    const float gravity = 9.81;   //Gravity in m/s^2
    const float accGain = 0.244;  //mg/LSB from dataSheet for +-8g
    //const float accGain = 0.061;  //mg/LSB from dataSheet for +- 2g
    const float gyroGain = 70;    //mdps/LSB from dataSheet for 2000dps max
    //const float gyroGain = 8.75;     //mdps/LSB from dataSheet for 245dps max
    //const float magGain = 6842.0; //LSB/gauss
    const float magGain = 1711.0; //LSB/gauss
    const float xmin = -676;

void setup() {
Wire.begin(); //Initialize I2C

  // Make sure the sensors get initialized
  if (!acc_gyr.init())
    //Turn on imu_LED
    digitalWrite(imu_LED, HIGH);
    while (1);
  }//end if
  acc_gyr.writeReg(LSM6::CTRL1_XL, 0x3C); // 52 Hz, 8 g full scale
  acc_gyr.writeReg(LSM6::CTRL2_G, 0x4C); // 104 Hz, 2000 dps full scale

  if (!mag.init())
    //Turn on mag_LED
    digitalWrite(mag_LED, HIGH);
    while (1);
  }//end if
  mag.writeReg(LIS3MDL::CTRL_REG2, 0x60); //
  analogWrite(LED, 127); //Turn on good status LED
  digitalWrite(13, LOW); //Turn off initialization LED
  time_0 = millis(); //Initial Time
  theta = 0;
  prevV = 0;
  coilTime_0 = millis();//Initial Time for the coils
  analogWriteFrequency(22, 5000); //changes the PWM frequency of FTM0 pins (22, 23) to 3000 Hz
  analogWriteFrequency(4, 5000);
}//end setup

void loop() {
  // put your main code here, to run repeatedly:

  //Read IMU Data;         //get data from the magnetometer
  acc_gyr.readAcc();  //get data from the accelerometer

  acc_gyr.readGyro();     //get data from the accelerometer and gyro

  //Assign values to the magnet
  magnetApplied.x = (mag.m.x - xoff) * magScale_X / magGain*100;
  magnetApplied.y = (mag.m.y - yoff) * magScale_Y / magGain*100;
  magnetApplied.z = (mag.m.z - zoff) * magScale_Z / magGain*100;

  IMU.header.frame_id = "IMU"; // Give the Sensor an ID
  IMU.header.stamp =; // This is NEEDED TO GET A TIME STEP

  //Assign values to the accelerometer
  IMU.linear_acceleration.x = acc_gyr.a.x * accGain * gravity;
  IMU.linear_acceleration.y = acc_gyr.a.y * accGain * gravity;
  IMU.linear_acceleration.z = acc_gyr.a.z * accGain * gravity;

  //Assign values to the gyro
  IMU.angular_velocity.x = acc_gyr.g.x * gyroGain;
  IMU.angular_velocity.y = acc_gyr.g.y * gyroGain;
  IMU.angular_velocity.z = acc_gyr.g.z * gyroGain;
}//end loop

Any ideas of how to fix this or how to continue to troubleshoot?

Thanks for your support,

Yes, accelerometers will notice the acceleration due to gravity, and it seems very likely that this is what you are noticing. One way to test for that is to flip your board over and see if the sign of that acceleration changes (or you can rotate your board in your hand and watch the magnitude of acceleration change as each axis aligns with the gravity vector). As for the rotation rates you are getting when the board is at a standstill, those values also look normal. The typical zero-rate level for the LSM6 is +/-10dps.


Good to know. So I assume my robot is no longer turning if the value is less than 10dps?

It might be reasonable/useful in some situations to set a threshold like 10dps to determine if your gyroscope is stationary. However, if you want something more analog, like responding in proportion to turning rate, a threshold like that might not be so appropriate. One thing to consider is that the value reported by the gyroscope basically has two components: an offset and noise. Offsets can be determined by obtaining an average rotation rate at each axis while the gyro is at a complete standstill and subtracting that offset from any future readings. Performing some kind of averaging (like a running average) can smooth out the noise.


I’m glad it can be that simple. Thanks!