user37949: I want to calculate the displacement of the Arduino 101 board compared to the starting point (only in the x direction so far). 
In below data I'm swinging the board multiple times in circles around my laptop and then putting it back at the origin a few seconds later.  
Regardless if 1ms-100ms between the loops, the numbers show no sign of the board returning to the origin. I've calibrated the accelerometer x-axis as closely as possible.

Am I doing something wrong in deriving the acceleration/velocity/distance, or is this the level of compounding error to expect? 
If so, can combining gyro data correct acceleration (thought it mainly worked the other way around)? 
I have a GPS meant for correcting position but was hoping any drift wouldn't be this quick.
EDIT: I was incorrect re. use of gyro data; the attitude of the board, which was not consistent in my swings, will effect the acceleration output. Gyro data can be used to calculate and "cancel out" this gravitational impact, and get a more accurate (linear) acceleration (http://www.cl.cam.ac.uk/research/dtg/www/files/publications/public/abr28/ojw28_thesis.pdf). Will report back in a few days.  
Code:
#include "CurieIMU.h"

float gravity = 9.80665; // to convert G forces (1 m/s2 = 0.101972 g; 1 g = 9.80665 m/s2) 
long t1; // create object for first time reference, set time just before the loop later on

// Variables that are dependent on value from last loop
float vx, vy, vz;
float imu_x, imu_y, imu_z;

void setup() {
  Serial.begin(9600); 
  while (!Serial);  // wait for serial to open

  Serial.println("Initializing IMU device...");
  CurieIMU.begin(); // start accelerometer / gyro
  CurieIMU.setAccelerometerRange(2);  // accelerometer range to 2G - might need to be greater later on (18 m/s2 highest possible now)

  /* 

  // Auto-calibration to ensure accelerometer doesn't drift
  CurieIMU.autoCalibrateAccelerometerOffset(X_AXIS, 0); // 89.69999 creates both positive and negative spikes
  delay(1000);
  CurieIMU.autoCalibrateAccelerometerOffset(Y_AXIS, 0);
  delay(1000);
  CurieIMU.autoCalibrateAccelerometerOffset(Z_AXIS, 1);
  delay(1000);

  */

  // Hardcoded accelerometer offsets after testing
  CurieIMU.setAccelerometerOffset(X_AXIS,89);

  // Fetch the offsets from the IMU
  float x_offset = CurieIMU.getAccelerometerOffset(X_AXIS);
  float y_offset = CurieIMU.getAccelerometerOffset(Y_AXIS); 
  float z_offset = CurieIMU.getAccelerometerOffset(Z_AXIS); 

  Serial.println("Current x_offset, y offset, z offset");
  Serial.print(x_offset, 6); 
  Serial.print("\t");
  Serial.print(y_offset, 6);
  Serial.print("\t");
  Serial.println(z_offset, 6);
  delay(5000);

  t1 = millis(); // set the first time reference

  Serial.println("ax_g (g), ax (m/s2), t1 (ms), t2 (ms), td (ms), tds (s), vx (m/s), imu_posx (m)");

}

void loop() {

  // Fetch G forces
  float ax_g, ay_g, az_g;   //scaled accelerometer values
  CurieIMU.readAccelerometerScaled(ax_g, ay_g, az_g); // read accelerometer measurements from device, scaled to the configured range

  // Convert G force to m/s2
  float ax = ax_g / gravity;
  float ay = ay_g / gravity;
  float az = az_g / gravity;

  // Calculate time since last loop
  long t2 = millis();
  float td = t2 - t1; // time delta in ms
  float tds = td / 1000; // delta in seconds for easier logic

  // Calculate current velocity: velocity (m/s) = velocity (m/s) + acceleration (m/s2) * deltaTime (s)
  vx = vx + ax * tds;
  vy = vy + ay * tds;
  vz = vz + az * tds;

  // Calculate position: position (m) = position (m) + velocity (m/s) * deltaTime (s)
  imu_x = imu_x + vx * tds;
  imu_y = imu_y + vy * tds;
  imu_z = imu_z + vz * tds;

  // Print the values
  Serial.print(ax_g, 6);
  Serial.print("\t");
  Serial.print(ax, 6);
  Serial.print("\t");
  Serial.print(t1);
  Serial.print("\t");
  Serial.print(t2);
  Serial.print("\t");
  Serial.print(td, 6);
  Serial.print("\t");
  Serial.print(tds, 6);
  Serial.print("\t");
  Serial.print(vx, 6);
  Serial.print("\t");
  Serial.println(imu_x, 6);

  // Reset start values for next loop
  t1 = millis();

  delay(1);

}


user40427: The Arduino 101 contains the Intel® Curie™ Module, this module contains an Inertial Measurements Unit or IMU for short among other sensors and peripherals 
The IMU of this module is Bosch BMI160 which is a low cost MEMS IMU, this IMUs typically suffer from systematic errors and random/stochastic errors, the following diagram summarize them:

If we take the bias error as an example of those errors, an uncompensated accelerometer bias introduces an error proportional to time (t) in the velocity and proportional to t^2 in the position. For example, consider a case where accelerometer bias is 10 m/s^2. If this bias offset is not removed from the measurements, it can generate a 500 m error in position after 10 seconds and 12.5 km error after 50 seconds. Let us back to our IMU, if we read the data sheet the Zero-g error "or bias" is 40mg for the 8g sensing accelerometer and Ta = 25 Celsius with normal VDD and the IC has been assembled on board. If we just consider this 40mg bias error "dropping other error sources" it is 0.392266 m/s^2 so after 10 seconds the position offset will be 1.96133 meter even if you don't move the Arduino.
I suggest you read "MEMS-Based Integrated Navigation" book here it will give you a good vision about MEMS based inertial sensors and basic navigation concepts.

37949: <p>I want to calculate the displacement of the Arduino 101 board compared to the starting point (only in the x direction so far). </p>

<p>In below data I'm swinging the board multiple times in circles around my laptop and then putting it back at the origin a few seconds later.  </p>

<p>Regardless if 1ms-100ms between the loops, the numbers show no sign of the board returning to the origin. I've calibrated the accelerometer x-axis as closely as possible.</p>

<p><a href="https://i.stack.imgur.com/MjLWM.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/MjLWM.png" alt="Results from swinging"></a></p>

<p>Am I doing something wrong in deriving the acceleration/velocity/distance, or is this the level of compounding error to expect? </p>

<p>If so, can combining gyro data correct acceleration (thought it mainly worked the other way around)? </p>

<p>I have a GPS meant for correcting position but was hoping any drift wouldn't be this quick.</p>

<p>EDIT: I was incorrect re. use of gyro data; the attitude of the board, which was not consistent in my swings, will effect the acceleration output. Gyro data can be used to calculate and "cancel out" this gravitational impact, and get a more accurate (linear) acceleration (<a href="http://www.cl.cam.ac.uk/research/dtg/www/files/publications/public/abr28/ojw28_thesis.pdf" rel="nofollow noreferrer">http://www.cl.cam.ac.uk/research/dtg/www/files/publications/public/abr28/ojw28_thesis.pdf</a>). Will report back in a few days.  </p>

<p>Code:</p>

<pre><code>#include "CurieIMU.h"

float gravity = 9.80665; // to convert G forces (1 m/s2 = 0.101972 g; 1 g = 9.80665 m/s2) 
long t1; // create object for first time reference, set time just before the loop later on

// Variables that are dependent on value from last loop
float vx, vy, vz;
float imu_x, imu_y, imu_z;

void setup() {
  Serial.begin(9600); 
  while (!Serial);  // wait for serial to open

  Serial.println("Initializing IMU device...");
  CurieIMU.begin(); // start accelerometer / gyro
  CurieIMU.setAccelerometerRange(2);  // accelerometer range to 2G - might need to be greater later on (18 m/s2 highest possible now)

  /* 

  // Auto-calibration to ensure accelerometer doesn't drift
  CurieIMU.autoCalibrateAccelerometerOffset(X_AXIS, 0); // 89.69999 creates both positive and negative spikes
  delay(1000);
  CurieIMU.autoCalibrateAccelerometerOffset(Y_AXIS, 0);
  delay(1000);
  CurieIMU.autoCalibrateAccelerometerOffset(Z_AXIS, 1);
  delay(1000);

  */

  // Hardcoded accelerometer offsets after testing
  CurieIMU.setAccelerometerOffset(X_AXIS,89);

  // Fetch the offsets from the IMU
  float x_offset = CurieIMU.getAccelerometerOffset(X_AXIS);
  float y_offset = CurieIMU.getAccelerometerOffset(Y_AXIS); 
  float z_offset = CurieIMU.getAccelerometerOffset(Z_AXIS); 

  Serial.println("Current x_offset, y offset, z offset");
  Serial.print(x_offset, 6); 
  Serial.print("\t");
  Serial.print(y_offset, 6);
  Serial.print("\t");
  Serial.println(z_offset, 6);
  delay(5000);

  t1 = millis(); // set the first time reference

  Serial.println("ax_g (g), ax (m/s2), t1 (ms), t2 (ms), td (ms), tds (s), vx (m/s), imu_posx (m)");

}

void loop() {

  // Fetch G forces
  float ax_g, ay_g, az_g;   //scaled accelerometer values
  CurieIMU.readAccelerometerScaled(ax_g, ay_g, az_g); // read accelerometer measurements from device, scaled to the configured range

  // Convert G force to m/s2
  float ax = ax_g / gravity;
  float ay = ay_g / gravity;
  float az = az_g / gravity;

  // Calculate time since last loop
  long t2 = millis();
  float td = t2 - t1; // time delta in ms
  float tds = td / 1000; // delta in seconds for easier logic

  // Calculate current velocity: velocity (m/s) = velocity (m/s) + acceleration (m/s2) * deltaTime (s)
  vx = vx + ax * tds;
  vy = vy + ay * tds;
  vz = vz + az * tds;

  // Calculate position: position (m) = position (m) + velocity (m/s) * deltaTime (s)
  imu_x = imu_x + vx * tds;
  imu_y = imu_y + vy * tds;
  imu_z = imu_z + vz * tds;

  // Print the values
  Serial.print(ax_g, 6);
  Serial.print("\t");
  Serial.print(ax, 6);
  Serial.print("\t");
  Serial.print(t1);
  Serial.print("\t");
  Serial.print(t2);
  Serial.print("\t");
  Serial.print(td, 6);
  Serial.print("\t");
  Serial.print(tds, 6);
  Serial.print("\t");
  Serial.print(vx, 6);
  Serial.print("\t");
  Serial.println(imu_x, 6);

  // Reset start values for next loop
  t1 = millis();

  delay(1);

}
</code></pre>
 40427: <p>The Arduino 101 contains the Intel® Curie™ Module, this module contains an Inertial Measurements Unit or IMU for short among other sensors and peripherals <a href="https://i.stack.imgur.com/UqoaL.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/UqoaL.png" alt="Intel® Curie™ Module Block Diagram"></a></p>

<p>The IMU of this module is Bosch BMI160 which is a low cost MEMS IMU, this IMUs typically suffer from systematic errors and random/stochastic errors, the following diagram summarize them:
<a href="https://i.stack.imgur.com/gV9W1.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/gV9W1.png" alt="enter image description here"></a></p>

<p>If we take the bias error as an example of those errors, an uncompensated accelerometer bias introduces an error proportional to time (t) in the velocity and proportional to t^2 in the position. For example, consider a case where accelerometer bias is 10 m/s^2. If this bias offset is not removed from the measurements, it can generate a 500 m error in position after 10 seconds and 12.5 km error after 50 seconds. Let us back to our IMU, if we read the data sheet the Zero-g error "or bias" is 40mg for the 8g sensing accelerometer and Ta = 25 Celsius with normal VDD and the IC has been assembled on board. If we just consider this 40mg bias error "dropping other error sources" it is 0.392266 m/s^2 so after 10 seconds the position offset will be 1.96133 meter even if you don't move the Arduino.
I suggest you read "MEMS-Based Integrated Navigation" book <a href="https://rads.stackoverflow.com/amzn/click/1608070433" rel="nofollow noreferrer">here</a> it will give you a good vision about MEMS based inertial sensors and basic navigation concepts.</p>
