Arduino UNO with 2 Acclerometers (MPU6050)

Dear All,

I'm working on a project where I have to capture accelerations in x, y and z-direction and the temperature at 2 separate locations.

I connected the accelerometers as shown in the attached picture and I can obtain measurements from both sensors; however, I would like to read the measurements separately. Here is the code:

#include<Wire.h>
const int MPU_addr = 0x68; // I2C address of the MPU-6050
int16_t AcX, AcY, AcZ, Tmp;


void setup() {
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  Serial.begin(9600);
}

void loop() {
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr, 14, true); // request a total of 14 registers
  float AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
  float AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  float AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)

  Serial.print(AcX / 16384);
  Serial.print(" "); 
  Serial.print(AcY / 16384);
  Serial.print(" ");
  Serial.print(AcZ / 16384);
  Serial.print(" ");
  Serial.println(Tmp / 340.00 + 36.53);
  delay(10);
}

So basically how this works at the moment is that if 1 sensor is static and I shake the other one, I will get the measurements from the one that I shook, or the other way around... I would like to be able to monitor the values of both sensors simultaneously.

I know that for that I would have to declare 4 new integers, but how could I store the readings from the sensors in a separate register - how to declare that each sensor has its own register to save the measurements? Could someone please aid me with this.

Kind regards,
L

Can you change the I2C address of either accelerometer? If not, you can't connect two of them to one Arduino. If you can, then reading them independently.

With regards to this topic, I'm 100% sure this can be done, I'm just not electronically educated enough to understand or know how to implement it... I know that the second sensor can have its I2C address changed to 0x69, but I would need some guidance on how to do it.

but I would need some guidance on how to do it.

Was there some part of "connect the AD0 straight to the 5v output of the arduino" that needs amplification?

From the MPU6050 datasheet:

Pg 25: The LSB of the of the I2C slave address is set by pin 9 (AD0).

Pg 33: The slave address of the MPU-60X0 is b110100X which is 7 bits long. The LSB bit of the 7 bit address is determined by the logic level on pin AD0. This allows two MPU-60X0s to be connected to the same I2C bus. When used in this configuration, the address of the one of the devices should be b1101000 (pin AD0 is logic low) and the address of the other should be b1101001 (pin AD0 is logic high).

So for 0x68, AD0 is Low, and for 0x69, AD0 is High.
Connect to Gnd on one device, and to 3.3V on the other.

Thank your very much sir, by using the I2C scanner I now recognized 2 different I2C addresses! Once I get the code working, I will post it here since this was quite a common topic.

Thanks again,
L

For everyone who ever tried to connect 2 MPU6050 on 1 ArduinoUNO, here is the code:

#include<Wire.h>
const int MPU_addr_1 = 0x68; // I2C address of the first MPU-6050
const int MPU_addr_2 = 0x69; // I2C address of the second MPU-6050
int16_t AcX1, AcY1, AcZ1, Tmp1, AcX2, AcY2, AcZ2, Tmp2; // definition of variables


void setup() {
  Wire.begin();
  Wire.beginTransmission(MPU_addr_1);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  Serial.begin(9600);
  Wire.begin();
  Wire.beginTransmission(MPU_addr_2);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  Serial.begin(9600);
}

void loop() {
  Wire.beginTransmission(MPU_addr_1);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr_1, 14, true); // request a total of 14 registers
  float AcX1 = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
  float AcY1 = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  float AcZ1 = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp1 = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)

  Wire.beginTransmission(MPU_addr_2);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr_2, 14, true); // request a total of 14 registers
  float AcX2 = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
  float AcY2= Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  float AcZ2 = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp2 = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)

  Serial.print(AcX1 / 16384);
  Serial.print(" "); 
  Serial.print(AcY1 / 16384);
  Serial.print(" ");
  Serial.print(AcZ1 / 16384);
  Serial.print(" ");
  Serial.print(Tmp1 / 340.00 + 36.53);
  Serial.print(" ");
  Serial.print(AcX2 / 16384);
  Serial.print(" "); 
  Serial.print(AcY2 / 16384);
  Serial.print(" ");
  Serial.print(AcZ2 / 16384);
  Serial.print(" ");
  Serial.println(Tmp2 / 340.00 + 36.53);
  delay(500);
}

It's probably not the most optimized code, but it works. Also, find attached the final wiring. As mentioned by Mr. CrossRoads, the connect one MPU6050's AD0 to GND and the other ones AD0 to 3.3V, with that you obtain 2 different I2C addresses. The one that is on GND is kept at 0x68 and the other that is on HIGH (3.3V) is changed to 0x69. Thanks again for all provided help.

Regards,

L

2 Likes

It's probably not the most optimized code

Arrays and for loops, and it would be about half the size it is.

