0

I am learning how to integrate sensors on arduinos and read their data.

My ultimate purpose is to place the IMU on a robot and use it in determining the robots location in an environment.

Using the following code, I am able to get accelerometer and temperature data:

// (c) Michael Schoeffler 2017, http://www.mschoeffler.de

#include "Wire.h" // This library allows you to communicate with I2C devices.

const int MPU_ADDR = 0x68; // I2C address of the MPU-6050. If AD0 pin is set to HIGH, the I2C address will be 0x69.

int16_t accelerometer_x, accelerometer_y, accelerometer_z; // variables for accelerometer raw data
int16_t gyro_x, gyro_y, gyro_z; // variables for gyro raw data
int16_t temperature; // variables for temperature data

char tmp_str[7]; // temporary variable used in convert function

char* convert_int16_to_str(int16_t i) { // converts int16 to string. Moreover, resulting strings will have the same length in the debug monitor.
  sprintf(tmp_str, "%6d", i);
  return tmp_str;
}

void setup() {
  Serial.begin(9600);
  Wire.begin();
  Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board)
  Wire.write(0x6B); // PWR_MGMT_1 register
  Wire.write(0); // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
}
void loop() {
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) [MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2, p.40]
  Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active.
  Wire.requestFrom(MPU_ADDR, 7*2, true); // request a total of 7*2=14 registers

  // "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same variable
  accelerometer_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
  accelerometer_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
  accelerometer_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
  temperature = Wire.read()<<8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L)
//  gyro_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
//  gyro_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
//  gyro_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)

//  // print out data
  Serial.print("aX = "); Serial.print(convert_int16_to_str(accelerometer_x));
  Serial.print(" | aY = "); Serial.print(convert_int16_to_str(accelerometer_y));
  Serial.print(" | aZ = "); Serial.print(convert_int16_to_str(accelerometer_z));
//  // the following equation was taken from the documentation [MPU-6000/MPU-6050 Register Map and Description, p.30]
  Serial.print(" | tmp = "); Serial.print(temperature/340.00+36.53);
//  Serial.print(" | gX = "); Serial.print(convert_int16_to_str(gyro_x));
//  Serial.print(" | gY = "); Serial.print(convert_int16_to_str(gyro_y));
//  Serial.print(" | gZ = "); Serial.print(convert_int16_to_str(gyro_z));
  Serial.println();

  // delay
  delay(1000);
}

Giving me output like the following:

aX =   3526 | aY =   -968 | aZ = -11988 | tmp = 25.89
aX =   3478 | aY =   -936 | aZ = -12020 | tmp = 25.91
aX =   3530 | aY =   -922 | aZ = -12002 | tmp = 25.91
aX =   3490 | aY =   -896 | aZ = -12006 | tmp = 25.94
aX =   3498 | aY =   -898 | aZ = -12036 | tmp = 25.91
aX =   3520 | aY =   -916 | aZ = -12050 | tmp = 25.91
aX =   3466 | aY =   -924 | aZ = -11960 | tmp = 25.91
aX =   3492 | aY =   -944 | aZ = -12026 | tmp = 25.92
aX =   3510 | aY =   -924 | aZ = -12048 | tmp = 25.91
aX =   3440 | aY =   -942 | aZ = -11980 | tmp = 25.91
aX =   3514 | aY =   -924 | aZ = -12066 | tmp = 25.91
aX =   3484 | aY =   -944 | aZ = -11968 | tmp = 25.92
aX =   3490 | aY =   -944 | aZ = -12012 | tmp = 25.92
aX =   3458 | aY =   -952 | aZ = -11944 | tmp = 25.92

What I need to know is how do I determine what direction my robot is moving in based on the accelerometer output?

3 Answers 3

1

You can't with any great accuracy.

The acceleration vector from the accelerometer is a combination of two things:

  • Gravitational acceleration
  • Acceleration due to change in the robot's velocity.

If the robot is travelling at a constant speed, there is no acceleration due to change in velocity, so the accelerometer will only be measuring gravity. No idea then how far the robot has gone.

If the robot is turning on the spot, again there is not acceleration change. So you don't know which direction the robot is facing!

You can get a rough idea of speed by integrating the acceleration, and distance by integrating speed. However any errors quickly accumulate, and thus the absolute distance may be very poor.

To get velocity (speed with a direction) or absolute position, you will need a magnetometer or gyroscope to estimate rotation.

1

You haven't described your robot but if it is a typical wheeled vehicle that can drive forward and backward, the accelerometer can give you one of those two directions (which is already known because you or your sketch commanded it). If in addition your robot can steer, the the accelerometer will give show a side force (aka centripetal acceleration or centrifugal force) in the direction of the turn.

Figuring out how much the robot turned (in order to get its current direction) is mathematically straight-forward but practically, it is noisy and subject to accumulating errors, as already pointed out.

If knowing orientation, thus direction of travel, is your goal, wouldn't a electronic compass (magnetometer) be of more help?

0

First you have to test, in which orientation the sensor on the IMU board is mounted. You can use your test sketch for this. If you don't move the sensor it will show you the gravitational force, which always points down. Orientate the IMU in such a way, that aX and aY are near zero. Now you know where up and down are. Move the IMU to the sides, until you found the direction, where only aX changes considerably, while aY is staying near zero. Then you have found the next direction.

Finally mount the IMU in your robot in the found orientation. Since you know, which of aX, aY and aZ change with which direction, you know the direction of the robots movement.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.