2

I am trying to interface MPU6050 with arduino. Found a simple code online, but having a bit of trouble in interpreting it.

// MPU-6050 Short Example Sketch
// By Arduino User JohnChi
// August 17, 2014
// Public Domain
#include<Wire.h>
const int MPU=0x68;  // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
void setup(){
Wire.begin();
Wire.beginTransmission(MPU);
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);
Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU,14,true);  // request a total of 14 registers
AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C     (ACCEL_XOUT_L)     
AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
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)
GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
Serial.print("AcX = "); Serial.print(AcX);
Serial.print(" | AcY = "); Serial.print(AcY);
Serial.print(" | AcZ = "); Serial.print(AcZ);
Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53);  //equation for   temperature in degrees C from datasheet
Serial.print(" | GyX = "); Serial.print(GyX);
Serial.print(" | GyY = "); Serial.print(GyY);
Serial.print(" | GyZ = "); Serial.println(GyZ);
delay(3330); 
}

Now there are a few things i want to ask regarding this code: 1. Here we have specified that the data from 3B register of the slave should be the first one and master will receive in total 14 bytes. In this case the 14 registers are continuous (see datasheet here) .Now how should i go about reading the values if i am interested in registers which are not continuous ,let us say alternative?

2.AcX=Wire.read()<<8|Wire.read();

This line is taking the first 8 bits and last 8 bits and forming a 16 bit number . But why do we need to shift the first 8-bits byte 8 places to left.Please explain how exactly this line works?

3
  • This code you found is very bad. Do not rely on it for your own developments. Specifically, there is no way to know which read() will be evaluated first in Wire.read()<<8|Wire.read(). Commented Jun 10, 2015 at 16:04
  • So can you please tell me how should i go about doing the same in a better way? Commented Jun 10, 2015 at 16:37
  • Take a look at FreeIMU - it has all the code you could ever want.
    – Majenko
    Commented Jun 10, 2015 at 17:36

1 Answer 1

1

For reading non-consecutive bytes, the “normal” way would be to do a one-byte request and a one-byte read for each byte you want. However, if the bytes you want are close enough (e.g. you want every other byte), it would be faster to do a contiguous read and just ignore the bytes you do not want. E.g.:

byte data1 = Wire.read();  // read first byte
Wire.read();               // read and ignore second byte
byte data3 = Wire.read();  // read third byte

For your question regarding the meaning of Wire.read()<<8|Wire.read();:

  1. Wire.read() return a 16-bit integer, where the 8 most significant bits are zero and the 8 least-significant bits contain the actual data. In binary, it's something like 00000000xxxxxxxx, where x are the data bits.
  2. <<8 means “shift left by eight positions”, where the missing bits are replaced by zeros. Thus Wire.read()<<8 is xxxxxxxx00000000 in binary.
  3. The second call to Wire.read() return another 16-bit integer in the form 00000000yyyyyyyy.
  4. The vertical bar | is the bitwise-or operator: each bit of the left operand is or-ed with the corresponding bit of the right operand to give one bit of the result: x or 0 is x, 0 or y is y.
  5. Then, the whole expression gives xxxxxxxxyyyyyyyy, where xxxxxxxx comes from the first Wire.read() and yyyyyyyy from the second.

The problem here is that the “first” and “second” Wire.read() in the sentence above refer to the position of the call in the line, not to the actual order in which the calls are performed. Thus you may be lucky and get the the correct byte order... or not. You should instead do a single read per statement if you want to control the byte order. For MSB first:

AcX = Wire.read() << 8;  // read most significant byte first
AcX |= Wire.read();      // then least significant byte

And for LSB first:

AcX = Wire.read();        // read least significant byte first
AcX |= Wire.read() << 8;  // then most significant byte
0

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.