Wire.requestFrom(MPU_addr_2, 14, true); // request a total of 14 registerWhy request data from 14 registers, when you read 8?

PaulS:
Arrays and for loops, and it would be about half the size it is.

I'm quite bad at Arduino programming, I'm using Python as preferred, but if you want to show me how you would optimize it, I would be more than happy to observe!

jremington:
Wire.requestFrom(MPU_addr_2, 14, true); // request a total of 14 registerWhy request data from 14 registers, when you read 8?

True, I didn't bother with that because it's from Arduino reference example, but I will change it. Thanks!

if you want to show me how you would optimize it, I would be more than happy to observe!

Observe away.

const int MPU_addrs[] = { 0x68, 0x69 };

int16_t AcX[2], AcY[2], AcZ[2], Tmp[2]; // definition of variables

void setup()
{
  for(byte b=0; b<2; b++)
  {
    Wire.begin();
    Wire.beginTransmission(MPU_addrs[b]);
    Wire.write(0x6B);  // PWR_MGMT_1 register
    Wire.write(0);     // set to zero (wakes up the MPU-6050)
    Wire.endTransmission(true);
  }

  Serial.begin(9600);
}

void loop()
{
  for(byte b=0; b<2; b++)
  {
    Wire.beginTransmission(MPU_addrs[b]);
    Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);

    Wire.requestFrom(MPU_addrs[b], 14, true); // request a total of 14 registers
    float AcX[b] = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
    float AcY[b] = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
    float AcZ[b] = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
    Tmp[b] = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)

    Serial.print("Data from sensor ");
    Serial.println(b);

    Serial.print(AcX[b] / 16384);
    Serial.print(" ");
    Serial.print(AcY[b] / 16384);
    Serial.print(" ");
    Serial.print(AcZ[b] / 16384);
    Serial.print(" ");
    Serial.println(Tmp[b] / 340.00 + 36.53);
  }
}

Still asking for data from 14 registers?

PaulS:
Observe away.

const int MPU_addrs[] = { 0x68, 0x69 };

int16_t AcX[2], AcY[2], AcZ[2], Tmp[2]; // definition of variables

void setup()
{
  for(byte b=0; b<2; b++)
  {
    Wire.begin();
    Wire.beginTransmission(MPU_addrs[b]);
    Wire.write(0x6B);  // PWR_MGMT_1 register
    Wire.write(0);    // set to zero (wakes up the MPU-6050)
    Wire.endTransmission(true);
  }

I'm getting some errors:

Serial.begin(9600);
}

void loop()
{
  for(byte b=0; b<2; b++)
  {
    Wire.beginTransmission(MPU_addrs[b]);
    Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);

Wire.requestFrom(MPU_addrs[b], 14, true); // request a total of 14 registers
    float AcX[b] = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
    float AcY[b] = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
    float AcZ[b] = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
    Tmp[b] = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)

Serial.print("Data from sensor ");
    Serial.println(b);

Serial.print(AcX[b] / 16384);
    Serial.print(" ");
    Serial.print(AcY[b] / 16384);
    Serial.print(" ");
    Serial.print(AcZ[b] / 16384);
    Serial.print(" ");
    Serial.println(Tmp[b] / 340.00 + 36.53);
  }
}

I'm getting some errors: array must be initialized with a brace-enclosed initializer. (for the definition of floats AcX, AcY and AcZ)

The arrays are first defined globally as int16_t and later in loop() as float.

#include <Wire.h>
const int MPU_addrs[] = { 0x68, 0x69 };

float AcX[2], AcY[2], AcZ[2], Tmp[2]; // definition of variables

void setup()
{
  for(byte b=0; b<2; b++)
  {
    Wire.begin();
    Wire.beginTransmission(MPU_addrs[b]);
    Wire.write(0x6B);  // PWR_MGMT_1 register
    Wire.write(0);     // set to zero (wakes up the MPU-6050)
    Wire.endTransmission(true);
  }

  Serial.begin(9600);
}

void loop()
{
  for(byte b=0; b<2; b++)
  {
    Wire.beginTransmission(MPU_addrs[b]);
    Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);

    Wire.requestFrom(MPU_addrs[b], 8, true); // request a total of 8 registers
    AcX[b] = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
    AcY[b] = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
    AcZ[b] = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
    Tmp[b] = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)

    Serial.print("Data from sensor ");
    Serial.println(b);

    Serial.print(AcX[b] / 16384);
    Serial.print(" ");
    Serial.print(AcY[b] / 16384);
    Serial.print(" ");
    Serial.print(AcZ[b] / 16384);
    Serial.print(" ");
    Serial.println(Tmp[b] / 340.00 + 36.53);
  }
}

The arrays are first defined globally as int16_t and later in loop() as float.

Who wrote that crappy code?